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