This is an undocumented API used by some programs to fetch the user's selected languages.
Example is Fusion360 (during its login process).
Signature currently taken from here: https://stackoverflow.com/questions/63877075/what-is-the-right-way-to-get-th... (Maybe that stackoverflow answer is also why Fusion has implemented this...)
-- v10: bcp47langs: Implement GetUserLanguages
From: Marius Schiffer marius@mschiffer.de
Implement an undocumented API used by some programs to fetch the user's selected languages. Returns only english as the language.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56915 --- configure.ac | 1 + dlls/bcp47langs/Makefile.in | 4 ++++ dlls/bcp47langs/bcp47langs.spec | 2 +- dlls/bcp47langs/main.c | 13 +++++++++++ dlls/bcp47langs/tests/Makefile.in | 6 +++++ dlls/bcp47langs/tests/bcp47langs.c | 22 +++++++++++++++++++ include/Makefile.in | 1 + include/bcp47langs.h | 35 ++++++++++++++++++++++++++++++ 8 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 dlls/bcp47langs/main.c create mode 100644 dlls/bcp47langs/tests/Makefile.in create mode 100644 dlls/bcp47langs/tests/bcp47langs.c create mode 100644 include/bcp47langs.h
diff --git a/configure.ac b/configure.ac index 23d3f8fbc49..70b607c7427 100644 --- a/configure.ac +++ b/configure.ac @@ -2461,6 +2461,7 @@ WINE_CONFIG_MAKEFILE(dlls/avifil32/tests) WINE_CONFIG_MAKEFILE(dlls/avifile.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/avrt) WINE_CONFIG_MAKEFILE(dlls/bcp47langs) +WINE_CONFIG_MAKEFILE(dlls/bcp47langs/tests) WINE_CONFIG_MAKEFILE(dlls/bcrypt) WINE_CONFIG_MAKEFILE(dlls/bcrypt/tests) WINE_CONFIG_MAKEFILE(dlls/bcryptprimitives) diff --git a/dlls/bcp47langs/Makefile.in b/dlls/bcp47langs/Makefile.in index 5eb4caaf0e7..dfe10916951 100644 --- a/dlls/bcp47langs/Makefile.in +++ b/dlls/bcp47langs/Makefile.in @@ -1,2 +1,6 @@ MODULE = bcp47langs.dll IMPORTLIB = bcp47langs +IMPORTS = combase + +SOURCES = \ + main.c diff --git a/dlls/bcp47langs/bcp47langs.spec b/dlls/bcp47langs/bcp47langs.spec index a054c1486a9..969f77b56b8 100644 --- a/dlls/bcp47langs/bcp47langs.spec +++ b/dlls/bcp47langs/bcp47langs.spec @@ -48,7 +48,7 @@ @ stub GetUserDisplayLanguageOverride @ stub GetUserLanguageInputMethods @ stub GetUserLanguageInputMethodsForUser -@ stub GetUserLanguages +@ stdcall GetUserLanguages(long ptr) @ stub GetUserLanguagesForAllUsers @ stub GetUserLanguagesForUser @ stub GetUserLocaleFromLanguageProfileOptOut diff --git a/dlls/bcp47langs/main.c b/dlls/bcp47langs/main.c new file mode 100644 index 00000000000..9c5639245a6 --- /dev/null +++ b/dlls/bcp47langs/main.c @@ -0,0 +1,13 @@ +#include <hstring.h> +#include <winstring.h> + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(bcp47langs); + +DWORD WINAPI GetUserLanguages(char delimiter, HSTRING *user_languages) { + static const LPCWSTR languages = L"en-US"; + FIXME("stub, only returning en-us\n"); + WindowsCreateString(languages, wcslen(languages), user_languages); + return 0; +} diff --git a/dlls/bcp47langs/tests/Makefile.in b/dlls/bcp47langs/tests/Makefile.in new file mode 100644 index 00000000000..498e1b34afe --- /dev/null +++ b/dlls/bcp47langs/tests/Makefile.in @@ -0,0 +1,6 @@ +TESTDLL = bcp47langs.dll +IMPORTS = bcp47langs msvcrt combase + +SOURCES = \ + bcp47langs.c + diff --git a/dlls/bcp47langs/tests/bcp47langs.c b/dlls/bcp47langs/tests/bcp47langs.c new file mode 100644 index 00000000000..76a21b12759 --- /dev/null +++ b/dlls/bcp47langs/tests/bcp47langs.c @@ -0,0 +1,22 @@ +#include <wine/test.h> +#include <winbase.h> + +#include "winstring.h" +#include "msvcrt/locale.h" +#include "bcp47langs.h" + +static void test_get_user_languages(void) +{ + HSTRING result; + const WCHAR *user_languages; + + setlocale(LC_ALL, "enu"); + ok( GetUserLanguages(',', &result) == 0, "unknown return code\n" ); + user_languages = WindowsGetStringRawBuffer(result, NULL); + ok( !lstrcmpW(user_languages, L"en-US"), "languages=%s\n", debugstr_w(user_languages) ); +} + +START_TEST(bcp47langs) +{ + test_get_user_languages(); +} diff --git a/include/Makefile.in b/include/Makefile.in index bbf28cfc87e..09259692949 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -45,6 +45,7 @@ SOURCES = \ axextendenums.h \ basetsd.h \ basetyps.h \ + bcp47langs.h \ bcrypt.h \ bdaiface.idl \ bdaiface_enums.h \ diff --git a/include/bcp47langs.h b/include/bcp47langs.h new file mode 100644 index 00000000000..2a99cc71d37 --- /dev/null +++ b/include/bcp47langs.h @@ -0,0 +1,35 @@ +/* + * bcp47langs definitions + * + * Copyright 2024 Marius Schiffer + * + * 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 _BCP47LANGS_ +#define _BCP47LANGS_ + +#ifdef __cplusplus +extern "C" { +#endif + +DWORD WINAPI GetUserLanguages(char delimiter, HSTRING *user_languages); + +#ifdef __cplusplus +} +#endif + +#endif /*_BCP47LANGS__*/
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147298
Your paranoid android.
=== w10pro64_en_AE_u8 (32 bit report) ===
bcp47langs: bcp47langs.c:16: Test failed: languages=L"en-US,en-CA,en-GB,en-AE,fr-FR,fr-CA,de-DE,es-ES,he,hi,ar-EG,ar-MA,ja,ko,pt-BR,pt-PT,zh-Hans-CN,ru,hy"
=== w10pro64_ar (64 bit report) ===
bcp47langs: bcp47langs.c:16: Test failed: languages=L"en-US,en-CA,en-GB,en-AE,fr-FR,fr-CA,de-DE,es-ES,he,hi,ar-EG,ar-MA,ja,ko,pt-BR,pt-PT,zh-Hans-CN,ru,hy"
=== w10pro64_ja (64 bit report) ===
bcp47langs: bcp47langs.c:16: Test failed: languages=L"en-US,en-CA,en-GB,en-AE,fr-FR,fr-CA,de-DE,es-ES,he,hi,ar-EG,ar-MA,ja,ko,pt-BR,pt-PT,zh-Hans-CN,ru,hy"
=== w10pro64_zh_CN (64 bit report) ===
bcp47langs: bcp47langs.c:16: Test failed: languages=L"en-US,en-CA,en-GB,en-AE,fr-FR,fr-CA,de-DE,es-ES,he,hi,ar-EG,ar-MA,ja,ko,pt-BR,pt-PT,zh-Hans-CN,ru,hy"
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000005C00E8, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/tests/Makefile.in:
+TESTDLL = bcp47langs.dll
Let's rename the commit subject to "bcp47langs: Add GetUserLanguages() stub."
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/tests/bcp47langs.c:
+#include <wine/test.h>
Add an LGPL license header. See other test files for example.
And <wine/test.h> is usually at the end of include list.
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/tests/bcp47langs.c:
+#include <wine/test.h> +#include <winbase.h>
+#include "winstring.h" +#include "msvcrt/locale.h" +#include "bcp47langs.h"
+static void test_get_user_languages(void)
Let use test_GetUserLanguages().
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/tests/bcp47langs.c:
+#include <wine/test.h> +#include <winbase.h>
+#include "winstring.h" +#include "msvcrt/locale.h" +#include "bcp47langs.h"
+static void test_get_user_languages(void) +{
- HSTRING result;
- const WCHAR *user_languages;
- setlocale(LC_ALL, "enu");
- ok( GetUserLanguages(',', &result) == 0, "unknown return code\n" );
Let's remove the spaces inside the parenthesis for ok.
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/tests/bcp47langs.c:
+#include <wine/test.h> +#include <winbase.h>
+#include "winstring.h" +#include "msvcrt/locale.h" +#include "bcp47langs.h"
+static void test_get_user_languages(void) +{
- HSTRING result;
- const WCHAR *user_languages;
- setlocale(LC_ALL, "enu");
I think it wouldn't be too difficult to test other locales and add support for them as well.
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/tests/bcp47langs.c:
+#include <wine/test.h> +#include <winbase.h>
+#include "winstring.h" +#include "msvcrt/locale.h" +#include "bcp47langs.h"
+static void test_get_user_languages(void) +{
- HSTRING result;
- const WCHAR *user_languages;
- setlocale(LC_ALL, "enu");
- ok( GetUserLanguages(',', &result) == 0, "unknown return code\n" );
- user_languages = WindowsGetStringRawBuffer(result, NULL);
I think you need to free result by calling WindowsDeleteString().
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/main.c:
+#include <hstring.h>
winstring.h already includes hstring.h.
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/main.c:
+#include <hstring.h> +#include <winstring.h>
+#include "wine/debug.h"
+WINE_DEFAULT_DEBUG_CHANNEL(bcp47langs);
+DWORD WINAPI GetUserLanguages(char delimiter, HSTRING *user_languages) {
The prototype is probably HRESULT WINAPI GetUserLanguages(WCHAR delimiter, HSTRING *user_languages). So the return value should be S_OK. You can add some parameter tests, for example, by passing NULL to user_languages and see if the return value is something like E_INVALIDARG.
For delimiter, it's most likely a WCHAR. This can be verified by passing a Unicode char to delimiter and check the result string.
And move { to a new line. Add a newline after variable declaration.
Zhiyi Zhang (@zhiyi) commented about include/bcp47langs.h:
- */
+#ifndef _BCP47LANGS_ +#define _BCP47LANGS_
+#ifdef __cplusplus +extern "C" { +#endif
+DWORD WINAPI GetUserLanguages(char delimiter, HSTRING *user_languages);
+#ifdef __cplusplus +} +#endif
+#endif /*_BCP47LANGS__*/
Add some after /* and before */. And _BCP47LANGS__ has two underscores at the end.
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/main.c:
+#include <hstring.h> +#include <winstring.h>
+#include "wine/debug.h"
+WINE_DEFAULT_DEBUG_CHANNEL(bcp47langs);
+DWORD WINAPI GetUserLanguages(char delimiter, HSTRING *user_languages) {
- static const LPCWSTR languages = L"en-US";
- FIXME("stub, only returning en-us\n");
Try to implement this properly for other locales as well.
Zhiyi Zhang (@zhiyi) commented about dlls/bcp47langs/main.c:
+#include <hstring.h> +#include <winstring.h>
+#include "wine/debug.h"
+WINE_DEFAULT_DEBUG_CHANNEL(bcp47langs);
+DWORD WINAPI GetUserLanguages(char delimiter, HSTRING *user_languages) {
- static const LPCWSTR languages = L"en-US";
- FIXME("stub, only returning en-us\n");
Add some parameter checks. For example, user_languages being NULL.
On Wed Sep 4 09:26:13 2024 +0000, Zhiyi Zhang wrote:
Let's rename the commit subject to "bcp47langs: Add GetUserLanguages() stub."
And the commit message body line width limit can be larger, like 80 or 100.