1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-03 08:19:41 +00:00

windows.globalization: Implement ILanguage::get_LanguageTag().

This commit is contained in:
Nikolay Sivov 2023-01-19 21:22:36 +03:00 committed by Alexandre Julliard
parent 86fb17c8fb
commit c38aa80ed4
5 changed files with 390 additions and 4 deletions

View File

@ -20,4 +20,16 @@
#pragma makedep register
#ifdef __WIDL__
#pragma winrt ns_prefix
#endif
import "inspectable.idl";
import "asyncinfo.idl";
import "eventtoken.idl";
import "windowscontracts.idl";
import "windows.foundation.idl";
#define DO_NO_IMPORTS
#include "windows.globalization.idl"
#include "windows.system.userprofile.idl"

View File

@ -234,16 +234,156 @@ struct windows_globalization
LONG ref;
};
struct language_factory
{
IActivationFactory IActivationFactory_iface;
ILanguageFactory ILanguageFactory_iface;
LONG ref;
};
struct language
{
ILanguage ILanguage_iface;
LONG ref;
WCHAR name[LOCALE_NAME_MAX_LENGTH];
};
static inline struct windows_globalization *impl_from_IActivationFactory(IActivationFactory *iface)
{
return CONTAINING_RECORD(iface, struct windows_globalization, IActivationFactory_iface);
}
static inline struct language_factory *impl_language_factory_from_IActivationFactory(IActivationFactory *iface)
{
return CONTAINING_RECORD(iface, struct language_factory, IActivationFactory_iface);
}
static inline struct windows_globalization *impl_from_IGlobalizationPreferencesStatics(IGlobalizationPreferencesStatics *iface)
{
return CONTAINING_RECORD(iface, struct windows_globalization, IGlobalizationPreferencesStatics_iface);
}
static inline struct language_factory *impl_from_ILanguageFactory(ILanguageFactory *iface)
{
return CONTAINING_RECORD(iface, struct language_factory, ILanguageFactory_iface);
}
static inline struct language *impl_from_ILanguage(ILanguage *iface)
{
return CONTAINING_RECORD(iface, struct language, ILanguage_iface);
}
static HRESULT STDMETHODCALLTYPE language_QueryInterface(
ILanguage *iface, REFIID iid, void **out)
{
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_ILanguage))
{
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 language_AddRef(
ILanguage *iface)
{
struct language *language = impl_from_ILanguage(iface);
ULONG ref = InterlockedIncrement(&language->ref);
TRACE("iface %p, ref %lu.\n", iface, ref);
return ref;
}
static ULONG STDMETHODCALLTYPE language_Release(
ILanguage *iface)
{
struct language *language = impl_from_ILanguage(iface);
ULONG ref = InterlockedDecrement(&language->ref);
TRACE("iface %p, ref %lu.\n", iface, ref);
if (!ref)
free(language);
return ref;
}
static HRESULT STDMETHODCALLTYPE language_GetIids(
ILanguage *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 language_GetRuntimeClassName(
ILanguage *iface, HSTRING *class_name)
{
FIXME("iface %p, class_name %p stub!\n", iface, class_name);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE language_GetTrustLevel(
ILanguage *iface, TrustLevel *trust_level)
{
FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE language_get_LanguageTag(
ILanguage *iface, HSTRING *value)
{
struct language *language = impl_from_ILanguage(iface);
TRACE("iface %p, value %p.\n", iface, value);
return WindowsCreateString(language->name, wcslen(language->name), value);
}
static HRESULT STDMETHODCALLTYPE language_get_DisplayName(
ILanguage *iface, HSTRING *value)
{
FIXME("iface %p, value %p stub!\n", iface, value);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE language_get_NativeName(
ILanguage *iface, HSTRING *value)
{
FIXME("iface %p, value %p stub!\n", iface, value);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE language_get_Script(
ILanguage *iface, HSTRING *value)
{
FIXME("iface %p, value %p stub!\n", iface, value);
return E_NOTIMPL;
}
static const struct ILanguageVtbl language_vtbl =
{
language_QueryInterface,
language_AddRef,
language_Release,
/* IInspectable methods */
language_GetIids,
language_GetRuntimeClassName,
language_GetTrustLevel,
/* ILanguage methods */
language_get_LanguageTag,
language_get_DisplayName,
language_get_NativeName,
language_get_Script,
};
static HRESULT STDMETHODCALLTYPE windows_globalization_QueryInterface(
IActivationFactory *iface, REFIID iid, void **out)
{
@ -454,13 +594,141 @@ static const struct IGlobalizationPreferencesStaticsVtbl globalization_preferenc
globalization_preferences_get_WeekStartsOn,
};
static struct windows_globalization windows_globalization =
static struct windows_globalization userprofile_preferences =
{
{&activation_factory_vtbl},
{&globalization_preferences_vtbl},
0
};
static HRESULT STDMETHODCALLTYPE windows_globalization_language_factory_QueryInterface(
IActivationFactory *iface, REFIID iid, void **out)
{
struct language_factory *factory = impl_language_factory_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;
}
if (IsEqualGUID(iid, &IID_ILanguageFactory))
{
IUnknown_AddRef(iface);
*out = &factory->ILanguageFactory_iface;
return S_OK;
}
FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
*out = NULL;
return E_NOINTERFACE;
}
static const struct IActivationFactoryVtbl activation_factory_language_vtbl =
{
windows_globalization_language_factory_QueryInterface,
windows_globalization_AddRef,
windows_globalization_Release,
/* IInspectable methods */
windows_globalization_GetIids,
windows_globalization_GetRuntimeClassName,
windows_globalization_GetTrustLevel,
/* IActivationFactory methods */
windows_globalization_ActivateInstance,
};
static HRESULT STDMETHODCALLTYPE language_factory_QueryInterface(
ILanguageFactory *iface, REFIID iid, void **object)
{
struct language_factory *factory = impl_from_ILanguageFactory(iface);
return IActivationFactory_QueryInterface(&factory->IActivationFactory_iface, iid, object);
}
static ULONG STDMETHODCALLTYPE language_factory_AddRef(
ILanguageFactory *iface)
{
struct language_factory *factory = impl_from_ILanguageFactory(iface);
return IActivationFactory_AddRef(&factory->IActivationFactory_iface);
}
static ULONG STDMETHODCALLTYPE language_factory_Release(
ILanguageFactory *iface)
{
struct language_factory *factory = impl_from_ILanguageFactory(iface);
return IActivationFactory_Release(&factory->IActivationFactory_iface);
}
static HRESULT STDMETHODCALLTYPE language_factory_GetIids(
ILanguageFactory *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 language_factory_GetRuntimeClassName(
ILanguageFactory *iface, HSTRING *class_name)
{
FIXME("iface %p, class_name %p stub!\n", iface, class_name);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE language_factory_GetTrustLevel(
ILanguageFactory *iface, TrustLevel *trust_level)
{
FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE language_factory_CreateLanguage(
ILanguageFactory *iface, HSTRING tag, ILanguage **value)
{
const WCHAR *name = WindowsGetStringRawBuffer(tag, NULL);
WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
struct language *language;
TRACE("iface %p, tag %p, value %p.\n", iface, tag, value);
if (!GetLocaleInfoEx(name, LOCALE_SNAME, buffer, ARRAY_SIZE(buffer)))
return E_INVALIDARG;
if (!(language = calloc(1, sizeof(*language))))
return E_OUTOFMEMORY;
language->ILanguage_iface.lpVtbl = &language_vtbl;
language->ref = 1;
wcscpy(language->name, buffer);
*value = &language->ILanguage_iface;
return S_OK;
}
static const struct ILanguageFactoryVtbl language_factory_vtbl =
{
language_factory_QueryInterface,
language_factory_AddRef,
language_factory_Release,
/* IInspectable methods */
language_factory_GetIids,
language_factory_GetRuntimeClassName,
language_factory_GetTrustLevel,
/* ILanguageFactory methods */
language_factory_CreateLanguage,
};
static struct language_factory language_factory =
{
{&activation_factory_language_vtbl},
{&language_factory_vtbl},
0
};
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);
@ -469,8 +737,23 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out)
HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory)
{
const WCHAR *name = WindowsGetStringRawBuffer(classid, NULL);
TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
*factory = &windows_globalization.IActivationFactory_iface;
IUnknown_AddRef(*factory);
return S_OK;
*factory = NULL;
if (!wcscmp(name, RuntimeClass_Windows_System_UserProfile_GlobalizationPreferences))
{
*factory = &userprofile_preferences.IActivationFactory_iface;
IUnknown_AddRef(*factory);
}
else if (!wcscmp(name, RuntimeClass_Windows_Globalization_Language))
{
*factory = &language_factory.IActivationFactory_iface;
IUnknown_AddRef(*factory);
}
if (*factory) return S_OK;
return CLASS_E_CLASSNOTAVAILABLE;
}

View File

@ -29,6 +29,8 @@
#define WIDL_using_Windows_Foundation
#define WIDL_using_Windows_Foundation_Collections
#include "windows.foundation.h"
#define WIDL_using_Windows_Globalization
#include "windows.globalization.h"
#define WIDL_using_Windows_System_UserProfile
#include "windows.system.userprofile.h"
@ -227,6 +229,90 @@ static void test_GlobalizationPreferences(void)
RoUninitialize();
}
static void test_Language(void)
{
static const WCHAR *class_name = L"Windows.Globalization.Language";
IAgileObject *agile_object, *tmp_agile_object;
IInspectable *inspectable, *tmp_inspectable;
WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
ILanguageFactory *language_factory;
IActivationFactory *factory;
ILanguage *language;
HSTRING tag, str;
const WCHAR *buf;
HRESULT hr;
hr = RoInitialize(RO_INIT_MULTITHREADED);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = WindowsCreateString(class_name, wcslen(class_name), &str);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "Unexpected 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, "Unexpected hr %#lx.\n", hr);
hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IActivationFactory_QueryInterface(factory, &IID_ILanguageFactory, (void **)&language_factory);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = ILanguageFactory_QueryInterface(language_factory, &IID_IInspectable, (void **)&tmp_inspectable);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(tmp_inspectable == inspectable, "Unexpected interface pointer %p, expected %p.\n", tmp_inspectable, inspectable);
IInspectable_Release(tmp_inspectable);
hr = ILanguageFactory_QueryInterface(language_factory, &IID_IAgileObject, (void **)&tmp_agile_object);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(tmp_agile_object == agile_object, "Unexpected interface pointer %p, expected %p.\n", tmp_agile_object, agile_object);
IAgileObject_Release(tmp_agile_object);
/* Invalid language tag */
hr = WindowsCreateString(L"test-tag", 8, &str);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = ILanguageFactory_CreateLanguage(language_factory, str, &language);
ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
ILanguage_Release(language);
WindowsDeleteString(str);
hr = WindowsCreateString(L"en-us", 5, &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_get_LanguageTag(language, &tag);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
buf = WindowsGetStringRawBuffer(tag, NULL);
ok(!wcscmp(buf, L"en-US"), "Unexpected tag %s.\n", debugstr_w(buf));
GetLocaleInfoEx(L"en-us", LOCALE_SNAME, buffer, ARRAY_SIZE(buffer));
ok(!wcscmp(buf, buffer), "Unexpected tag %s, locale name %s.\n", debugstr_w(buf), debugstr_w(buffer));
WindowsDeleteString(tag);
ILanguage_Release(language);
ILanguageFactory_Release(language_factory);
IAgileObject_Release(agile_object);
IInspectable_Release(inspectable);
IActivationFactory_Release(factory);
RoUninitialize();
}
START_TEST(globalization)
{
HMODULE kernel32;
@ -235,4 +321,5 @@ START_TEST(globalization)
pGetUserDefaultGeoName = (void*)GetProcAddress(kernel32, "GetUserDefaultGeoName");
test_GlobalizationPreferences();
test_Language();
}

View File

@ -20,11 +20,13 @@
#pragma winrt ns_prefix
#endif
#ifndef DO_NO_IMPORTS
import "inspectable.idl";
import "asyncinfo.idl";
import "eventtoken.idl";
import "windowscontracts.idl";
import "windows.foundation.idl";
#endif
namespace Windows {
namespace Globalization {

View File

@ -20,12 +20,14 @@
#pragma winrt ns_prefix
#endif
#ifndef DO_NO_IMPORTS
import "inspectable.idl";
import "asyncinfo.idl";
import "eventtoken.idl";
import "windowscontracts.idl";
import "windows.foundation.idl";
import "windows.globalization.idl";
#endif
namespace Windows {
namespace System {