wined3d: Restore recording mode later in ActiveRender().
[wine] / dlls / ntdll / wcstring.c
index 55da518..6891258 100644 (file)
@@ -3,6 +3,21 @@
  *
  * Copyright 2000 Alexandre Julliard
  * Copyright 2000 Jon Griffiths
+ * Copyright 2003 Thomas Mertes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include "config.h"
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
 #include <stdio.h>
 
 #include "windef.h"
-#include "winbase.h"
-#include "winnls.h"
+#include "winternl.h"
 #include "wine/unicode.h"
-#include "heap.h"
-#include "debugtools.h"
+#include "wine/debug.h"
 
-DEFAULT_DEBUG_CHANNEL(ntdll);
+WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
 
 /*********************************************************************
- *           NTDLL__wcsicmp    (NTDLL)
+ *           _wcsicmp    (NTDLL.@)
  */
 INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
 {
@@ -33,7 +47,7 @@ INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
 
 
 /*********************************************************************
- *           NTDLL__wcslwr    (NTDLL)
+ *           _wcslwr    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
 {
@@ -42,7 +56,7 @@ LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
 
 
 /*********************************************************************
- *           NTDLL__wcsnicmp    (NTDLL)
+ *           _wcsnicmp    (NTDLL.@)
  */
 INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
 {
@@ -51,7 +65,7 @@ INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
 
 
 /*********************************************************************
- *           NTDLL__wcsupr    (NTDLL)
+ *           _wcsupr    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
 {
@@ -60,7 +74,7 @@ LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
 
 
 /*********************************************************************
- *           NTDLL_towlower    (NTDLL)
+ *           towlower    (NTDLL.@)
  */
 WCHAR __cdecl NTDLL_towlower( WCHAR ch )
 {
@@ -69,7 +83,7 @@ WCHAR __cdecl NTDLL_towlower( WCHAR ch )
 
 
 /*********************************************************************
- *           NTDLL_towupper    (NTDLL)
+ *           towupper    (NTDLL.@)
  */
 WCHAR __cdecl NTDLL_towupper( WCHAR ch )
 {
@@ -78,7 +92,7 @@ WCHAR __cdecl NTDLL_towupper( WCHAR ch )
 
 
 /***********************************************************************
- *           NTDLL_wcscat    (NTDLL)
+ *           wcscat    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
 {
@@ -87,7 +101,7 @@ LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
 
 
 /*********************************************************************
- *           NTDLL_wcschr    (NTDLL)
+ *           wcschr    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
 {
@@ -96,7 +110,7 @@ LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
 
 
 /*********************************************************************
- *           NTDLL_wcscmp    (NTDLL)
+ *           wcscmp    (NTDLL.@)
  */
 INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
 {
@@ -105,7 +119,7 @@ INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
 
 
 /***********************************************************************
- *           NTDLL_wcscpy    (NTDLL)
+ *           wcscpy    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
 {
@@ -114,24 +128,16 @@ LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
 
 
 /*********************************************************************
- *           NTDLL_wcscspn    (NTDLL)
+ *           wcscspn    (NTDLL.@)
  */
 INT __cdecl NTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
 {
-    LPCWSTR start = str;
-    while (*str)
-    {
-        LPCWSTR p = reject;
-        while (*p && (*p != *str)) p++;
-        if (*p) break;
-        str++;
-    }
-    return str - start;
+    return strcspnW( str, reject );
 }
 
 
 /***********************************************************************
- *           NTDLL_wcslen    (NTDLL)
+ *           wcslen    (NTDLL.@)
  */
 INT __cdecl NTDLL_wcslen( LPCWSTR str )
 {
@@ -140,7 +146,7 @@ INT __cdecl NTDLL_wcslen( LPCWSTR str )
 
 
 /*********************************************************************
- *           NTDLL_wcsncat    (NTDLL)
+ *           wcsncat    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
 {
@@ -153,7 +159,7 @@ LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
 
 
 /*********************************************************************
- *           NTDLL_wcsncmp    (NTDLL)
+ *           wcsncmp    (NTDLL.@)
  */
 INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
 {
@@ -162,63 +168,46 @@ INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
 
 
 /*********************************************************************
- *           NTDLL_wcsncpy    (NTDLL)
+ *           wcsncpy    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
 {
-    return strncpyW( s1, s2, n );
+    WCHAR *ret = s1;
+    while (n-- > 0) if (!(*s1++ = *s2++)) break;
+    while (n-- > 0) *s1++ = 0;
+    return ret;
 }
 
 
 /*********************************************************************
- *           NTDLL_wcspbrk    (NTDLL)
+ *           wcspbrk    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
 {
-    LPCWSTR p;
-    while (*str)
-    {
-        for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
-        str++;
-    }
-    return NULL;
+    return strpbrkW( str, accept );
 }
 
 
 /*********************************************************************
- *           NTDLL_wcsrchr    (NTDLL)
+ *           wcsrchr    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcsrchr( LPWSTR str, WCHAR ch )
 {
-    LPWSTR last = NULL;
-    while (*str)
-    {
-        if (*str == ch) last = str;
-        str++;
-    }
-    return last;
+    return strrchrW( str, ch );
 }
 
 
 /*********************************************************************
- *           NTDLL_wcsspn    (NTDLL)
+ *           wcsspn    (NTDLL.@)
  */
 INT __cdecl NTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
 {
-    LPCWSTR start = str;
-    while (*str)
-    {
-        LPCWSTR p = accept;
-        while (*p && (*p != *str)) p++;
-        if (!*p) break;
-        str++;
-    }
-    return str - start;
+    return strspnW( str, accept );
 }
 
 
 /*********************************************************************
- *           NTDLL_wcsstr    (NTDLL)
+ *           wcsstr    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
 {
@@ -227,7 +216,7 @@ LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
 
 
 /*********************************************************************
- *           NTDLL_wcstok    (NTDLL)
+ *           wcstok    (NTDLL.@)
  */
 LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
 {
@@ -248,48 +237,68 @@ LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
 
 
 /*********************************************************************
- *           NTDLL_wcstombs    (NTDLL)
+ *           wcstombs    (NTDLL.@)
  */
 INT __cdecl NTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
 {
-    INT ret;
-    if (n <= 0) return 0;
-    ret = WideCharToMultiByte( CP_ACP, 0, src, -1, dst, dst ? n : 0, NULL, NULL );
-    if (!ret) return n;  /* overflow */
-    return ret - 1;  /* do not count terminating NULL */
+    DWORD len;
+
+    if (!dst)
+    {
+        RtlUnicodeToMultiByteSize( &len, src, strlenW(src)*sizeof(WCHAR) );
+        return len;
+    }
+    else
+    {
+        if (n <= 0) return 0;
+        RtlUnicodeToMultiByteN( dst, n, &len, src, strlenW(src)*sizeof(WCHAR) );
+        if (len < n) dst[len] = 0;
+    }
+    return len;
 }
 
 
 /*********************************************************************
- *           NTDLL_mbstowcs    (NTDLL)
+ *           mbstowcs    (NTDLL.@)
  */
 INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
 {
-    INT ret;
-    if (n <= 0) return 0;
-    ret = MultiByteToWideChar( CP_ACP, 0, src, -1, dst, dst ? n : 0 );
-    if (!ret) return n;  /* overflow */
-    return ret - 1;  /* do not count terminating NULL */
+    DWORD len;
+
+    if (!dst)
+    {
+        RtlMultiByteToUnicodeSize( &len, src, strlen(src) );
+    }
+    else
+    {
+        if (n <= 0) return 0;
+        RtlMultiByteToUnicodeN( dst, n*sizeof(WCHAR), &len, src, strlen(src) );
+        if (len / sizeof(WCHAR) < n) dst[len / sizeof(WCHAR)] = 0;
+    }
+    return len / sizeof(WCHAR);
 }
 
 
 /*********************************************************************
- *                  wcstol  (NTDLL)
- * Like strtol, but for wide character strings.
+ *                  wcstol  (NTDLL.@)
  */
-INT __cdecl NTDLL_wcstol(LPWSTR s,LPWSTR *end,INT base)
+long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
 {
-    LPSTR sA = HEAP_strdupWtoA(GetProcessHeap(),0,s),endA;
-    INT        ret = strtol(sA,&endA,base);
+    return strtolW( s, end, base );
+}
 
-    HeapFree(GetProcessHeap(),0,sA);
-    if (end) *end = s+(endA-sA); /* pointer magic checked. */
-    return ret;
+
+/*********************************************************************
+ *                  wcstoul  (NTDLL.@)
+ */
+unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
+{
+    return strtoulW( s, end, base );
 }
 
 
 /*********************************************************************
- *           NTDLL_iswctype    (NTDLL)
+ *           iswctype    (NTDLL.@)
  */
 INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
 {
@@ -298,196 +307,460 @@ INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
 
 
 /*********************************************************************
- *           NTDLL_iswalpha    (NTDLL)
+ *           iswalpha    (NTDLL.@)
+ *
+ * Checks if an unicode char wc is a letter
+ *
+ * RETURNS
+ *  TRUE: The unicode char wc is a letter.
+ *  FALSE: Otherwise
  */
 INT __cdecl NTDLL_iswalpha( WCHAR wc )
 {
-    return get_char_typeW(wc) & C1_ALPHA;
+    return isalphaW(wc);
 }
 
 
 /*********************************************************************
- *           _ultow    (NTDLL)
- * Like _ultoa, but for wide character strings.
+ *             iswdigit (NTDLL.@)
+ *
+ * Checks if an unicode char wc is a digit
+ *
+ * RETURNS
+ *  TRUE: The unicode char wc is a digit.
+ *  FALSE: Otherwise
  */
-LPWSTR __cdecl _ultow(ULONG value, LPWSTR string, INT radix)
+INT __cdecl NTDLL_iswdigit( WCHAR wc )
 {
-    WCHAR tmp[33];
-    LPWSTR tp = tmp;
-    LPWSTR sp;
-    LONG i;
-    ULONG v = value;
+    return isdigitW(wc);
+}
 
-    if (radix > 36 || radix <= 1)
-       return 0;
 
-    while (v || tp == tmp)
-    {
-       i = v % radix;
-       v = v / radix;
-       if (i < 10)
-           *tp++ = i + '0';
-       else
-           *tp++ = i + 'a' - 10;
-    }
+/*********************************************************************
+ *             iswlower (NTDLL.@)
+ *
+ * Checks if an unicode char wc is a lower case letter
+ *
+ * RETURNS
+ *  TRUE: The unicode char wc is a lower case letter.
+ *  FALSE: Otherwise
+ */
+INT __cdecl NTDLL_iswlower( WCHAR wc )
+{
+    return islowerW(wc);
+}
 
-    sp = string;
-    while (tp > tmp)
-       *sp++ = *--tp;
-    *sp = 0;
-    return string;
+
+/*********************************************************************
+ *             iswspace (NTDLL.@)
+ *
+ * Checks if an unicode char wc is a white space character
+ *
+ * RETURNS
+ *  TRUE: The unicode char wc is a white space character.
+ *  FALSE: Otherwise
+ */
+INT __cdecl NTDLL_iswspace( WCHAR wc )
+{
+    return isspaceW(wc);
+}
+
+
+/*********************************************************************
+ *             iswxdigit (NTDLL.@)
+ *
+ * Checks if an unicode char wc is an extended digit
+ *
+ * RETURNS
+ *  TRUE: The unicode char wc is an extended digit.
+ *  FALSE: Otherwise
+ */
+INT __cdecl NTDLL_iswxdigit( WCHAR wc )
+{
+    return isxdigitW(wc);
 }
 
 
-/* INTERNAL: Wide char snprintf
- * If you fix a bug in this function, fix it in msvcrt/wcs.c also!
+/*********************************************************************
+ *      _ultow   (NTDLL.@)
+ *
+ * Converts an unsigned long integer to an unicode string.
+ *
+ * RETURNS
+ *  Always returns str.
+ *
+ * NOTES
+ *  Converts value to a '\0' terminated wstring which is copied to str.
+ *  The maximum length of the copied str is 33 bytes.
+ *  Does not check if radix is in the range of 2 to 36.
+ *  If str is NULL it just returns NULL.
  */
-static int __cdecl NTDLL_vsnwprintf(WCHAR *str, unsigned int len,
-                                    const WCHAR *format, va_list valist)
+LPWSTR __cdecl _ultow(
+    unsigned long value, /* [I] Value to be converted */
+    LPWSTR str,          /* [O] Destination for the converted value */
+    INT radix)           /* [I] Number base for conversion */
 {
-  unsigned int written = 0;
-  const WCHAR *iter = format;
-  char bufa[256], fmtbufa[64], *fmta;
+    WCHAR buffer[33];
+    PWCHAR pos;
+    WCHAR digit;
+
+    pos = &buffer[32];
+    *pos = '\0';
+
+    do {
+       digit = value % radix;
+       value = value / radix;
+       if (digit < 10) {
+           *--pos = '0' + digit;
+       } else {
+           *--pos = 'a' + digit - 10;
+       } /* if */
+    } while (value != 0L);
+
+    if (str != NULL) {
+       memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
+    } /* if */
+    return str;
+}
 
-  TRACE("(%d,%s)\n",len,debugstr_w(format));
 
-  while (*iter)
-  {
-    while (*iter && *iter != (WCHAR)L'%')
-    {
-     if (written++ >= len)
-       return -1;
-     *str++ = *iter++;
-    }
-    if (*iter == (WCHAR)L'%')
-    {
-      fmta = fmtbufa;
-      *fmta++ = *iter++;
-      while (*iter == (WCHAR)L'0' ||
-             *iter == (WCHAR)L'+' ||
-             *iter == (WCHAR)L'-' ||
-             *iter == (WCHAR)L' ' ||
-             *iter == (WCHAR)L'0' ||
-             *iter == (WCHAR)L'*' ||
-             *iter == (WCHAR)L'#')
-      {
-        if (*iter == (WCHAR)L'*')
-        {
-          char *buffiter = bufa;
-          int fieldlen = va_arg(valist, int);
-          sprintf(buffiter, "%d", fieldlen);
-          while (*buffiter)
-            *fmta++ = *buffiter++;
-        }
-        else
-          *fmta++ = *iter;
-        iter++;
-      }
-
-      while (isdigit(*iter))
-        *fmta++ = *iter++;
-
-      if (*iter == (WCHAR)L'.')
-      {
-        *fmta++ = *iter++;
-        if (*iter == (WCHAR)L'*')
-        {
-          char *buffiter = bufa;
-          int fieldlen = va_arg(valist, int);
-          sprintf(buffiter, "%d", fieldlen);
-          while (*buffiter)
-            *fmta++ = *buffiter++;
-        }
-        else
-          while (isdigit(*iter))
-            *fmta++ = *iter++;
-      }
-      if (*iter == (WCHAR)L'h' ||
-          *iter == (WCHAR)L'l')
-      {
-          *fmta++ = *iter++;
-          *fmta++ = *iter++;
-      }
-
-      switch (*iter)
-      {
-      case (WCHAR)L's':
-        {
-          static const WCHAR none[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
-          const WCHAR *wstr = va_arg(valist, const WCHAR *);
-          const WCHAR *striter = wstr ? wstr : none;
-          while (*striter)
-          {
-            if (written++ >= len)
-              return -1;
-            *str++ = *striter++;
-          }
-          iter++;
-          break;
-        }
-
-      case (WCHAR)L'c':
-        if (written++ >= len)
-          return -1;
-        *str++ = va_arg(valist, WCHAR);
-        iter++;
-        break;
-
-      default:
-        {
-          /* For non wc types, use system sprintf and append to wide char output */
-          /* FIXME: for unrecognised types, should ignore % when printing */
-          char *bufaiter = bufa;
-          if (*iter == (WCHAR)L'p')
-            sprintf(bufaiter, "%08lX", va_arg(valist, long));
-          else
-          {
-            *fmta++ = *iter;
-            *fmta = '\0';
-            sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
-          }
-          while (*bufaiter)
-          {
-            if (written++ >= len)
-              return -1;
-            *str++ = *bufaiter++;
-          }
-          iter++;
-          break;
-        }
-      }
-    }
-  }
-  if (written >= len)
-    return -1;
-  *str++ = (WCHAR)L'\0';
-  return (int)written;
+/*********************************************************************
+ *      _ltow   (NTDLL.@)
+ *
+ * Converts a long integer to an unicode string.
+ *
+ * RETURNS
+ *  Always returns str.
+ *
+ * NOTES
+ *  Converts value to a '\0' terminated wstring which is copied to str.
+ *  The maximum length of the copied str is 33 bytes. If radix
+ *  is 10 and value is negative, the value is converted with sign.
+ *  Does not check if radix is in the range of 2 to 36.
+ *  If str is NULL it just returns NULL.
+ */
+LPWSTR __cdecl _ltow(
+    long value, /* [I] Value to be converted */
+    LPWSTR str, /* [O] Destination for the converted value */
+    INT radix)  /* [I] Number base for conversion */
+{
+    unsigned long val;
+    int negative;
+    WCHAR buffer[33];
+    PWCHAR pos;
+    WCHAR digit;
+
+    if (value < 0 && radix == 10) {
+       negative = 1;
+        val = -value;
+    } else {
+       negative = 0;
+        val = value;
+    } /* if */
+
+    pos = &buffer[32];
+    *pos = '\0';
+
+    do {
+       digit = val % radix;
+       val = val / radix;
+       if (digit < 10) {
+           *--pos = '0' + digit;
+       } else {
+           *--pos = 'a' + digit - 10;
+       } /* if */
+    } while (val != 0L);
+
+    if (negative) {
+       *--pos = '-';
+    } /* if */
+
+    if (str != NULL) {
+       memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
+    } /* if */
+    return str;
+}
+
+
+/*********************************************************************
+ *      _itow    (NTDLL.@)
+ *
+ * Converts an integer to an unicode string.
+ *
+ * RETURNS
+ *  Always returns str.
+ *
+ * NOTES
+ *  Converts value to a '\0' terminated wstring which is copied to str.
+ *  The maximum length of the copied str is 33 bytes. If radix
+ *  is 10 and value is negative, the value is converted with sign.
+ *  Does not check if radix is in the range of 2 to 36.
+ *  If str is NULL it just returns NULL.
+ *
+ * DIFFERENCES
+ * - The native function crashes when the string is longer than 19 chars.
+ *   This function does not have this bug.
+ */
+LPWSTR __cdecl _itow(
+    int value,  /* [I] Value to be converted */
+    LPWSTR str, /* [O] Destination for the converted value */
+    INT radix)  /* [I] Number base for conversion */
+{
+    return _ltow(value, str, radix);
+}
+
+
+/*********************************************************************
+ *      _ui64tow   (NTDLL.@)
+ *
+ * Converts a large unsigned integer to an unicode string.
+ *
+ * RETURNS
+ *  Always returns str.
+ *
+ * NOTES
+ *  Converts value to a '\0' terminated wstring which is copied to str.
+ *  The maximum length of the copied str is 33 bytes.
+ *  Does not check if radix is in the range of 2 to 36.
+ *  If str is NULL it just returns NULL.
+ *
+ * DIFFERENCES
+ * - This function does not exist in the native DLL (but in msvcrt).
+ *   But since the maintenance of all these functions is better done
+ *   in one place we implement it here.
+ */
+LPWSTR __cdecl _ui64tow(
+    ULONGLONG value, /* [I] Value to be converted */
+    LPWSTR str,      /* [O] Destination for the converted value */
+    INT radix)       /* [I] Number base for conversion */
+{
+    WCHAR buffer[65];
+    PWCHAR pos;
+    WCHAR digit;
+
+    pos = &buffer[64];
+    *pos = '\0';
+
+    do {
+       digit = value % radix;
+       value = value / radix;
+       if (digit < 10) {
+           *--pos = '0' + digit;
+       } else {
+           *--pos = 'a' + digit - 10;
+       } /* if */
+    } while (value != 0L);
+
+    if (str != NULL) {
+       memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
+    } /* if */
+    return str;
+}
+
+
+/*********************************************************************
+ *      _i64tow   (NTDLL.@)
+ *
+ * Converts a large integer to an unicode string.
+ *
+ * RETURNS
+ *  Always returns str.
+ *
+ * NOTES
+ *  Converts value to a '\0' terminated wstring which is copied to str.
+ *  The maximum length of the copied str is 33 bytes. If radix
+ *  is 10 and value is negative, the value is converted with sign.
+ *  Does not check if radix is in the range of 2 to 36.
+ *  If str is NULL it just returns NULL.
+ *
+ * DIFFERENCES
+ * - The native DLL converts negative values (for base 10) wrong:
+ *                     -1 is converted to -18446744073709551615
+ *                     -2 is converted to -18446744073709551614
+ *   -9223372036854775807 is converted to  -9223372036854775809
+ *   -9223372036854775808 is converted to  -9223372036854775808
+ *   The native msvcrt _i64tow function and our ntdll function do
+ *   not have this bug.
+ */
+LPWSTR __cdecl _i64tow(
+    LONGLONG value, /* [I] Value to be converted */
+    LPWSTR str,     /* [O] Destination for the converted value */
+    INT radix)      /* [I] Number base for conversion */
+{
+    ULONGLONG val;
+    int negative;
+    WCHAR buffer[65];
+    PWCHAR pos;
+    WCHAR digit;
+
+    if (value < 0 && radix == 10) {
+       negative = 1;
+        val = -value;
+    } else {
+       negative = 0;
+        val = value;
+    } /* if */
+
+    pos = &buffer[64];
+    *pos = '\0';
+
+    do {
+       digit = val % radix;
+       val = val / radix;
+       if (digit < 10) {
+           *--pos = '0' + digit;
+       } else {
+           *--pos = 'a' + digit - 10;
+       } /* if */
+    } while (val != 0L);
+
+    if (negative) {
+       *--pos = '-';
+    } /* if */
+
+    if (str != NULL) {
+       memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
+    } /* if */
+    return str;
+}
+
+
+/*********************************************************************
+ *      _wtol    (NTDLL.@)
+ *
+ * Converts an unicode string to a long integer.
+ *
+ * PARAMS
+ *  str [I] Wstring to be converted
+ *
+ * RETURNS
+ *  On success it returns the integer value otherwise it returns 0.
+ *
+ * NOTES
+ *  Accepts: {whitespace} [+|-] {digits}
+ *  No check is made for value overflow, only the lower 32 bits are assigned.
+ *  If str is NULL it crashes, as the native function does.
+ */
+LONG __cdecl _wtol( LPCWSTR str )
+{
+    ULONG RunningTotal = 0;
+    char bMinus = 0;
+
+    while (isspaceW(*str)) {
+       str++;
+    } /* while */
+
+    if (*str == '+') {
+       str++;
+    } else if (*str == '-') {
+       bMinus = 1;
+       str++;
+    } /* if */
+
+    while (*str >= '0' && *str <= '9') {
+       RunningTotal = RunningTotal * 10 + *str - '0';
+       str++;
+    } /* while */
+
+    return bMinus ? -RunningTotal : RunningTotal;
+}
+
+
+/*********************************************************************
+ *      _wtoi    (NTDLL.@)
+ *
+ * Converts an unicode string to an integer.
+ *
+ * PARAMS
+ *  str [I] Wstring to be converted
+ *
+ * RETURNS
+ *  On success it returns the integer value otherwise it returns 0.
+ *
+ * NOTES
+ *  Accepts: {whitespace} [+|-] {digits}
+ *  No check is made for value overflow, only the lower 32 bits are assigned.
+ *  If str is NULL it crashes, as the native function does.
+ */
+int __cdecl _wtoi( LPCWSTR str )
+{
+    return _wtol(str);
+}
+
+
+/*********************************************************************
+ *      _wtoi64   (NTDLL.@)
+ *
+ * Converts an unicode string to a large integer.
+ *
+ * PARAMS
+ *  str [I] Wstring to be converted
+ *
+ * RETURNS
+ *  On success it returns the integer value otherwise it returns 0.
+ *
+ * NOTES
+ *  Accepts: {whitespace} [+|-] {digits}
+ *  No check is made for value overflow, only the lower 64 bits are assigned.
+ *  If str is NULL it crashes, as the native function does.
+ */
+LONGLONG  __cdecl _wtoi64( LPCWSTR str )
+{
+    ULONGLONG RunningTotal = 0;
+    char bMinus = 0;
+
+    while (isspaceW(*str)) {
+       str++;
+    } /* while */
+
+    if (*str == '+') {
+       str++;
+    } else if (*str == '-') {
+       bMinus = 1;
+       str++;
+    } /* if */
+
+    while (*str >= '0' && *str <= '9') {
+       RunningTotal = RunningTotal * 10 + *str - '0';
+       str++;
+    } /* while */
+
+    return bMinus ? -RunningTotal : RunningTotal;
 }
 
 
 /***********************************************************************
- *        _snwprintf (NTDLL)
+ *        _snwprintf (NTDLL.@)
  */
 int __cdecl _snwprintf(WCHAR *str, unsigned int len, const WCHAR *format, ...)
 {
   int retval;
   va_list valist;
   va_start(valist, format);
-  retval = NTDLL_vsnwprintf(str, len, format, valist);
+  retval = vsnprintfW(str, len, format, valist);
   va_end(valist);
   return retval;
 }
 
 
 /***********************************************************************
- *        NTDLL_swprintf (NTDLL)
+ *        swprintf (NTDLL.@)
  */
 int __cdecl NTDLL_swprintf(WCHAR *str, const WCHAR *format, ...)
 {
   int retval;
   va_list valist;
   va_start(valist, format);
-  retval = NTDLL_vsnwprintf(str, INT_MAX, format, valist);
+  retval = vsnprintfW(str, INT_MAX, format, valist);
   va_end(valist);
   return retval;
 }
+
+
+/***********************************************************************
+ *        _vsnwprintf (NTDLL.@)
+ */
+int __cdecl _vsnwprintf( WCHAR *str, unsigned int len, const WCHAR *format, va_list args )
+{
+  return vsnprintfW( str, len, format, args );
+}