Moved wsprintf functions to dlls/user.

diff --git a/dlls/commdlg/filedlg95.c b/dlls/commdlg/filedlg95.c
index 861477e..2839919 100644
--- a/dlls/commdlg/filedlg95.c
+++ b/dlls/commdlg/filedlg95.c
@@ -770,7 +770,7 @@
                 /* Prepend the current path */
                 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrCurrentDir);
                 if ((LPSTR)lParam!=NULL)
-                    wsnprintfA((LPSTR)lParam,(int)wParam,"%s\\%s",lpstrCurrentDir,lpstrPath);
+                    snprintf((LPSTR)lParam,(int)wParam,"%s\\%s",lpstrCurrentDir,lpstrPath);
                 reqSize=strlen(lpstrCurrentDir)+1+strlen(lpstrPath)+1;
             } 
 	    else 
diff --git a/dlls/crtdll/Makefile.in b/dlls/crtdll/Makefile.in
index 51852e0..d9907e7 100644
--- a/dlls/crtdll/Makefile.in
+++ b/dlls/crtdll/Makefile.in
@@ -4,7 +4,6 @@
 VPATH     = @srcdir@
 MODULE    = crtdll
 EXTRALIBS = -lwine_unicode
-IMPORTS   = ntdll
 
 LDDLLFLAGS = @LDDLLFLAGS@
 SYMBOLFILE = $(MODULE).tmp.o
diff --git a/dlls/crtdll/crtdll.spec b/dlls/crtdll/crtdll.spec
index 22e6ceb..4c22aa8 100644
--- a/dlls/crtdll/crtdll.spec
+++ b/dlls/crtdll/crtdll.spec
@@ -490,7 +490,7 @@
 @ cdecl strtol(str ptr long) strtol
 @ cdecl strtoul(str ptr long) strtoul
 @ cdecl strxfrm(ptr str long) strxfrm
-@ varargs swprintf(wstr wstr) wsprintfW
+@ stub swprintf
 @ stub swscanf
 @ cdecl system(str) CRTDLL_system
 @ cdecl tan(double) tan
@@ -508,7 +508,7 @@
 @ stub vfwprintf
 @ stub vprintf
 @ cdecl vsprintf(ptr str ptr) vsprintf
-@ cdecl vswprintf(ptr wstr ptr) CRTDLL_vswprintf
+@ stub vswprintf
 @ stub vwprintf
 @ forward wcscat ntdll.wcscat
 @ forward wcschr ntdll.wcschr
diff --git a/dlls/crtdll/crtdll_main.c b/dlls/crtdll/crtdll_main.c
index 6915ed8..0f4e5b4 100644
--- a/dlls/crtdll/crtdll_main.c
+++ b/dlls/crtdll/crtdll_main.c
@@ -598,15 +598,6 @@
 
 
 /*********************************************************************
- *                  vswprintf      (CRTDLL.501)
- */
-INT __cdecl CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args )
-{
-    return wvsprintfW( buffer, spec, args );
-}
-
-
-/*********************************************************************
  *                  longjmp        (CRTDLL.426)
  */
 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
diff --git a/dlls/kernel/debugger.c b/dlls/kernel/debugger.c
index ee0a0c2..07d6d74 100644
--- a/dlls/kernel/debugger.c
+++ b/dlls/kernel/debugger.c
@@ -4,10 +4,13 @@
  * Copyright (C) 1999 Alexandre Julliard
  */
 
+#include <stdio.h>
 #include <string.h>
 
 #include "winerror.h"
+#include "wine/winbase16.h"
 #include "server.h"
+#include "stackframe.h"
 #include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(debugstr);
@@ -229,3 +232,29 @@
     SERVER_END_REQ;
     return ret;
 }
+
+
+/***********************************************************************
+ *           _DebugOutput                    (KERNEL.328)
+ */
+void WINAPIV _DebugOutput( void )
+{
+    VA_LIST16 valist;
+    WORD flags;
+    SEGPTR spec;
+    char caller[101];
+
+    /* Decode caller address */
+    if (!GetModuleName16( GetExePtr(CURRENT_STACK16->cs), caller, sizeof(caller) ))
+        sprintf( caller, "%04X:%04X", CURRENT_STACK16->cs, CURRENT_STACK16->ip );
+
+    /* Build debug message string */
+    VA_START16( valist );
+    flags = VA_ARG16( valist, WORD );
+    spec  = VA_ARG16( valist, SEGPTR );
+    /* FIXME: cannot use wvsnprintf16 from kernel */
+    /* wvsnprintf16( temp, sizeof(temp), (LPCSTR)PTR_SEG_TO_LIN(spec), valist ); */
+
+    /* Output */
+    FIXME("%s %04x %s\n", caller, flags, debugstr_a(PTR_SEG_TO_LIN(spec)) );
+}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 5423063..f68a201 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -945,7 +945,7 @@
 @ cdecl -noimport strspn(str str) strspn
 @ cdecl -noimport strstr(str str) strstr
 @ cdecl -noimport strtol(str ptr long) strtol
-@ varargs swprintf(wstr wstr) wsprintfW
+@ stub swprintf
 @ stub tan
 @ cdecl tolower(long) tolower
 @ cdecl toupper(long) toupper
diff --git a/dlls/user/Makefile.in b/dlls/user/Makefile.in
index b4bc683..82831b7 100644
--- a/dlls/user/Makefile.in
+++ b/dlls/user/Makefile.in
@@ -20,7 +20,8 @@
 	resource.c \
 	text.c \
 	thunk.c \
-	user_main.c
+	user_main.c \
+	wsprintf.c
 
 RC_SRCS = \
 	resources/display.rc \
diff --git a/dlls/user/user.spec b/dlls/user/user.spec
index b85b729..5f51c97 100644
--- a/dlls/user/user.spec
+++ b/dlls/user/user.spec
@@ -398,7 +398,7 @@
 416 pascal16 TrackPopupMenu(word word s_word s_word s_word word ptr) TrackPopupMenu16
 417 pascal   GetMenuCheckMarkDimensions() GetMenuCheckMarkDimensions
 418 pascal16 SetMenuItemBitmaps(word word word word word) SetMenuItemBitmaps16
-420 pascal16 _wsprintf() WIN16_wsprintf16
+420 pascal16 _wsprintf() wsprintf16
 421 pascal16 wvsprintf(ptr str ptr) wvsprintf16
 422 pascal16 DlgDirSelectEx(word ptr word word) DlgDirSelectEx16
 423 pascal16 DlgDirSelectComboBoxEx(word ptr word word) DlgDirSelectComboBoxEx16
diff --git a/dlls/user/user32.spec b/dlls/user/user32.spec
index c38834e..f939bd4 100644
--- a/dlls/user/user32.spec
+++ b/dlls/user/user32.spec
@@ -651,3 +651,9 @@
 @ stdcall GetClipboardSequenceNumber () GetClipboardSequenceNumber
 @ stdcall AllowSetForegroundWindow (long) AllowSetForegroundWindow
 @ stdcall LockSetForegroundWindow (long) LockSetForegroundWindow
+
+###################################################
+# Extra useful functions not exported under Windows
+#
+@ stdcall wvsnprintfA(ptr long str ptr) wvsnprintfA
+@ stdcall wvsnprintfW(ptr long wstr ptr) wvsnprintfW
diff --git a/dlls/user/wsprintf.c b/dlls/user/wsprintf.c
new file mode 100644
index 0000000..ea20a52
--- /dev/null
+++ b/dlls/user/wsprintf.c
@@ -0,0 +1,607 @@
+/*
+ * wsprintf functions
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include "wine/winbase16.h"
+#include "windef.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "ldt.h"
+#include "stackframe.h"
+#include "global.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(string);
+
+
+#define WPRINTF_LEFTALIGN   0x0001  /* Align output on the left ('-' prefix) */
+#define WPRINTF_PREFIX_HEX  0x0002  /* Prefix hex with 0x ('#' prefix) */
+#define WPRINTF_ZEROPAD     0x0004  /* Pad with zeros ('0' prefix) */
+#define WPRINTF_LONG        0x0008  /* Long arg ('l' prefix) */
+#define WPRINTF_SHORT       0x0010  /* Short arg ('h' prefix) */
+#define WPRINTF_UPPER_HEX   0x0020  /* Upper-case hex ('X' specifier) */
+#define WPRINTF_WIDE        0x0040  /* Wide arg ('w' prefix) */
+
+typedef enum
+{
+    WPR_UNKNOWN,
+    WPR_CHAR,
+    WPR_WCHAR,
+    WPR_STRING,
+    WPR_WSTRING,
+    WPR_SIGNED,
+    WPR_UNSIGNED,
+    WPR_HEXA
+} WPRINTF_TYPE;
+
+typedef struct
+{
+    UINT         flags;
+    UINT         width;
+    UINT         precision;
+    WPRINTF_TYPE   type;
+} WPRINTF_FORMAT;
+
+typedef union {
+    WCHAR   wchar_view;
+    CHAR    char_view;
+    LPCSTR  lpcstr_view;
+    LPCWSTR lpcwstr_view;
+    INT     int_view;
+} WPRINTF_DATA;
+
+static const CHAR null_stringA[] = "(null)";
+static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
+
+/***********************************************************************
+ *           WPRINTF_ParseFormatA
+ *
+ * Parse a format specification. A format specification has the form:
+ *
+ * [-][#][0][width][.precision]type
+ *
+ * Return value is the length of the format specification in characters.
+ */
+static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
+{
+    LPCSTR p = format;
+
+    res->flags = 0;
+    res->width = 0;
+    res->precision = 0;
+    if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
+    if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
+    if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
+    while ((*p >= '0') && (*p <= '9'))  /* width field */
+    {
+        res->width = res->width * 10 + *p - '0';
+        p++;
+    }
+    if (*p == '.')  /* precision field */
+    {
+        p++;
+        while ((*p >= '0') && (*p <= '9'))
+        {
+            res->precision = res->precision * 10 + *p - '0';
+            p++;
+        }
+    }
+    if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
+    else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
+    else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
+    switch(*p)
+    {
+    case 'c':
+        res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
+        break;
+    case 'C':
+        res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
+        break;
+    case 'd':
+    case 'i':
+        res->type = WPR_SIGNED;
+        break;
+    case 's':
+        res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
+        break;
+    case 'S':
+        res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
+        break;
+    case 'u':
+        res->type = WPR_UNSIGNED;
+        break;
+    case 'X':
+        res->flags |= WPRINTF_UPPER_HEX;
+        /* fall through */
+    case 'x':
+        res->type = WPR_HEXA;
+        break;
+    default: /* unknown format char */
+        res->type = WPR_UNKNOWN;
+        p--;  /* print format as normal char */
+        break;
+    }
+    return (INT)(p - format) + 1;
+}
+
+
+/***********************************************************************
+ *           WPRINTF_ParseFormatW
+ *
+ * Parse a format specification. A format specification has the form:
+ *
+ * [-][#][0][width][.precision]type
+ *
+ * Return value is the length of the format specification in characters.
+ */
+static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
+{
+    LPCWSTR p = format;
+
+    res->flags = 0;
+    res->width = 0;
+    res->precision = 0;
+    if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
+    if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
+    if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
+    while ((*p >= '0') && (*p <= '9'))  /* width field */
+    {
+        res->width = res->width * 10 + *p - '0';
+        p++;
+    }
+    if (*p == '.')  /* precision field */
+    {
+        p++;
+        while ((*p >= '0') && (*p <= '9'))
+        {
+            res->precision = res->precision * 10 + *p - '0';
+            p++;
+        }
+    }
+    if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
+    else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
+    else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
+    switch((CHAR)*p)
+    {
+    case 'c':
+        res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
+        break;
+    case 'C':
+        res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
+        break;
+    case 'd':
+    case 'i':
+        res->type = WPR_SIGNED;
+        break;
+    case 's':
+        res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
+        break;
+    case 'S':
+        res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
+        break;
+    case 'u':
+        res->type = WPR_UNSIGNED;
+        break;
+    case 'X':
+        res->flags |= WPRINTF_UPPER_HEX;
+        /* fall through */
+    case 'x':
+        res->type = WPR_HEXA;
+        break;
+    default:
+        res->type = WPR_UNKNOWN;
+        p--;  /* print format as normal char */
+        break;
+    }
+    return (INT)(p - format) + 1;
+}
+
+
+/***********************************************************************
+ *           WPRINTF_GetLen
+ */
+static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
+                              LPSTR number, UINT maxlen )
+{
+    UINT len;
+
+    if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
+    if (format->width > maxlen) format->width = maxlen;
+    switch(format->type)
+    {
+    case WPR_CHAR:
+    case WPR_WCHAR:
+        return (format->precision = 1);
+    case WPR_STRING:
+        if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
+        for (len = 0; !format->precision || (len < format->precision); len++)
+            if (!*(arg->lpcstr_view + len)) break;
+        if (len > maxlen) len = maxlen;
+        return (format->precision = len);
+    case WPR_WSTRING:
+        if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
+        for (len = 0; !format->precision || (len < format->precision); len++)
+            if (!*(arg->lpcwstr_view + len)) break;
+        if (len > maxlen) len = maxlen;
+        return (format->precision = len);
+    case WPR_SIGNED:
+        len = sprintf( number, "%d", arg->int_view );
+        break;
+    case WPR_UNSIGNED:
+        len = sprintf( number, "%u", (UINT)arg->int_view );
+        break;
+    case WPR_HEXA:
+        len = sprintf( number,
+                       (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
+                       (UINT)arg->int_view);
+        break;
+    default:
+        return 0;
+    }
+    if (len > maxlen) len = maxlen;
+    if (format->precision < len) format->precision = len;
+    if (format->precision > maxlen) format->precision = maxlen;
+    if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
+        format->precision = format->width;
+    if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
+    return len;
+}
+
+/***********************************************************************
+ *           WPRINTF_ExtractVAPtr
+ */
+static WPRINTF_DATA WPRINTF_ExtractVAPtr( WPRINTF_FORMAT *format, va_list* args )
+{
+    WPRINTF_DATA result;
+    switch(format->type)
+    {
+        case WPR_WCHAR:
+            result.wchar_view = (WCHAR)va_arg( *args, int );break;
+        case WPR_CHAR:
+            result.char_view = (CHAR)va_arg( *args, int );  break;
+        case WPR_STRING:
+            result.lpcstr_view = va_arg( *args, LPCSTR);    break;
+        case WPR_WSTRING:
+            result.lpcwstr_view = va_arg( *args, LPCWSTR);  break;
+        case WPR_HEXA:
+        case WPR_SIGNED:
+        case WPR_UNSIGNED:
+            result.int_view = va_arg( *args, INT );         break;
+        default:
+            result.wchar_view = 0;                          break;
+    }
+    return result;
+}
+
+/***********************************************************************
+ *           wvsnprintf16   (Not a Windows API)
+ */
+static INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec,
+                           LPCVOID args )
+{
+    WPRINTF_FORMAT format;
+    LPSTR p = buffer;
+    UINT i, len;
+    CHAR number[20];
+    WPRINTF_DATA cur_arg;
+    SEGPTR seg_str;
+
+    while (*spec && (maxlen > 1))
+    {
+        if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
+        spec++;
+        if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
+        spec += WPRINTF_ParseFormatA( spec, &format );
+        switch(format.type)
+        {
+        case WPR_WCHAR:  /* No Unicode in Win16 */
+        case WPR_CHAR:
+            cur_arg.char_view = VA_ARG16( args, CHAR );
+            break;
+        case WPR_WSTRING:  /* No Unicode in Win16 */
+        case WPR_STRING:
+            seg_str = VA_ARG16( args, SEGPTR );
+            if (IsBadReadPtr16(seg_str, 1 )) cur_arg.lpcstr_view = "";
+            else cur_arg.lpcstr_view = PTR_SEG_TO_LIN( seg_str );
+            break;
+        case WPR_SIGNED:
+            if (!(format.flags & WPRINTF_LONG))
+            {
+                cur_arg.int_view = VA_ARG16( args, INT16 );
+                break;
+            }
+            /* fall through */
+        case WPR_HEXA:
+        case WPR_UNSIGNED:
+            if (format.flags & WPRINTF_LONG)
+                cur_arg.int_view = VA_ARG16( args, UINT );
+            else
+                cur_arg.int_view = VA_ARG16( args, UINT16 );
+            break;
+        case WPR_UNKNOWN:
+            continue;
+        }
+        len = WPRINTF_GetLen( &format, &cur_arg, number, maxlen - 1 );
+        if (!(format.flags & WPRINTF_LEFTALIGN))
+            for (i = format.precision; i < format.width; i++, maxlen--)
+                *p++ = ' ';
+        switch(format.type)
+        {
+        case WPR_WCHAR:  /* No Unicode in Win16 */
+        case WPR_CHAR:
+            *p= cur_arg.char_view;
+            if (*p != '\0') p++;
+            else if (format.width > 1) *p++ = ' ';
+            else len = 0;
+            break;
+        case WPR_WSTRING:  /* No Unicode in Win16 */
+        case WPR_STRING:
+            if (len) memcpy( p, cur_arg.lpcstr_view, len );
+            p += len;
+            break;
+        case WPR_HEXA:
+            if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
+            {
+                *p++ = '0';
+                *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
+                maxlen -= 2;
+                len -= 2;
+            }
+            /* fall through */
+        case WPR_SIGNED:
+        case WPR_UNSIGNED:
+            for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
+            if (len) memcpy( p, number, len );
+            p += len;
+            break;
+        case WPR_UNKNOWN:
+            continue;
+        }
+        if (format.flags & WPRINTF_LEFTALIGN)
+            for (i = format.precision; i < format.width; i++, maxlen--)
+                *p++ = ' ';
+        maxlen -= len;
+    }
+    *p = 0;
+    return (maxlen > 1) ? (INT)(p - buffer) : -1;
+}
+
+
+/***********************************************************************
+ *           wvsnprintfA   (Not a Windows API, but we export it from USER32 anyway)
+ */
+INT WINAPI wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, va_list args )
+{
+    WPRINTF_FORMAT format;
+    LPSTR p = buffer;
+    UINT i, len;
+    CHAR number[20];
+    WPRINTF_DATA argData;
+
+    TRACE("%p %u %s\n", buffer, maxlen, debugstr_a(spec));
+
+    while (*spec && (maxlen > 1))
+    {
+        if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
+        spec++;
+        if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
+        spec += WPRINTF_ParseFormatA( spec, &format );
+        argData = WPRINTF_ExtractVAPtr( &format, &args );
+        len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
+        if (!(format.flags & WPRINTF_LEFTALIGN))
+            for (i = format.precision; i < format.width; i++, maxlen--)
+                *p++ = ' ';
+        switch(format.type)
+        {
+        case WPR_WCHAR:
+            *p = argData.wchar_view;
+            if (*p != '\0') p++;
+            else if (format.width > 1) *p++ = ' ';
+            else len = 0;
+            break;
+        case WPR_CHAR:
+            *p = argData.char_view;
+            if (*p != '\0') p++;
+            else if (format.width > 1) *p++ = ' ';
+            else len = 0;
+            break;
+        case WPR_STRING:
+            memcpy( p, argData.lpcstr_view, len );
+            p += len;
+            break;
+        case WPR_WSTRING:
+            {
+                LPCWSTR ptr = argData.lpcwstr_view;
+                for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
+            }
+            break;
+        case WPR_HEXA:
+            if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
+            {
+                *p++ = '0';
+                *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
+                maxlen -= 2;
+                len -= 2;
+            }
+            /* fall through */
+        case WPR_SIGNED:
+        case WPR_UNSIGNED:
+            for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
+            memcpy( p, number, len );
+            p += len;
+            break;
+        case WPR_UNKNOWN:
+            continue;
+        }
+        if (format.flags & WPRINTF_LEFTALIGN)
+            for (i = format.precision; i < format.width; i++, maxlen--)
+                *p++ = ' ';
+        maxlen -= len;
+    }
+    *p = 0;
+    TRACE("%s\n",debugstr_a(buffer));
+    return (maxlen > 1) ? (INT)(p - buffer) : -1;
+}
+
+
+/***********************************************************************
+ *           wvsnprintfW   (Not a Windows API, but we export it from USER32 anyway)
+ */
+INT WINAPI wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, va_list args )
+{
+    WPRINTF_FORMAT format;
+    LPWSTR p = buffer;
+    UINT i, len;
+    CHAR number[20];
+    WPRINTF_DATA argData;
+
+    TRACE("%p %u %s\n", buffer, maxlen, debugstr_w(spec));
+
+    while (*spec && (maxlen > 1))
+    {
+        if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
+        spec++;
+        if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
+        spec += WPRINTF_ParseFormatW( spec, &format );
+        argData = WPRINTF_ExtractVAPtr( &format, &args );
+        len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
+        if (!(format.flags & WPRINTF_LEFTALIGN))
+            for (i = format.precision; i < format.width; i++, maxlen--)
+                *p++ = ' ';
+        switch(format.type)
+        {
+        case WPR_WCHAR:
+            *p = argData.wchar_view;
+            if (*p != '\0') p++;
+            else if (format.width > 1) *p++ = ' ';
+            else len = 0;
+            break;
+        case WPR_CHAR:
+            *p = argData.char_view;
+            if (*p != '\0') p++;
+            else if (format.width > 1) *p++ = ' ';
+            else len = 0;
+            break;
+        case WPR_STRING:
+            {
+                LPCSTR ptr = argData.lpcstr_view;
+                for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
+            }
+            break;
+        case WPR_WSTRING:
+            if (len) memcpy( p, argData.lpcwstr_view, len * sizeof(WCHAR) );
+            p += len;
+            break;
+        case WPR_HEXA:
+            if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
+            {
+                *p++ = '0';
+                *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
+                maxlen -= 2;
+                len -= 2;
+            }
+            /* fall through */
+        case WPR_SIGNED:
+        case WPR_UNSIGNED:
+            for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
+            for (i = 0; i < len; i++) *p++ = (WCHAR)number[i];
+            break;
+        case WPR_UNKNOWN:
+            continue;
+        }
+        if (format.flags & WPRINTF_LEFTALIGN)
+            for (i = format.precision; i < format.width; i++, maxlen--)
+                *p++ = ' ';
+        maxlen -= len;
+    }
+    *p = 0;
+    TRACE("%s\n",debugstr_w(buffer));
+    return (maxlen > 1) ? (INT)(p - buffer) : -1;
+}
+
+
+/***********************************************************************
+ *           wvsprintf16   (USER.421)
+ */
+INT16 WINAPI wvsprintf16( LPSTR buffer, LPCSTR spec, LPCVOID args )
+{
+    INT16 res;
+
+    TRACE("for %p got:\n",buffer);
+    res = wvsnprintf16( buffer, 1024, spec, args );
+    return ( res == -1 ) ? 1024 : res;
+}
+
+
+/***********************************************************************
+ *           wvsprintfA   (USER32.587)
+ */
+INT WINAPI wvsprintfA( LPSTR buffer, LPCSTR spec, va_list args )
+{
+    INT res = wvsnprintfA( buffer, 1024, spec, args );
+    return ( res == -1 ) ? 1024 : res;
+}
+
+
+/***********************************************************************
+ *           wvsprintfW   (USER32.588)
+ */
+INT WINAPI wvsprintfW( LPWSTR buffer, LPCWSTR spec, va_list args )
+{
+    INT res = wvsnprintfW( buffer, 1024, spec, args );
+    return ( res == -1 ) ? 1024 : res;
+}
+
+
+/***********************************************************************
+ *           wsprintf16   (USER.420)
+ */
+INT16 WINAPIV wsprintf16(void)
+{
+    VA_LIST16 valist;
+    INT16 res;
+    SEGPTR buffer, spec;
+
+    VA_START16( valist );
+    buffer = VA_ARG16( valist, SEGPTR );
+    spec   = VA_ARG16( valist, SEGPTR );
+    res = wvsnprintf16( (LPSTR)PTR_SEG_TO_LIN(buffer), 1024,
+                        (LPCSTR)PTR_SEG_TO_LIN(spec), valist );
+    VA_END16( valist );
+    return ( res == -1 ) ? 1024 : res;
+}
+
+
+/***********************************************************************
+ *           wsprintfA   (USER32.585)
+ */
+INT WINAPIV wsprintfA( LPSTR buffer, LPCSTR spec, ... )
+{
+    va_list valist;
+    INT res;
+
+    va_start( valist, spec );
+    res = wvsnprintfA( buffer, 1024, spec, valist );
+    va_end( valist );
+    return ( res == -1 ) ? 1024 : res;
+}
+
+
+/***********************************************************************
+ *           wsprintfW   (USER32.586)
+ */
+INT WINAPIV wsprintfW( LPWSTR buffer, LPCWSTR spec, ... )
+{
+    va_list valist;
+    INT res;
+
+    va_start( valist, spec );
+    res = wvsnprintfW( buffer, 1024, spec, valist );
+    va_end( valist );
+    return ( res == -1 ) ? 1024 : res;
+}
diff --git a/dlls/winmm/mci.c b/dlls/winmm/mci.c
index 59bea9c..8891512 100644
--- a/dlls/winmm/mci.c
+++ b/dlls/winmm/mci.c
@@ -735,7 +735,7 @@
 	    switch (dwRet & 0xFFFF0000ul) {
 	    case 0:
 	    case MCI_INTEGER_RETURNED:
-		wsnprintfA(lpstrRet, uRetLen, "%ld", data[1]);
+		snprintf(lpstrRet, uRetLen, "%ld", data[1]);
 		break;
 	    case MCI_RESOURCE_RETURNED:
 		/* return string which ID is HIWORD(data[1]), 
@@ -749,12 +749,12 @@
 		LoadStringA(wmd->hDrv, HIWORD(data[1]), lpstrRet, uRetLen);
 		break;
 	    case MCI_COLONIZED3_RETURN:
-		wsnprintfA(lpstrRet, uRetLen, "%d:%d:%d", 
+		snprintf(lpstrRet, uRetLen, "%d:%d:%d", 
 			 LOBYTE(LOWORD(data[1])), HIBYTE(LOWORD(data[1])), 
 			 LOBYTE(HIWORD(data[1])));
 		break;
 	    case MCI_COLONIZED4_RETURN:
-		wsnprintfA(lpstrRet, uRetLen, "%d:%d:%d:%d", 
+		snprintf(lpstrRet, uRetLen, "%d:%d:%d:%d", 
 			 LOBYTE(LOWORD(data[1])), HIBYTE(LOWORD(data[1])), 
 			 LOBYTE(HIWORD(data[1])), HIBYTE(HIWORD(data[1])));
 		break;
@@ -768,7 +768,7 @@
 		break;
 	    case MCI_INTEGER_RETURNED:
 		data[1] = *(LPDWORD)lpstrRet;
-		wsnprintfA(lpstrRet, uRetLen, "%ld", data[1]);
+		snprintf(lpstrRet, uRetLen, "%ld", data[1]);
 		break;
 	    default:
 		WARN("Oooch. MCI_STRING and HIWORD(dwRet)=%04x\n", HIWORD(dwRet));
@@ -778,7 +778,7 @@
 	case MCI_RECT:	
 	    if (dwRet & 0xFFFF0000ul)	
 		WARN("Oooch. MCI_STRING and HIWORD(dwRet)=%04x\n", HIWORD(dwRet));
-	    wsnprintfA(lpstrRet, uRetLen, "%ld %ld %ld %ld", 
+	    snprintf(lpstrRet, uRetLen, "%ld %ld %ld %ld", 
 		       data[1], data[2], data[3], data[4]);	
 	    break;
 	default:		ERR("oops\n");
diff --git a/dlls/winspool/Makefile.in b/dlls/winspool/Makefile.in
index b12f653..e24b1ff 100644
--- a/dlls/winspool/Makefile.in
+++ b/dlls/winspool/Makefile.in
@@ -4,7 +4,7 @@
 VPATH     = @srcdir@
 MODULE    = winspool.drv
 SOVERSION = 1.0
-IMPORTS   = gdi32 advapi32 kernel32 ntdll
+IMPORTS   = user32 gdi32 advapi32 kernel32 ntdll
 
 C_SRCS = \
 	info.c \
diff --git a/dlls/winspool/winspool.drv.spec b/dlls/winspool/winspool.drv.spec
index d4fd544..9f7100a 100644
--- a/dlls/winspool/winspool.drv.spec
+++ b/dlls/winspool/winspool.drv.spec
@@ -3,6 +3,7 @@
 file	winspool.drv
 init	WINSPOOL_EntryPoint
 
+import	user32.dll
 import	gdi32.dll
 import	advapi32.dll
 import	kernel32.dll