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
cd13557f
Commit
cd13557f
authored
Mar 02, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Reimplement IdnToNameprepUnicode() using the NLS normalization table.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
35c22385
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
90 additions
and
212 deletions
+90
-212
locale.c
dlls/kernel32/locale.c
+4
-206
locale.c
dlls/kernel32/tests/locale.c
+10
-6
locale.c
dlls/ntdll/locale.c
+74
-0
ntdll.spec
dlls/ntdll/ntdll.spec
+1
-0
winternl.h
include/winternl.h
+1
-0
No files found.
dlls/kernel32/locale.c
View file @
cd13557f
...
...
@@ -708,213 +708,11 @@ INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeCha
/******************************************************************************
* IdnToNameprepUnicode (KERNEL32.@)
*/
INT
WINAPI
IdnToNameprepUnicode
(
DWORD
dwFlags
,
LPCWSTR
lpUnicodeCharStr
,
INT
cchUnicodeChar
,
LPWSTR
lpNameprepCharStr
,
INT
cchNameprepChar
)
INT
WINAPI
IdnToNameprepUnicode
(
DWORD
flags
,
const
WCHAR
*
src
,
INT
srclen
,
WCHAR
*
dst
,
INT
dstlen
)
{
enum
{
UNASSIGNED
=
0x1
,
PROHIBITED
=
0x2
,
BIDI_RAL
=
0x4
,
BIDI_L
=
0x8
};
const
WCHAR
*
ptr
;
WORD
flags
;
WCHAR
buf
[
64
],
*
map_str
,
norm_str
[
64
],
ch
;
DWORD
i
,
map_len
,
norm_len
,
mask
,
label_start
,
label_end
,
out
=
0
;
BOOL
have_bidi_ral
,
prohibit_bidi_ral
,
ascii_only
;
TRACE
(
"%x %p %d %p %d
\n
"
,
dwFlags
,
lpUnicodeCharStr
,
cchUnicodeChar
,
lpNameprepCharStr
,
cchNameprepChar
);
if
(
dwFlags
&
~
(
IDN_ALLOW_UNASSIGNED
|
IDN_USE_STD3_ASCII_RULES
))
{
SetLastError
(
ERROR_INVALID_FLAGS
);
return
0
;
}
if
(
!
lpUnicodeCharStr
||
cchUnicodeChar
<-
1
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
if
(
cchUnicodeChar
==
-
1
)
cchUnicodeChar
=
strlenW
(
lpUnicodeCharStr
)
+
1
;
if
(
!
cchUnicodeChar
||
(
cchUnicodeChar
==
1
&&
lpUnicodeCharStr
[
0
]
==
0
))
{
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
for
(
label_start
=
0
;
label_start
<
cchUnicodeChar
;)
{
ascii_only
=
TRUE
;
for
(
i
=
label_start
;
i
<
cchUnicodeChar
;
i
++
)
{
ch
=
lpUnicodeCharStr
[
i
];
if
(
i
!=
cchUnicodeChar
-
1
&&
!
ch
)
{
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
/* check if ch is one of label separators defined in RFC3490 */
if
(
!
ch
||
ch
==
'.'
||
ch
==
0x3002
||
ch
==
0xff0e
||
ch
==
0xff61
)
break
;
if
(
ch
>
0x7f
)
{
ascii_only
=
FALSE
;
continue
;
}
if
((
dwFlags
&
IDN_USE_STD3_ASCII_RULES
)
==
0
)
continue
;
if
((
ch
>=
'a'
&&
ch
<=
'z'
)
||
(
ch
>=
'A'
&&
ch
<=
'Z'
)
||
(
ch
>=
'0'
&&
ch
<=
'9'
)
||
ch
==
'-'
)
continue
;
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
label_end
=
i
;
/* last label may be empty */
if
(
label_start
==
label_end
&&
ch
)
{
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
if
((
dwFlags
&
IDN_USE_STD3_ASCII_RULES
)
&&
(
lpUnicodeCharStr
[
label_start
]
==
'-'
||
lpUnicodeCharStr
[
label_end
-
1
]
==
'-'
))
{
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
if
(
ascii_only
)
{
/* maximal label length is 63 characters */
if
(
label_end
-
label_start
>
63
)
{
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
if
(
label_end
<
cchUnicodeChar
)
label_end
++
;
if
(
!
lpNameprepCharStr
)
{
out
+=
label_end
-
label_start
;
}
else
if
(
out
+
label_end
-
label_start
<=
cchNameprepChar
)
{
memcpy
(
lpNameprepCharStr
+
out
,
lpUnicodeCharStr
+
label_start
,
(
label_end
-
label_start
)
*
sizeof
(
WCHAR
));
if
(
lpUnicodeCharStr
[
label_end
-
1
]
>
0x7f
)
lpNameprepCharStr
[
out
+
label_end
-
label_start
-
1
]
=
'.'
;
out
+=
label_end
-
label_start
;
}
else
{
SetLastError
(
ERROR_INSUFFICIENT_BUFFER
);
return
0
;
}
label_start
=
label_end
;
continue
;
}
map_len
=
0
;
for
(
i
=
label_start
;
i
<
label_end
;
i
++
)
{
ch
=
lpUnicodeCharStr
[
i
];
ptr
=
nameprep_mapping
+
nameprep_mapping
[
ch
>>
8
];
ptr
=
nameprep_mapping
+
ptr
[(
ch
>>
4
)
&
0x0f
]
+
3
*
(
ch
&
0x0f
);
if
(
!
ptr
[
0
])
map_len
++
;
else
if
(
!
ptr
[
1
])
map_len
++
;
else
if
(
!
ptr
[
2
])
map_len
+=
2
;
else
if
(
ptr
[
0
]
!=
0xffff
||
ptr
[
1
]
!=
0xffff
||
ptr
[
2
]
!=
0xffff
)
map_len
+=
3
;
}
if
(
map_len
*
sizeof
(
WCHAR
)
>
sizeof
(
buf
))
{
map_str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
map_len
*
sizeof
(
WCHAR
));
if
(
!
map_str
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
}
else
{
map_str
=
buf
;
}
map_len
=
0
;
for
(
i
=
label_start
;
i
<
label_end
;
i
++
)
{
ch
=
lpUnicodeCharStr
[
i
];
ptr
=
nameprep_mapping
+
nameprep_mapping
[
ch
>>
8
];
ptr
=
nameprep_mapping
+
ptr
[(
ch
>>
4
)
&
0x0f
]
+
3
*
(
ch
&
0x0f
);
if
(
!
ptr
[
0
])
{
map_str
[
map_len
++
]
=
ch
;
}
else
if
(
!
ptr
[
1
])
{
map_str
[
map_len
++
]
=
ptr
[
0
];
}
else
if
(
!
ptr
[
2
])
{
map_str
[
map_len
++
]
=
ptr
[
0
];
map_str
[
map_len
++
]
=
ptr
[
1
];
}
else
if
(
ptr
[
0
]
!=
0xffff
||
ptr
[
1
]
!=
0xffff
||
ptr
[
2
]
!=
0xffff
)
{
map_str
[
map_len
++
]
=
ptr
[
0
];
map_str
[
map_len
++
]
=
ptr
[
1
];
map_str
[
map_len
++
]
=
ptr
[
2
];
}
}
norm_len
=
FoldStringW
(
MAP_FOLDCZONE
,
map_str
,
map_len
,
norm_str
,
ARRAY_SIZE
(
norm_str
)
-
1
);
if
(
map_str
!=
buf
)
HeapFree
(
GetProcessHeap
(),
0
,
map_str
);
if
(
!
norm_len
)
{
if
(
GetLastError
()
==
ERROR_INSUFFICIENT_BUFFER
)
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
if
(
label_end
<
cchUnicodeChar
)
{
norm_str
[
norm_len
++
]
=
lpUnicodeCharStr
[
label_end
]
?
'.'
:
0
;
label_end
++
;
}
if
(
!
lpNameprepCharStr
)
{
out
+=
norm_len
;
}
else
if
(
out
+
norm_len
<=
cchNameprepChar
)
{
memcpy
(
lpNameprepCharStr
+
out
,
norm_str
,
norm_len
*
sizeof
(
WCHAR
));
out
+=
norm_len
;
}
else
{
SetLastError
(
ERROR_INSUFFICIENT_BUFFER
);
return
0
;
}
have_bidi_ral
=
prohibit_bidi_ral
=
FALSE
;
mask
=
PROHIBITED
;
if
((
dwFlags
&
IDN_ALLOW_UNASSIGNED
)
==
0
)
mask
|=
UNASSIGNED
;
for
(
i
=
0
;
i
<
norm_len
;
i
++
)
{
ch
=
norm_str
[
i
];
flags
=
get_table_entry
(
nameprep_char_type
,
ch
);
if
(
flags
&
mask
)
{
SetLastError
((
flags
&
PROHIBITED
)
?
ERROR_INVALID_NAME
:
ERROR_NO_UNICODE_TRANSLATION
);
return
0
;
}
if
(
flags
&
BIDI_RAL
)
have_bidi_ral
=
TRUE
;
if
(
flags
&
BIDI_L
)
prohibit_bidi_ral
=
TRUE
;
}
if
(
have_bidi_ral
)
{
ch
=
norm_str
[
0
];
flags
=
get_table_entry
(
nameprep_char_type
,
ch
);
if
((
flags
&
BIDI_RAL
)
==
0
)
prohibit_bidi_ral
=
TRUE
;
ch
=
norm_str
[
norm_len
-
1
];
flags
=
get_table_entry
(
nameprep_char_type
,
ch
);
if
((
flags
&
BIDI_RAL
)
==
0
)
prohibit_bidi_ral
=
TRUE
;
}
if
(
have_bidi_ral
&&
prohibit_bidi_ral
)
{
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
label_start
=
label_end
;
}
return
out
;
NTSTATUS
status
=
RtlIdnToNameprepUnicode
(
flags
,
src
,
srclen
,
dst
,
&
dstlen
);
if
(
!
set_ntstatus
(
status
))
return
0
;
return
dstlen
;
}
/******************************************************************************
...
...
dlls/kernel32/tests/locale.c
View file @
cd13557f
...
...
@@ -4431,14 +4431,14 @@ static void test_IdnToNameprepUnicode(void)
{
5
,
L"test"
,
0
,
5
,
5
,
L"test"
},
{
3
,
L"a
\xe111
z"
,
0
,
0
,
0
,
L"a
\xe111
z"
,
0
,
STATUS_NO_UNICODE_TRANSLATION
},
{
4
,
L"t
\0
e"
,
0
,
0
,
0
,
{
0
},
STATUS_NO_UNICODE_TRANSLATION
,
STATUS_NO_UNICODE_TRANSLATION
},
{
1
,
L"T"
,
0
,
1
,
1
,
L"
t
"
},
{
1
,
L"T"
,
0
,
1
,
1
,
L"
T
"
},
{
1
,
{
0
},
0
,
0
},
/* 5 */
{
6
,
L" -/[]"
,
0
,
6
,
6
,
L" -/[]"
},
{
3
,
L"a-a"
,
IDN_USE_STD3_ASCII_RULES
,
3
,
3
,
L"a-a"
},
{
3
,
L"aa-"
,
IDN_USE_STD3_ASCII_RULES
,
0
,
0
,
L"aa-"
},
{
-
1
,
L"T
\xdf\x130\x143\x37a\x6a\x30c
\xaa
"
,
0
,
12
,
12
,
L"tssi
\x307\x144
\x3b9\x1f0
a"
},
{
11
,
L"t
\xad\x34f\x1806\x180b\x180c\x180d\x200b\x200c\x200d
"
,
0
,
2
,
0
,
L"t"
,
{
11
,
L"t
\xad\x34f\x1806\x180b\x180c\x180d\x200b\x200c\x200d
"
,
0
,
0
,
2
,
L"t"
,
STATUS_NO_UNICODE_TRANSLATION
},
/* 10 */
{
2
,
{
0x3b0
},
0
,
2
,
2
,
{
0x3b0
}
},
...
...
@@ -4447,6 +4447,9 @@ static void test_IdnToNameprepUnicode(void)
{
5
,
L"a..a"
,
0
,
0
,
0
,
L"a..a"
},
{
3
,
L"a."
,
0
,
3
,
3
,
L"a."
},
/* 15 */
{
5
,
L"T.
\x105
.A"
,
0
,
5
,
5
,
L"t.
\x105
.a"
},
{
5
,
L"T.*.A"
,
0
,
5
,
5
,
L"T.*.A"
},
{
5
,
L"X
\xff0e
.Z"
,
0
,
0
,
0
,
L"x..z"
},
{
63
,
L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
,
0
,
63
,
63
,
L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
{
64
,
L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
,
0
,
...
...
@@ -4515,7 +4518,7 @@ static void test_IdnToNameprepUnicode(void)
if
(
ret
==
test_data
[
i
].
ret
)
{
ok
(
err
==
ret
?
0xdeadbeef
:
ERROR_INVALID_NAME
,
"%d: err = %d
\n
"
,
i
,
err
);
ok
(
!
wcsn
i
cmp
(
test_data
[
i
].
out
,
buf
,
ret
),
"%d: buf = %s
\n
"
,
i
,
wine_dbgstr_wn
(
buf
,
ret
));
ok
(
!
wcsncmp
(
test_data
[
i
].
out
,
buf
,
ret
),
"%d: buf = %s
\n
"
,
i
,
wine_dbgstr_wn
(
buf
,
ret
));
}
if
(
pRtlNormalizeString
)
{
...
...
@@ -4525,7 +4528,7 @@ static void test_IdnToNameprepUnicode(void)
status
=
pRtlNormalizeString
(
13
,
test_data
[
i
].
in
,
test_data
[
i
].
in_len
,
buf
,
&
len
);
ok
(
status
==
test_data
[
i
].
status
||
broken
(
status
==
test_data
[
i
].
broken_status
),
"%d: failed %x
\n
"
,
i
,
status
);
if
(
!
status
)
ok
(
!
wcsncmp
(
test_data
[
i
].
out
,
buf
,
len
),
"%d: buf = %s
\n
"
,
i
,
wine_dbgstr_wn
(
buf
,
len
));
if
(
!
status
)
ok
(
!
wcsn
i
cmp
(
test_data
[
i
].
out
,
buf
,
len
),
"%d: buf = %s
\n
"
,
i
,
wine_dbgstr_wn
(
buf
,
len
));
}
}
}
...
...
@@ -4569,10 +4572,11 @@ static void test_IdnToAscii(void)
SetLastError
(
0xdeadbeef
);
ret
=
pIdnToAscii
(
test_data
[
i
].
flags
,
test_data
[
i
].
in
,
test_data
[
i
].
in_len
,
buf
,
ARRAY_SIZE
(
buf
));
err
=
GetLastError
();
todo_wine_if
(
i
>
9
)
todo_wine_if
(
i
==
10
)
ok
(
ret
==
test_data
[
i
].
ret
||
broken
(
ret
==
test_data
[
i
].
broken_ret
),
"%d: ret = %d
\n
"
,
i
,
ret
);
ok
(
err
==
ret
?
0xdeadbeef
:
ERROR_INVALID_NAME
,
"%d: err = %d
\n
"
,
i
,
err
);
ok
(
!
wcsncmp
(
test_data
[
i
].
out
,
buf
,
ret
),
"%d: buf = %s
\n
"
,
i
,
wine_dbgstr_wn
(
buf
,
ret
));
todo_wine_if
(
i
==
10
)
ok
(
!
wcsnicmp
(
test_data
[
i
].
out
,
buf
,
ret
),
"%d: buf = %s
\n
"
,
i
,
wine_dbgstr_wn
(
buf
,
ret
));
}
}
...
...
dlls/ntdll/locale.c
View file @
cd13557f
...
...
@@ -2016,3 +2016,77 @@ NTSTATUS WINAPI RtlNormalizeString( ULONG form, const WCHAR *src, INT src_len, W
*
dst_len
=
buf_len
;
return
status
;
}
/******************************************************************************
* RtlIdnToNameprepUnicode (NTDLL.@)
*/
NTSTATUS
WINAPI
RtlIdnToNameprepUnicode
(
DWORD
flags
,
const
WCHAR
*
src
,
INT
srclen
,
WCHAR
*
dst
,
INT
*
dstlen
)
{
const
struct
norm_table
*
info
;
unsigned
int
ch
;
NTSTATUS
status
;
WCHAR
buf
[
256
];
int
i
,
start
,
len
,
buflen
=
ARRAY_SIZE
(
buf
);
if
(
flags
&
~
(
IDN_ALLOW_UNASSIGNED
|
IDN_USE_STD3_ASCII_RULES
))
return
STATUS_INVALID_PARAMETER
;
if
(
!
src
||
srclen
<
-
1
)
return
STATUS_INVALID_PARAMETER
;
TRACE
(
"%x %s %p %d
\n
"
,
flags
,
debugstr_wn
(
src
,
srclen
),
dst
,
*
dstlen
);
if
((
status
=
load_norm_table
(
13
,
&
info
)))
return
status
;
if
(
srclen
==
-
1
)
srclen
=
strlenW
(
src
)
+
1
;
for
(
i
=
0
;
i
<
srclen
;
i
++
)
if
(
src
[
i
]
<
0x20
||
src
[
i
]
>=
0x7f
)
break
;
if
(
i
==
srclen
||
(
i
==
srclen
-
1
&&
!
src
[
i
]))
/* ascii only */
{
if
(
srclen
>
buflen
)
return
STATUS_INVALID_IDN_NORMALIZATION
;
memcpy
(
buf
,
src
,
srclen
*
sizeof
(
WCHAR
)
);
buflen
=
srclen
;
}
else
if
((
status
=
RtlNormalizeString
(
13
,
src
,
srclen
,
buf
,
&
buflen
)))
{
if
(
status
==
STATUS_NO_UNICODE_TRANSLATION
)
status
=
STATUS_INVALID_IDN_NORMALIZATION
;
return
status
;
}
for
(
i
=
start
=
0
;
i
<
buflen
;
i
+=
len
)
{
if
(
!
(
len
=
get_utf16
(
buf
+
i
,
buflen
-
i
,
&
ch
)))
break
;
if
(
!
ch
)
break
;
if
(
ch
==
'.'
)
{
if
(
start
==
i
)
return
STATUS_INVALID_IDN_NORMALIZATION
;
/* maximal label length is 63 characters */
if
(
i
-
start
>
63
)
return
STATUS_INVALID_IDN_NORMALIZATION
;
if
((
flags
&
IDN_USE_STD3_ASCII_RULES
)
&&
(
buf
[
start
]
==
'-'
||
buf
[
i
-
1
]
==
'-'
))
return
STATUS_INVALID_IDN_NORMALIZATION
;
start
=
i
+
1
;
continue
;
}
if
(
flags
&
IDN_USE_STD3_ASCII_RULES
)
{
if
((
ch
>=
'a'
&&
ch
<=
'z'
)
||
(
ch
>=
'A'
&&
ch
<=
'Z'
)
||
(
ch
>=
'0'
&&
ch
<=
'9'
)
||
ch
==
'-'
)
continue
;
return
STATUS_INVALID_IDN_NORMALIZATION
;
}
if
(
!
(
flags
&
IDN_ALLOW_UNASSIGNED
))
{
if
(
get_char_props
(
info
,
ch
)
==
0x7f
)
return
STATUS_INVALID_IDN_NORMALIZATION
;
}
}
if
(
!
i
||
i
-
start
>
63
)
return
STATUS_INVALID_IDN_NORMALIZATION
;
if
((
flags
&
IDN_USE_STD3_ASCII_RULES
)
&&
(
buf
[
start
]
==
'-'
||
buf
[
i
-
1
]
==
'-'
))
return
STATUS_INVALID_IDN_NORMALIZATION
;
if
(
*
dstlen
)
{
if
(
buflen
<=
*
dstlen
)
memcpy
(
dst
,
buf
,
buflen
*
sizeof
(
WCHAR
)
);
else
status
=
STATUS_BUFFER_TOO_SMALL
;
}
*
dstlen
=
buflen
;
return
status
;
}
dlls/ntdll/ntdll.spec
View file @
cd13557f
...
...
@@ -722,6 +722,7 @@
@ stub RtlGuidToPropertySetName
@ stdcall RtlHashUnicodeString(ptr long long ptr)
@ stdcall RtlIdentifierAuthoritySid(ptr)
@ stdcall RtlIdnToNameprepUnicode(long wstr long ptr ptr)
@ stdcall RtlImageDirectoryEntryToData(long long long ptr)
@ stdcall RtlImageNtHeader(long)
@ stdcall RtlImageRvaToSection(ptr long long)
...
...
include/winternl.h
View file @
cd13557f
...
...
@@ -2797,6 +2797,7 @@ NTSYSAPI DWORD WINAPI RtlGetThreadErrorMode(void);
NTSYSAPI
NTSTATUS
WINAPI
RtlGetVersion
(
RTL_OSVERSIONINFOEXW
*
);
NTSYSAPI
NTSTATUS
WINAPI
RtlGUIDFromString
(
PUNICODE_STRING
,
GUID
*
);
NTSYSAPI
PSID_IDENTIFIER_AUTHORITY
WINAPI
RtlIdentifierAuthoritySid
(
PSID
);
NTSYSAPI
NTSTATUS
WINAPI
RtlIdnToNameprepUnicode
(
DWORD
,
const
WCHAR
*
,
INT
,
WCHAR
*
,
INT
*
);
NTSYSAPI
PVOID
WINAPI
RtlImageDirectoryEntryToData
(
HMODULE
,
BOOL
,
WORD
,
ULONG
*
);
NTSYSAPI
PIMAGE_NT_HEADERS
WINAPI
RtlImageNtHeader
(
HMODULE
);
NTSYSAPI
PIMAGE_SECTION_HEADER
WINAPI
RtlImageRvaToSection
(
const
IMAGE_NT_HEADERS
*
,
HMODULE
,
DWORD
);
...
...
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