Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
7ac7a902
Commit
7ac7a902
authored
Nov 19, 2019
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Implement RtlLocaleNameToLcid().
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
4538a137
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
221 additions
and
5 deletions
+221
-5
locale.c
dlls/kernel32/tests/locale.c
+74
-5
loader.c
dlls/ntdll/loader.c
+2
-0
locale.c
dlls/ntdll/locale.c
+142
-0
ntdll.spec
dlls/ntdll/ntdll.spec
+1
-0
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+1
-0
winternl.h
include/winternl.h
+1
-0
No files found.
dlls/kernel32/tests/locale.c
View file @
7ac7a902
...
...
@@ -30,11 +30,14 @@
#include <stdarg.h>
#include <stdio.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#include "winternl.h"
static
const
WCHAR
upper_case
[]
=
{
'\t'
,
'J'
,
'U'
,
'S'
,
'T'
,
'!'
,
' '
,
'A'
,
','
,
' '
,
'T'
,
'E'
,
'S'
,
'T'
,
';'
,
' '
,
'S'
,
'T'
,
'R'
,
'I'
,
'N'
,
'G'
,
' '
,
'1'
,
'/'
,
'*'
,
'+'
,
'-'
,
'.'
,
'\r'
,
'\n'
,
0
};
static
const
WCHAR
lower_case
[]
=
{
'\t'
,
'j'
,
'u'
,
's'
,
't'
,
'!'
,
' '
,
'a'
,
','
,
' '
,
't'
,
'e'
,
's'
,
't'
,
';'
,
' '
,
's'
,
't'
,
'r'
,
'i'
,
'n'
,
'g'
,
' '
,
'1'
,
'/'
,
'*'
,
'+'
,
'-'
,
'.'
,
'\r'
,
'\n'
,
0
};
...
...
@@ -83,6 +86,7 @@ static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROCA, DWORD, LONG_PTR);
static
BOOL
(
WINAPI
*
pEnumSystemLocalesEx
)(
LOCALE_ENUMPROCEX
,
DWORD
,
LPARAM
,
LPVOID
);
static
INT
(
WINAPI
*
pLCMapStringEx
)(
LPCWSTR
,
DWORD
,
LPCWSTR
,
INT
,
LPWSTR
,
INT
,
LPNLSVERSIONINFO
,
LPVOID
,
LPARAM
);
static
LCID
(
WINAPI
*
pLocaleNameToLCID
)(
LPCWSTR
,
DWORD
);
static
NTSTATUS
(
WINAPI
*
pRtlLocaleNameToLcid
)(
LPCWSTR
,
LCID
*
,
DWORD
);
static
INT
(
WINAPI
*
pLCIDToLocaleName
)(
LCID
,
LPWSTR
,
INT
,
DWORD
);
static
INT
(
WINAPI
*
pFoldStringA
)(
DWORD
,
LPCSTR
,
INT
,
LPSTR
,
INT
);
static
INT
(
WINAPI
*
pFoldStringW
)(
DWORD
,
LPCWSTR
,
INT
,
LPWSTR
,
INT
);
...
...
@@ -148,6 +152,7 @@ static void InitFunctionPointers(void)
mod
=
GetModuleHandleA
(
"ntdll"
);
X
(
RtlUpcaseUnicodeChar
);
X
(
RtlLocaleNameToLcid
);
#undef X
}
...
...
@@ -2792,9 +2797,12 @@ static const struct neutralsublang_name_t neutralsublang_names[] = {
static
void
test_LocaleNameToLCID
(
void
)
{
LCID
lcid
;
LCID
lcid
,
expect
;
NTSTATUS
status
;
INT
ret
;
WCHAR
buffer
[
LOCALE_NAME_MAX_LENGTH
];
const
struct
neutralsublang_name_t
*
ptr
;
static
const
WCHAR
enW
[]
=
{
'e'
,
'n'
,
0
};
static
const
WCHAR
esesW
[]
=
{
'e'
,
's'
,
'-'
,
'e'
,
's'
,
0
};
static
const
WCHAR
zhHansW
[]
=
{
'z'
,
'h'
,
'-'
,
'H'
,
'a'
,
'n'
,
's'
,
0
};
...
...
@@ -2853,9 +2861,7 @@ static void test_LocaleNameToLCID(void)
broken
(
lcid
==
0
)
/* Vista */
,
"got 0x%04x
\n
"
,
lcid
);
if
(
lcid
)
{
const
struct
neutralsublang_name_t
*
ptr
=
neutralsublang_names
;
while
(
*
ptr
->
name
)
for
(
ptr
=
neutralsublang_names
;
*
ptr
->
name
;
ptr
++
)
{
lcid
=
pLocaleNameToLCID
(
ptr
->
name
,
0
);
todo_wine_if
(
ptr
->
todo
)
...
...
@@ -2868,7 +2874,6 @@ static void test_LocaleNameToLCID(void)
ok
(
!
lstrcmpW
(
ptr
->
sname
,
buffer
),
"%s: got wrong locale name %s
\n
"
,
wine_dbgstr_w
(
ptr
->
name
),
wine_dbgstr_w
(
buffer
));
ptr
++
;
}
/* zh-Hant has LCID 0x7c04, but LocaleNameToLCID actually returns 0x0c04, which is the LCID of zh-HK */
...
...
@@ -2919,6 +2924,70 @@ static void test_LocaleNameToLCID(void)
ok
(
!
lstrcmpW
(
zhcnW
,
buffer
),
"%s: got wrong locale name %s
\n
"
,
wine_dbgstr_w
(
zhhansW
),
wine_dbgstr_w
(
buffer
));
}
if
(
pRtlLocaleNameToLcid
)
{
status
=
pRtlLocaleNameToLcid
(
LOCALE_NAME_USER_DEFAULT
,
&
lcid
,
0
);
ok
(
status
==
STATUS_INVALID_PARAMETER_1
,
"wrong error %x
\n
"
,
status
);
status
=
pRtlLocaleNameToLcid
(
LOCALE_NAME_SYSTEM_DEFAULT
,
&
lcid
,
0
);
ok
(
status
==
STATUS_INVALID_PARAMETER_1
,
"wrong error %x
\n
"
,
status
);
status
=
pRtlLocaleNameToLcid
(
invalidW
,
&
lcid
,
0
);
ok
(
status
==
STATUS_INVALID_PARAMETER_1
,
"wrong error %x
\n
"
,
status
);
lcid
=
0
;
status
=
pRtlLocaleNameToLcid
(
LOCALE_NAME_INVARIANT
,
&
lcid
,
0
);
ok
(
!
status
,
"failed error %x
\n
"
,
status
);
ok
(
lcid
==
LANG_INVARIANT
,
"got %08x
\n
"
,
lcid
);
lcid
=
0
;
status
=
pRtlLocaleNameToLcid
(
localeW
,
&
lcid
,
0
);
ok
(
!
status
,
"failed error %x
\n
"
,
status
);
ok
(
lcid
==
MAKELANGID
(
LANG_ENGLISH
,
SUBLANG_ENGLISH_US
),
"got %08x
\n
"
,
lcid
);
lcid
=
0
;
status
=
pRtlLocaleNameToLcid
(
esesW
,
&
lcid
,
0
);
ok
(
!
status
,
"failed error %x
\n
"
,
status
);
ok
(
lcid
==
MAKELANGID
(
LANG_SPANISH
,
SUBLANG_SPANISH_MODERN
),
"got %08x
\n
"
,
lcid
);
lcid
=
0
;
status
=
pRtlLocaleNameToLcid
(
enW
,
&
lcid
,
0
);
ok
(
status
==
STATUS_INVALID_PARAMETER_1
,
"wrong error %x
\n
"
,
status
);
status
=
pRtlLocaleNameToLcid
(
enW
,
&
lcid
,
1
);
ok
(
status
==
STATUS_INVALID_PARAMETER_1
,
"wrong error %x
\n
"
,
status
);
status
=
pRtlLocaleNameToLcid
(
enW
,
&
lcid
,
2
);
ok
(
!
status
,
"failed error %x
\n
"
,
status
);
ok
(
lcid
==
MAKELANGID
(
LANG_ENGLISH
,
SUBLANG_NEUTRAL
),
"got %08x
\n
"
,
lcid
);
status
=
pRtlLocaleNameToLcid
(
L"en-RR"
,
&
lcid
,
2
);
ok
(
status
==
STATUS_INVALID_PARAMETER_1
,
"wrong error %x
\n
"
,
status
);
status
=
pRtlLocaleNameToLcid
(
L"en-Latn-RR"
,
&
lcid
,
2
);
ok
(
status
==
STATUS_INVALID_PARAMETER_1
,
"wrong error %x
\n
"
,
status
);
for
(
ptr
=
neutralsublang_names
;
*
ptr
->
name
;
ptr
++
)
{
switch
(
LANGIDFROMLCID
(
ptr
->
lcid
))
{
case
MAKELANGID
(
LANG_SERBIAN
,
SUBLANG_SERBIAN_SERBIA_LATIN
):
expect
=
LANG_SERBIAN_NEUTRAL
;
break
;
case
MAKELANGID
(
LANG_SERBIAN
,
SUBLANG_SERBIAN_SERBIA_CYRILLIC
):
expect
=
0x6c1a
;
break
;
case
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_CHINESE_SIMPLIFIED
):
expect
=
0x7804
;
break
;
case
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_CHINESE_HONGKONG
):
expect
=
LANG_CHINESE_TRADITIONAL
;
break
;
default:
expect
=
MAKELANGID
(
PRIMARYLANGID
(
ptr
->
lcid
),
SUBLANG_NEUTRAL
);
break
;
}
status
=
pRtlLocaleNameToLcid
(
ptr
->
name
,
&
lcid
,
2
);
ok
(
!
status
||
broken
(
ptr
->
lcid
==
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_CHINESE_SIMPLIFIED
)),
/* vista */
"%s failed error %x
\n
"
,
wine_dbgstr_w
(
ptr
->
name
),
status
);
todo_wine_if
(
ptr
->
todo
)
if
(
!
status
)
ok
(
lcid
==
expect
,
"%s: got wrong lcid 0x%04x, expected 0x%04x
\n
"
,
wine_dbgstr_w
(
ptr
->
name
),
lcid
,
expect
);
status
=
pRtlLocaleNameToLcid
(
ptr
->
sname
,
&
lcid
,
0
);
ok
(
!
status
||
broken
(
ptr
->
lcid
==
MAKELANGID
(
LANG_SERBIAN
,
SUBLANG_SERBIAN_SERBIA_LATIN
)),
/* vista */
"%s failed error %x
\n
"
,
wine_dbgstr_w
(
ptr
->
name
),
status
);
todo_wine_if
(
ptr
->
todo
)
if
(
!
status
)
ok
(
lcid
==
ptr
->
lcid
,
"%s: got wrong lcid 0x%04x, expected 0x%04x
\n
"
,
wine_dbgstr_w
(
ptr
->
name
),
lcid
,
ptr
->
lcid
);
}
}
else
win_skip
(
"RtlLocaleNameToLcid not available
\n
"
);
}
/* this requires collation table patch to make it MS compatible */
...
...
dlls/ntdll/loader.c
View file @
7ac7a902
...
...
@@ -4281,6 +4281,8 @@ void __wine_process_init(void)
exit
(
1
);
}
init_locale
(
wm
->
ldr
.
BaseAddress
);
params
=
peb
->
ProcessParameters
;
if
(
!
(
status
=
load_dll
(
params
->
DllPath
.
Buffer
,
params
->
ImagePathName
.
Buffer
,
NULL
,
DONT_RESOLVE_DLL_REFERENCES
,
&
wm
)))
...
...
dlls/ntdll/locale.c
View file @
7ac7a902
...
...
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define NONAMELESSUNION
#include "config.h"
#include "wine/port.h"
...
...
@@ -37,8 +38,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(nls);
LCID
user_lcid
=
0
,
system_lcid
=
0
;
static
LANGID
user_ui_language
,
system_ui_language
;
static
HMODULE
kernel32_handle
;
static
const
union
cptable
*
unix_table
;
/* NULL if UTF8 */
static
NTSTATUS
load_string
(
ULONG
id
,
LANGID
lang
,
WCHAR
*
buffer
,
ULONG
len
)
{
const
IMAGE_RESOURCE_DATA_ENTRY
*
data
;
LDR_RESOURCE_INFO
info
;
NTSTATUS
status
;
WCHAR
*
p
;
int
i
;
info
.
Type
=
6
;
/* RT_STRING */
info
.
Name
=
(
id
>>
4
)
+
1
;
info
.
Language
=
lang
;
if
((
status
=
LdrFindResource_U
(
kernel32_handle
,
&
info
,
3
,
&
data
)))
return
status
;
p
=
(
WCHAR
*
)((
char
*
)
kernel32_handle
+
data
->
OffsetToData
);
for
(
i
=
0
;
i
<
(
id
&
0x0f
);
i
++
)
p
+=
*
p
+
1
;
if
(
*
p
>=
len
)
return
STATUS_BUFFER_TOO_SMALL
;
memcpy
(
buffer
,
p
+
1
,
*
p
*
sizeof
(
WCHAR
)
);
buffer
[
*
p
]
=
0
;
return
STATUS_SUCCESS
;
}
#if !defined(__APPLE__) && !defined(__ANDROID__)
/* these platforms always use UTF-8 */
/* charset to codepage map, sorted by name */
...
...
@@ -143,6 +166,12 @@ void init_unix_codepage(void) { }
#endif
/* __APPLE__ || __ANDROID__ */
void
init_locale
(
HMODULE
module
)
{
kernel32_handle
=
module
;
}
/******************************************************************
* ntdll_umbstowcs
*/
...
...
@@ -234,3 +263,116 @@ NTSTATUS WINAPI NtQueryInstallUILanguage( LANGID *lang )
*
lang
=
system_ui_language
;
return
STATUS_SUCCESS
;
}
/******************************************************************
* RtlLocaleNameToLcid (NTDLL.@)
*/
NTSTATUS
WINAPI
RtlLocaleNameToLcid
(
const
WCHAR
*
name
,
LCID
*
lcid
,
ULONG
flags
)
{
/* locale name format is: lang[-script][-country][_modifier] */
static
const
WCHAR
sepW
[]
=
{
'-'
,
'_'
,
0
};
const
IMAGE_RESOURCE_DIRECTORY
*
resdir
;
const
IMAGE_RESOURCE_DIRECTORY_ENTRY
*
et
;
LDR_RESOURCE_INFO
info
;
WCHAR
buf
[
LOCALE_NAME_MAX_LENGTH
];
WCHAR
lang
[
LOCALE_NAME_MAX_LENGTH
];
/* language ("en") (note: buffer contains the other strings too) */
WCHAR
*
country
=
NULL
;
/* country ("US") */
WCHAR
*
script
=
NULL
;
/* script ("Latn") */
WCHAR
*
p
;
int
i
;
if
(
!
name
)
return
STATUS_INVALID_PARAMETER_1
;
if
(
!
name
[
0
])
{
*
lcid
=
LANG_INVARIANT
;
goto
found
;
}
if
(
strlenW
(
name
)
>=
LOCALE_NAME_MAX_LENGTH
)
return
STATUS_INVALID_PARAMETER_1
;
strcpyW
(
lang
,
name
);
if
((
p
=
strpbrkW
(
lang
,
sepW
))
&&
*
p
==
'-'
)
{
*
p
++
=
0
;
country
=
p
;
if
((
p
=
strpbrkW
(
p
,
sepW
))
&&
*
p
==
'-'
)
{
*
p
++
=
0
;
script
=
country
;
country
=
p
;
p
=
strpbrkW
(
p
,
sepW
);
}
if
(
p
)
*
p
=
0
;
/* FIXME: modifier is ignored */
/* second value can be script or country, check length to resolve the ambiguity */
if
(
!
script
&&
strlenW
(
country
)
==
4
)
{
script
=
country
;
country
=
NULL
;
}
}
info
.
Type
=
6
;
/* RT_STRING */
info
.
Name
=
(
LOCALE_SNAME
>>
4
)
+
1
;
if
(
LdrFindResourceDirectory_U
(
kernel32_handle
,
&
info
,
2
,
&
resdir
))
return
STATUS_INVALID_PARAMETER_1
;
et
=
(
const
IMAGE_RESOURCE_DIRECTORY_ENTRY
*
)(
resdir
+
1
);
for
(
i
=
0
;
i
<
resdir
->
NumberOfNamedEntries
+
resdir
->
NumberOfIdEntries
;
i
++
)
{
LANGID
id
=
et
[
i
].
u
.
Id
;
if
(
PRIMARYLANGID
(
id
)
==
LANG_NEUTRAL
)
continue
;
if
(
!
load_string
(
LOCALE_SNAME
,
id
,
buf
,
ARRAY_SIZE
(
buf
)
)
&&
!
strcmpiW
(
name
,
buf
))
{
*
lcid
=
MAKELCID
(
id
,
SORT_DEFAULT
);
/* FIXME: handle sort order */
goto
found
;
}
if
(
load_string
(
LOCALE_SISO639LANGNAME
,
id
,
buf
,
ARRAY_SIZE
(
buf
)
)
||
strcmpiW
(
lang
,
buf
))
continue
;
if
(
script
)
{
unsigned
int
len
=
strlenW
(
script
);
if
(
load_string
(
LOCALE_SSCRIPTS
,
id
,
buf
,
ARRAY_SIZE
(
buf
)
))
continue
;
p
=
buf
;
while
(
*
p
)
{
if
(
!
strncmpiW
(
p
,
script
,
len
)
&&
(
!
p
[
len
]
||
p
[
len
]
==
';'
))
break
;
if
(
!
(
p
=
strchrW
(
p
,
';'
)))
break
;
p
++
;
}
if
(
!
p
||
!*
p
)
continue
;
}
if
(
!
country
&&
(
flags
&
2
))
{
if
(
!
script
)
id
=
MAKELANGID
(
PRIMARYLANGID
(
id
),
LANG_NEUTRAL
);
switch
(
id
)
{
case
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_NEUTRAL
):
case
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_CHINESE_SINGAPORE
):
*
lcid
=
MAKELCID
(
0x7804
,
SORT_DEFAULT
);
break
;
case
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_CHINESE_TRADITIONAL
):
case
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_CHINESE_MACAU
):
case
MAKELANGID
(
LANG_CHINESE
,
SUBLANG_CHINESE_HONGKONG
):
*
lcid
=
MAKELCID
(
0x7c04
,
SORT_DEFAULT
);
break
;
default:
*
lcid
=
MAKELANGID
(
PRIMARYLANGID
(
id
),
SUBLANG_NEUTRAL
);
break
;
}
goto
found
;
}
}
return
STATUS_INVALID_PARAMETER_1
;
found:
TRACE
(
"%s -> %04x
\n
"
,
debugstr_w
(
name
),
*
lcid
);
return
STATUS_SUCCESS
;
}
dlls/ntdll/ntdll.spec
View file @
7ac7a902
...
...
@@ -807,6 +807,7 @@
@ stdcall RtlLengthSecurityDescriptor(ptr)
@ stdcall RtlLengthSid(ptr)
@ stdcall RtlLocalTimeToSystemTime(ptr ptr)
@ stdcall RtlLocaleNameToLcid(wstr ptr long)
# @ stub RtlLockBootStatusData
@ stdcall RtlLockHeap(long)
# @ stub RtlLockMemoryStreamRegion
...
...
dlls/ntdll/ntdll_misc.h
View file @
7ac7a902
...
...
@@ -86,6 +86,7 @@ extern void virtual_init_threading(void) DECLSPEC_HIDDEN;
extern
void
fill_cpu_info
(
void
)
DECLSPEC_HIDDEN
;
extern
void
heap_set_debug_flags
(
HANDLE
handle
)
DECLSPEC_HIDDEN
;
extern
void
init_unix_codepage
(
void
)
DECLSPEC_HIDDEN
;
extern
void
init_locale
(
HMODULE
module
)
DECLSPEC_HIDDEN
;
extern
void
init_user_process_params
(
SIZE_T
data_size
)
DECLSPEC_HIDDEN
;
extern
char
**
build_envp
(
const
WCHAR
*
envW
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
restart_process
(
RTL_USER_PROCESS_PARAMETERS
*
params
,
NTSTATUS
status
)
DECLSPEC_HIDDEN
;
...
...
include/winternl.h
View file @
7ac7a902
...
...
@@ -2778,6 +2778,7 @@ NTSYSAPI DWORD WINAPI RtlLengthRequiredSid(DWORD);
NTSYSAPI
ULONG
WINAPI
RtlLengthSecurityDescriptor
(
PSECURITY_DESCRIPTOR
);
NTSYSAPI
DWORD
WINAPI
RtlLengthSid
(
PSID
);
NTSYSAPI
NTSTATUS
WINAPI
RtlLocalTimeToSystemTime
(
const
LARGE_INTEGER
*
,
PLARGE_INTEGER
);
NTSYSAPI
NTSTATUS
WINAPI
RtlLocaleNameToLcid
(
const
WCHAR
*
,
LCID
*
,
ULONG
);
NTSYSAPI
BOOLEAN
WINAPI
RtlLockHeap
(
HANDLE
);
NTSYSAPI
NTSTATUS
WINAPI
RtlLookupAtomInAtomTable
(
RTL_ATOM_TABLE
,
const
WCHAR
*
,
RTL_ATOM
*
);
NTSYSAPI
NTSTATUS
WINAPI
RtlMakeSelfRelativeSD
(
PSECURITY_DESCRIPTOR
,
PSECURITY_DESCRIPTOR
,
LPDWORD
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment