Piotr Caban : kernel32: Added IdnToUnicode implementation.
Alexandre Julliard
julliard at winehq.org
Mon Apr 30 14:13:09 CDT 2012
Module: wine
Branch: master
Commit: e2f0463963c45e06789454e1bebc0a71800fe48a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e2f0463963c45e06789454e1bebc0a71800fe48a
Author: Piotr Caban <piotr at codeweavers.com>
Date: Mon Apr 30 17:28:08 2012 +0200
kernel32: Added IdnToUnicode implementation.
---
dlls/kernel32/locale.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 146 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index fbc3ae2..b506f15 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -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;
}
More information about the wine-cvs
mailing list