Commit e2f04639 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

kernel32: Added IdnToUnicode implementation.

parent 03b58f58
......@@ -4263,8 +4263,151 @@ INT WINAPI IdnToNameprepUnicode(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cch
INT WINAPI IdnToUnicode(DWORD dwFlags, LPCWSTR lpASCIICharStr, INT cchASCIIChar,
LPWSTR lpUnicodeCharStr, INT cchUnicodeChar)
{
FIXME("%x %p %d %p %d\n", dwFlags, lpASCIICharStr, cchASCIIChar,
extern const unsigned short nameprep_char_type[];
INT i, label_start, label_end, out_label, out = 0;
WCHAR ch;
TRACE("%x %p %d %p %d\n", dwFlags, lpASCIICharStr, cchASCIIChar,
lpUnicodeCharStr, cchUnicodeChar);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
for(label_start=0; label_start<cchASCIIChar;) {
INT n = INIT_N, pos = 0, old_pos, w, k, bias = INIT_BIAS, delim=0, digit, t;
out_label = out;
for(i=label_start; i<cchASCIIChar; i++) {
ch = lpASCIICharStr[i];
if(ch>0x7f || (i!=cchASCIIChar-1 && !ch)) {
SetLastError(ERROR_INVALID_NAME);
return 0;
}
if(!ch || ch=='.')
break;
if(ch == '-')
delim = i;
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(label_end-label_start > 63) {
SetLastError(ERROR_INVALID_NAME);
return 0;
}
if(label_end-label_start<4 ||
tolowerW(lpASCIICharStr[label_start])!='x' ||
tolowerW(lpASCIICharStr[label_start+1])!='n' ||
lpASCIICharStr[label_start+2]!='-' || lpASCIICharStr[label_start+3]!='-') {
if(label_end < cchUnicodeChar)
label_end++;
if(!lpUnicodeCharStr) {
out += label_end-label_start;
}else if(out+label_end-label_start <= cchUnicodeChar) {
memcpy(lpUnicodeCharStr+out, lpASCIICharStr+label_start,
(label_end-label_start)*sizeof(WCHAR));
out += label_end-label_start;
}else {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
label_start = label_end;
continue;
}
if(delim == label_start+3)
delim++;
if(!lpUnicodeCharStr) {
out += delim-label_start-4;
}else if(out+delim-label_start-4 <= cchUnicodeChar) {
memcpy(lpUnicodeCharStr+out, lpASCIICharStr+label_start+4,
(delim-label_start-4)*sizeof(WCHAR));
out += delim-label_start-4;
}else {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
if(out != out_label)
delim++;
for(i=delim; i<label_end;) {
old_pos = pos;
w = 1;
for(k=BASE; ; k+=BASE) {
ch = i<label_end ? tolowerW(lpASCIICharStr[i++]) : 0;
if((ch<'a' || ch>'z') && (ch<'0' || ch>'9')) {
SetLastError(ERROR_INVALID_NAME);
return 0;
}
digit = ch<='9' ? ch-'0'+'z'-'a'+1 : ch-'a';
pos += digit*w;
t = k<=bias ? TMIN : k>=bias+TMAX ? TMAX : k-bias;
if(digit < t)
break;
w *= BASE-t;
}
bias = adapt(pos-old_pos, out-out_label+1, old_pos==0);
n += pos/(out-out_label+1);
pos %= out-out_label+1;
if((dwFlags&IDN_ALLOW_UNASSIGNED)==0 &&
get_table_entry(nameprep_char_type, n)==1/*UNASSIGNED*/) {
SetLastError(ERROR_INVALID_NAME);
return 0;
}
if(!lpUnicodeCharStr) {
out++;
}else if(out+1 <= cchASCIIChar) {
memmove(lpUnicodeCharStr+out_label+pos+1,
lpUnicodeCharStr+out_label+pos,
(out-out_label-pos)*sizeof(WCHAR));
lpUnicodeCharStr[out_label+pos] = n;
out++;
}else {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
pos++;
}
if(out-out_label > 63) {
SetLastError(ERROR_INVALID_NAME);
return 0;
}
if(label_end < cchASCIIChar) {
if(!lpUnicodeCharStr) {
out++;
}else if(out+1 <= cchUnicodeChar) {
lpUnicodeCharStr[out++] = lpASCIICharStr[label_end];
}else {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
}
label_start = label_end+1;
}
return out;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment