Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
01237d08
Commit
01237d08
authored
Mar 02, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Reimplement IdnToAscii() using the normalization table and the ntdll helpers.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
cd13557f
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
161 additions
and
136 deletions
+161
-136
locale.c
dlls/kernel32/locale.c
+4
-133
locale.c
dlls/kernel32/tests/locale.c
+7
-3
locale.c
dlls/ntdll/locale.c
+148
-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 @
01237d08
...
...
@@ -568,141 +568,12 @@ static inline INT adapt(INT delta, INT numpoints, BOOL firsttime)
/******************************************************************************
* IdnToAscii (KERNEL32.@)
* Implementation of Punycode based on RFC 3492.
*/
INT
WINAPI
IdnToAscii
(
DWORD
dwFlags
,
LPCWSTR
lpUnicodeCharStr
,
INT
cchUnicodeChar
,
LPWSTR
lpASCIICharStr
,
INT
cchASCIIChar
)
INT
WINAPI
IdnToAscii
(
DWORD
flags
,
const
WCHAR
*
src
,
INT
srclen
,
WCHAR
*
dst
,
INT
dstlen
)
{
static
const
WCHAR
prefixW
[]
=
{
'x'
,
'n'
,
'-'
,
'-'
};
WCHAR
*
norm_str
;
INT
i
,
label_start
,
label_end
,
norm_len
,
out_label
,
out
=
0
;
TRACE
(
"%x %p %d %p %d
\n
"
,
dwFlags
,
lpUnicodeCharStr
,
cchUnicodeChar
,
lpASCIICharStr
,
cchASCIIChar
);
norm_len
=
IdnToNameprepUnicode
(
dwFlags
,
lpUnicodeCharStr
,
cchUnicodeChar
,
NULL
,
0
);
if
(
!
norm_len
)
return
0
;
norm_str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
norm_len
*
sizeof
(
WCHAR
));
if
(
!
norm_str
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
norm_len
=
IdnToNameprepUnicode
(
dwFlags
,
lpUnicodeCharStr
,
cchUnicodeChar
,
norm_str
,
norm_len
);
if
(
!
norm_len
)
{
HeapFree
(
GetProcessHeap
(),
0
,
norm_str
);
return
0
;
}
for
(
label_start
=
0
;
label_start
<
norm_len
;)
{
INT
n
=
INIT_N
,
bias
=
INIT_BIAS
;
INT
delta
=
0
,
b
=
0
,
h
;
out_label
=
out
;
for
(
i
=
label_start
;
i
<
norm_len
&&
norm_str
[
i
]
!=
'.'
&&
norm_str
[
i
]
!=
0x3002
&&
norm_str
[
i
]
!=
'\0'
;
i
++
)
if
(
norm_str
[
i
]
<
0x80
)
b
++
;
label_end
=
i
;
if
(
b
==
label_end
-
label_start
)
{
if
(
label_end
<
norm_len
)
b
++
;
if
(
!
lpASCIICharStr
)
{
out
+=
b
;
}
else
if
(
out
+
b
<=
cchASCIIChar
)
{
memcpy
(
lpASCIICharStr
+
out
,
norm_str
+
label_start
,
b
*
sizeof
(
WCHAR
));
out
+=
b
;
}
else
{
HeapFree
(
GetProcessHeap
(),
0
,
norm_str
);
SetLastError
(
ERROR_INSUFFICIENT_BUFFER
);
return
0
;
}
label_start
=
label_end
+
1
;
continue
;
}
if
(
!
lpASCIICharStr
)
{
out
+=
5
+
b
;
/* strlen(xn--...-) */
}
else
if
(
out
+
5
+
b
<=
cchASCIIChar
)
{
memcpy
(
lpASCIICharStr
+
out
,
prefixW
,
sizeof
(
prefixW
));
out
+=
4
;
for
(
i
=
label_start
;
i
<
label_end
;
i
++
)
if
(
norm_str
[
i
]
<
0x80
)
lpASCIICharStr
[
out
++
]
=
norm_str
[
i
];
lpASCIICharStr
[
out
++
]
=
'-'
;
}
else
{
HeapFree
(
GetProcessHeap
(),
0
,
norm_str
);
SetLastError
(
ERROR_INSUFFICIENT_BUFFER
);
return
0
;
}
if
(
!
b
)
out
--
;
for
(
h
=
b
;
h
<
label_end
-
label_start
;)
{
INT
m
=
0xffff
,
q
,
k
;
for
(
i
=
label_start
;
i
<
label_end
;
i
++
)
{
if
(
norm_str
[
i
]
>=
n
&&
m
>
norm_str
[
i
])
m
=
norm_str
[
i
];
}
delta
+=
(
m
-
n
)
*
(
h
+
1
);
n
=
m
;
for
(
i
=
label_start
;
i
<
label_end
;
i
++
)
{
if
(
norm_str
[
i
]
<
n
)
{
delta
++
;
}
else
if
(
norm_str
[
i
]
==
n
)
{
for
(
q
=
delta
,
k
=
BASE
;
;
k
+=
BASE
)
{
INT
t
=
k
<=
bias
?
TMIN
:
k
>=
bias
+
TMAX
?
TMAX
:
k
-
bias
;
INT
disp
=
q
<
t
?
q
:
t
+
(
q
-
t
)
%
(
BASE
-
t
);
if
(
!
lpASCIICharStr
)
{
out
++
;
}
else
if
(
out
+
1
<=
cchASCIIChar
)
{
lpASCIICharStr
[
out
++
]
=
disp
<=
'z'
-
'a'
?
'a'
+
disp
:
'0'
+
disp
-
'z'
+
'a'
-
1
;
}
else
{
HeapFree
(
GetProcessHeap
(),
0
,
norm_str
);
SetLastError
(
ERROR_INSUFFICIENT_BUFFER
);
return
0
;
}
if
(
q
<
t
)
break
;
q
=
(
q
-
t
)
/
(
BASE
-
t
);
}
bias
=
adapt
(
delta
,
h
+
1
,
h
==
b
);
delta
=
0
;
h
++
;
}
}
delta
++
;
n
++
;
}
if
(
out
-
out_label
>
63
)
{
HeapFree
(
GetProcessHeap
(),
0
,
norm_str
);
SetLastError
(
ERROR_INVALID_NAME
);
return
0
;
}
if
(
label_end
<
norm_len
)
{
if
(
!
lpASCIICharStr
)
{
out
++
;
}
else
if
(
out
+
1
<=
cchASCIIChar
)
{
lpASCIICharStr
[
out
++
]
=
norm_str
[
label_end
]
?
'.'
:
0
;
}
else
{
HeapFree
(
GetProcessHeap
(),
0
,
norm_str
);
SetLastError
(
ERROR_INSUFFICIENT_BUFFER
);
return
0
;
}
}
label_start
=
label_end
+
1
;
}
HeapFree
(
GetProcessHeap
(),
0
,
norm_str
);
return
out
;
NTSTATUS
status
=
RtlIdnToAscii
(
flags
,
src
,
srclen
,
dst
,
&
dstlen
);
if
(
!
set_ntstatus
(
status
))
return
0
;
return
dstlen
;
}
/******************************************************************************
...
...
dlls/kernel32/tests/locale.c
View file @
01237d08
...
...
@@ -4572,10 +4572,8 @@ 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
==
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
);
todo_wine_if
(
i
==
10
)
ok
(
!
wcsnicmp
(
test_data
[
i
].
out
,
buf
,
ret
),
"%d: buf = %s
\n
"
,
i
,
wine_dbgstr_wn
(
buf
,
ret
));
}
}
...
...
@@ -4691,10 +4689,16 @@ static void test_Idn(void)
ret
=
pIdnToAscii
(
0
,
columns
[
0
],
-
1
,
dst
,
ARRAY_SIZE
(
dst
)
);
if
(
!
is_idn_error
(
error
))
{
ok
(
ret
,
"line %u: toAscii failed for %s
\n
"
,
line
,
debugstr_w
(
columns
[
0
])
);
ok
(
ret
,
"line %u: toAscii failed for %s expected %s
\n
"
,
line
,
debugstr_w
(
columns
[
0
]),
debugstr_w
(
expect
)
);
if
(
ret
)
ok
(
!
wcscmp
(
dst
,
expect
),
"line %u: got %s expected %s
\n
"
,
line
,
debugstr_w
(
dst
),
debugstr_w
(
expect
)
);
}
else
{
ok
(
!
ret
,
"line %u: toAscii didn't fail for %s got %s expected error %s
\n
"
,
line
,
debugstr_w
(
columns
[
0
]),
debugstr_w
(
dst
),
debugstr_w
(
error
)
);
}
expect
=
columns
[
1
];
if
(
!*
expect
)
expect
=
columns
[
0
];
...
...
dlls/ntdll/locale.c
View file @
01237d08
...
...
@@ -2018,6 +2018,154 @@ NTSTATUS WINAPI RtlNormalizeString( ULONG form, const WCHAR *src, INT src_len, W
}
/* Punycode parameters */
enum
{
BASE
=
36
,
TMIN
=
1
,
TMAX
=
26
,
SKEW
=
38
,
DAMP
=
700
};
static
BOOL
check_invalid_chars
(
const
struct
norm_table
*
info
,
DWORD
flags
,
const
unsigned
int
*
buffer
,
int
len
)
{
int
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
switch
(
buffer
[
i
])
{
case
0x200c
:
/* zero-width non-joiner */
case
0x200d
:
/* zero-width joiner */
if
(
!
i
||
get_combining_class
(
info
,
buffer
[
i
-
1
]
)
!=
9
)
return
TRUE
;
break
;
case
0x2260
:
/* not equal to */
case
0x226e
:
/* not less than */
case
0x226f
:
/* not greater than */
if
(
flags
&
IDN_USE_STD3_ASCII_RULES
)
return
TRUE
;
break
;
}
switch
(
get_char_props
(
info
,
buffer
[
i
]
))
{
case
0xbf
:
return
TRUE
;
case
0xff
:
if
(
buffer
[
i
]
>=
HANGUL_SBASE
&&
buffer
[
i
]
<
HANGUL_SBASE
+
0x2c00
)
break
;
return
TRUE
;
case
0x7f
:
if
(
!
(
flags
&
IDN_ALLOW_UNASSIGNED
))
return
TRUE
;
break
;
}
}
if
((
flags
&
IDN_USE_STD3_ASCII_RULES
)
&&
len
&&
(
buffer
[
0
]
==
'-'
||
buffer
[
len
-
1
]
==
'-'
))
return
TRUE
;
return
FALSE
;
}
/******************************************************************************
* RtlIdnToAscii (NTDLL.@)
*/
NTSTATUS
WINAPI
RtlIdnToAscii
(
DWORD
flags
,
const
WCHAR
*
src
,
INT
srclen
,
WCHAR
*
dst
,
INT
*
dstlen
)
{
static
const
WCHAR
prefixW
[]
=
{
'x'
,
'n'
,
'-'
,
'-'
};
const
struct
norm_table
*
info
;
NTSTATUS
status
;
WCHAR
normstr
[
256
],
res
[
256
];
unsigned
int
ch
,
buffer
[
64
];
int
i
,
len
,
start
,
end
,
out_label
,
out
=
0
,
normlen
=
ARRAY_SIZE
(
normstr
);
TRACE
(
"%x %s %p %d
\n
"
,
flags
,
debugstr_wn
(
src
,
srclen
),
dst
,
*
dstlen
);
if
((
status
=
load_norm_table
(
13
,
&
info
)))
return
status
;
if
((
status
=
RtlIdnToNameprepUnicode
(
flags
,
src
,
srclen
,
normstr
,
&
normlen
)))
return
status
;
/* implementation of Punycode based on RFC 3492 */
for
(
start
=
0
;
start
<
normlen
;
start
=
end
+
1
)
{
int
n
=
0x80
,
bias
=
72
,
delta
=
0
,
b
=
0
,
h
,
buflen
=
0
;
out_label
=
out
;
for
(
i
=
start
;
i
<
normlen
;
i
+=
len
)
{
if
(
!
(
len
=
get_utf16
(
normstr
+
i
,
normlen
-
i
,
&
ch
)))
break
;
if
(
!
ch
||
ch
==
'.'
)
break
;
if
(
ch
<
0x80
)
b
++
;
buffer
[
buflen
++
]
=
ch
;
}
end
=
i
;
if
(
b
==
end
-
start
)
{
if
(
end
<
normlen
)
b
++
;
if
(
out
+
b
>
ARRAY_SIZE
(
res
))
return
STATUS_INVALID_IDN_NORMALIZATION
;
memcpy
(
res
+
out
,
normstr
+
start
,
b
*
sizeof
(
WCHAR
)
);
out
+=
b
;
continue
;
}
if
(
buflen
>=
4
&&
buffer
[
2
]
==
'-'
&&
buffer
[
3
]
==
'-'
)
return
STATUS_INVALID_IDN_NORMALIZATION
;
if
(
check_invalid_chars
(
info
,
flags
,
buffer
,
buflen
))
return
STATUS_INVALID_IDN_NORMALIZATION
;
if
(
out
+
5
+
b
>
ARRAY_SIZE
(
res
))
return
STATUS_INVALID_IDN_NORMALIZATION
;
memcpy
(
res
+
out
,
prefixW
,
sizeof
(
prefixW
)
);
out
+=
ARRAY_SIZE
(
prefixW
);
if
(
b
)
{
for
(
i
=
start
;
i
<
end
;
i
++
)
if
(
normstr
[
i
]
<
0x80
)
res
[
out
++
]
=
normstr
[
i
];
res
[
out
++
]
=
'-'
;
}
for
(
h
=
b
;
h
<
buflen
;
delta
++
,
n
++
)
{
int
m
=
0x10ffff
,
q
,
k
;
for
(
i
=
0
;
i
<
buflen
;
i
++
)
if
(
buffer
[
i
]
>=
n
&&
m
>
buffer
[
i
])
m
=
buffer
[
i
];
delta
+=
(
m
-
n
)
*
(
h
+
1
);
n
=
m
;
for
(
i
=
0
;
i
<
buflen
;
i
++
)
{
if
(
buffer
[
i
]
==
n
)
{
for
(
q
=
delta
,
k
=
BASE
;
;
k
+=
BASE
)
{
int
t
=
k
<=
bias
?
TMIN
:
k
>=
bias
+
TMAX
?
TMAX
:
k
-
bias
;
int
disp
=
q
<
t
?
q
:
t
+
(
q
-
t
)
%
(
BASE
-
t
);
if
(
out
+
1
>
ARRAY_SIZE
(
res
))
return
STATUS_INVALID_IDN_NORMALIZATION
;
res
[
out
++
]
=
disp
<=
25
?
'a'
+
disp
:
'0'
+
disp
-
26
;
if
(
q
<
t
)
break
;
q
=
(
q
-
t
)
/
(
BASE
-
t
);
}
delta
/=
(
h
==
b
?
DAMP
:
2
);
delta
+=
delta
/
(
h
+
1
);
for
(
k
=
0
;
delta
>
((
BASE
-
TMIN
)
*
TMAX
)
/
2
;
k
+=
BASE
)
delta
/=
BASE
-
TMIN
;
bias
=
k
+
((
BASE
-
TMIN
+
1
)
*
delta
)
/
(
delta
+
SKEW
);
delta
=
0
;
h
++
;
}
else
if
(
buffer
[
i
]
<
n
)
delta
++
;
}
}
if
(
out
-
out_label
>
63
)
return
STATUS_INVALID_IDN_NORMALIZATION
;
if
(
end
<
normlen
)
{
if
(
out
+
1
>
ARRAY_SIZE
(
res
))
return
STATUS_INVALID_IDN_NORMALIZATION
;
res
[
out
++
]
=
normstr
[
end
];
}
}
if
(
*
dstlen
)
{
if
(
out
<=
*
dstlen
)
memcpy
(
dst
,
res
,
out
*
sizeof
(
WCHAR
)
);
else
status
=
STATUS_BUFFER_TOO_SMALL
;
}
*
dstlen
=
out
;
return
status
;
}
/******************************************************************************
* RtlIdnToNameprepUnicode (NTDLL.@)
*/
...
...
dlls/ntdll/ntdll.spec
View file @
01237d08
...
...
@@ -722,6 +722,7 @@
@ stub RtlGuidToPropertySetName
@ stdcall RtlHashUnicodeString(ptr long long ptr)
@ stdcall RtlIdentifierAuthoritySid(ptr)
@ stdcall RtlIdnToAscii(long wstr long ptr ptr)
@ stdcall RtlIdnToNameprepUnicode(long wstr long ptr ptr)
@ stdcall RtlImageDirectoryEntryToData(long long long ptr)
@ stdcall RtlImageNtHeader(long)
...
...
include/winternl.h
View file @
01237d08
...
...
@@ -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
RtlIdnToAscii
(
DWORD
,
const
WCHAR
*
,
INT
,
WCHAR
*
,
INT
*
);
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
);
...
...
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