Remove kernel32 dependency on user32 by implementing family of k32
functions as callouts to user32.

diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in
index ba34885..9f64aab 100644
--- a/dlls/kernel/Makefile.in
+++ b/dlls/kernel/Makefile.in
@@ -13,6 +13,7 @@
 	format_msg.c \
 	kernel_main.c \
 	stress.c \
+	string.c \
 	sync.c \
 	thunk.c \
 	time.c \
diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec
index 2b23718..8201bca 100644
--- a/dlls/kernel/kernel32.spec
+++ b/dlls/kernel/kernel32.spec
@@ -26,13 +26,13 @@
   7 register -i386 VxDCall6(long) VxDCall
   8 register -i386 VxDCall7(long) VxDCall
   9 register -i386 VxDCall8(long) VxDCall
- 10 forward k32CharToOemA user32.CharToOemA
- 11 forward k32CharToOemBuffA user32.CharToOemBuffA
- 12 forward k32OemToCharA user32.OemToCharA
- 13 forward k32OemToCharBuffA user32.OemToCharBuffA
- 14 forward k32LoadStringA user32.LoadStringA
- 15 forward k32wsprintfA user32.wsprintfA
- 16 forward k32wvsprintfA user32.wvsprintfA
+ 10 stdcall k32CharToOemA(str ptr) k32CharToOemA
+ 11 stdcall k32CharToOemBuffA(str ptr long) k32CharToOemBuffA
+ 12 stdcall k32OemToCharA(ptr ptr) k32OemToCharA
+ 13 stdcall k32OemToCharBuffA(ptr ptr long) k32OemToCharBuffA
+ 14 stdcall k32LoadStringA(long long ptr long) k32LoadStringA
+ 15 varargs k32wsprintfA(str str) k32wsprintfA
+ 16 stdcall k32wvsprintfA(ptr str ptr) k32wvsprintfA
  17 register -i386 CommonUnimpStub() CommonUnimpStub
  18 stdcall GetProcessDword(long long) GetProcessDword
  19 stub ThunkTheTemplateHandle
diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c
index 0a69fa9..2789616 100644
--- a/dlls/kernel/kernel_main.c
+++ b/dlls/kernel/kernel_main.c
@@ -110,72 +110,7 @@
  *
  * Entry point for kernel functions that do nothing.
  */
-LONG WINAPI KERNEL_nop(void) { return 0; }
-
-
-/***************************************************************************
- *
- * Win 2.x string functions now moved to USER
- *
- * We rather want to implement them here instead of doing Callouts
- */
-
-/***********************************************************************
- *		KERNEL_AnsiNext16 (KERNEL.77)
- */
-SEGPTR WINAPI KERNEL_AnsiNext16(SEGPTR current)
+LONG WINAPI KERNEL_nop(void)
 {
-    return (*(char *)MapSL(current)) ? current + 1 : current;
-}
-
-/***********************************************************************
- *		KERNEL_AnsiPrev16(KERNEL.78)
- */	
-SEGPTR WINAPI KERNEL_AnsiPrev16( SEGPTR start, SEGPTR current )
-{
-    return (current==start)?start:current-1;
-}
-
-/***********************************************************************
- *		KERNEL_AnsiUpper16 (KERNEL.79)
- */
-SEGPTR WINAPI KERNEL_AnsiUpper16( SEGPTR strOrChar )
-{
-    /* uppercase only one char if strOrChar < 0x10000 */
-    if (HIWORD(strOrChar))
-    {
-        char *s = MapSL(strOrChar);
-	while (*s) {
-	    *s = toupper(*s);
-	    s++;
-	}
-        return strOrChar;
-    }
-    else return toupper((char)strOrChar);
-}
-
-/***********************************************************************
- *		KERNEL_AnsiLower16 (KERNEL.80)
- */
-SEGPTR WINAPI KERNEL_AnsiLower16( SEGPTR strOrChar )
-{
-    /* lowercase only one char if strOrChar < 0x10000 */
-    if (HIWORD(strOrChar))
-    {
-        char *s = MapSL(strOrChar);
-	while (*s) {
-	    *s = tolower(*s);
-	    s++;
-	}
-        return strOrChar;
-    }
-    else return tolower((char)strOrChar);
-}
-
-/***********************************************************************
- *		KERNEL_lstrcmp16 (KERNEL.87)
- */
-INT16 WINAPI KERNEL_lstrcmp16( LPCSTR str1, LPCSTR str2 )
-{
-    return (INT16)strcmp( str1, str2 );
+    return 0;
 }
diff --git a/dlls/kernel/string.c b/dlls/kernel/string.c
new file mode 100644
index 0000000..4cdd139
--- /dev/null
+++ b/dlls/kernel/string.c
@@ -0,0 +1,184 @@
+/*
+ * Kernel string functions
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "winbase.h"
+#include "wine/winbase16.h"
+
+
+static INT WINAPI (*pLoadStringA)(HINSTANCE, UINT, LPSTR, INT);
+static INT WINAPI (*pwvsprintfA)(LPSTR, LPCSTR, va_list);
+
+/***********************************************************************
+ * Helper for k32 family functions
+ */
+static void *user32_proc_address(const char *proc_name)
+{
+    static HMODULE hUser32;
+
+    if(!hUser32) hUser32 = LoadLibraryA("user32.dll");
+    return GetProcAddress(hUser32, proc_name);
+}
+
+
+/***********************************************************************
+ *		KERNEL_lstrcmp16 (KERNEL.87)
+ */
+INT16 WINAPI KERNEL_lstrcmp16( LPCSTR str1, LPCSTR str2 )
+{
+    return (INT16)strcmp( str1, str2 );
+}
+
+
+/***********************************************************************
+ *		k32CharToOemBuffA   (KERNEL32.@)
+ */
+BOOL WINAPI k32CharToOemBuffA(LPCSTR s, LPSTR d, DWORD len)
+{
+    WCHAR *bufW;
+
+    if ((bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+    {
+        MultiByteToWideChar( CP_ACP, 0, s, len, bufW, len );
+        WideCharToMultiByte( CP_OEMCP, 0, bufW, len, d, len, NULL, NULL );
+        HeapFree( GetProcessHeap(), 0, bufW );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *		k32CharToOemA   (KERNEL32.@)
+ */
+BOOL WINAPI k32CharToOemA(LPCSTR s, LPSTR d)
+{
+    if (!s || !d) return TRUE;
+    return k32CharToOemBuffA( s, d, strlen(s) + 1 );
+}
+
+
+/***********************************************************************
+ *		k32OemToCharBuffA   (KERNEL32.@)
+ */
+BOOL WINAPI k32OemToCharBuffA(LPCSTR s, LPSTR d, DWORD len)
+{
+    WCHAR *bufW;
+
+    if ((bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+    {
+        MultiByteToWideChar( CP_OEMCP, 0, s, len, bufW, len );
+        WideCharToMultiByte( CP_ACP, 0, bufW, len, d, len, NULL, NULL );
+        HeapFree( GetProcessHeap(), 0, bufW );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *		k32OemToCharA   (KERNEL32.@)
+ */
+BOOL WINAPI k32OemToCharA(LPCSTR s, LPSTR d)
+{
+    return k32OemToCharBuffA( s, d, strlen(s) + 1 );
+}
+
+
+/**********************************************************************
+ *		k32LoadStringA   (KERNEL32.@)
+ */
+INT WINAPI k32LoadStringA(HINSTANCE instance, UINT resource_id,
+                          LPSTR buffer, INT buflen)
+{
+    if(!pLoadStringA) pLoadStringA = user32_proc_address("LoadStringA");
+    return pLoadStringA(instance, resource_id, buffer, buflen);
+}
+
+
+/***********************************************************************
+ *		k32wvsprintfA   (KERNEL32.@)
+ */
+INT WINAPI k32wvsprintfA(LPSTR buffer, LPCSTR spec, va_list args)
+{
+    if(!pwvsprintfA) pwvsprintfA = user32_proc_address("wvsprintfA");
+    return (*pwvsprintfA)(buffer, spec, args);
+}
+
+
+/***********************************************************************
+ *		k32wsprintfA   (KERNEL32.@)
+ */
+INT WINAPIV k32wsprintfA(LPSTR buffer, LPCSTR spec, ...)
+{
+    va_list args;
+    INT res;
+
+    va_start(args, spec);
+    res = k32wvsprintfA(buffer, spec, args);
+    va_end(args);
+    return res;
+}
+
+
+/***************************************************************************
+ *
+ * Win 2.x string functions now moved to USER
+ *
+ * We rather want to implement them here instead of doing Callouts
+ */
+
+/***********************************************************************
+ *		KERNEL_AnsiNext16 (KERNEL.77)
+ */
+SEGPTR WINAPI KERNEL_AnsiNext16(SEGPTR current)
+{
+    return (*(char *)MapSL(current)) ? current + 1 : current;
+}
+
+/***********************************************************************
+ *		KERNEL_AnsiPrev16(KERNEL.78)
+ */
+SEGPTR WINAPI KERNEL_AnsiPrev16( SEGPTR start, SEGPTR current )
+{
+    return (current==start)?start:current-1;
+}
+
+/***********************************************************************
+ *		KERNEL_AnsiUpper16 (KERNEL.79)
+ */
+SEGPTR WINAPI KERNEL_AnsiUpper16( SEGPTR strOrChar )
+{
+    /* uppercase only one char if strOrChar < 0x10000 */
+    if (HIWORD(strOrChar))
+    {
+        char *s = MapSL(strOrChar);
+        while (*s)
+        {
+            *s = toupper(*s);
+            s++;
+        }
+        return strOrChar;
+    }
+    else return toupper((char)strOrChar);
+}
+
+/***********************************************************************
+ *		KERNEL_AnsiLower16 (KERNEL.80)
+ */
+SEGPTR WINAPI KERNEL_AnsiLower16( SEGPTR strOrChar )
+{
+    /* lowercase only one char if strOrChar < 0x10000 */
+    if (HIWORD(strOrChar))
+    {
+        char *s = MapSL(strOrChar);
+        while (*s)
+        {
+            *s = tolower(*s);
+            s++;
+        }
+        return strOrChar;
+    }
+    else return tolower((char)strOrChar);
+}