Index: crt/crt.rbuild
===================================================================
--- crt/crt.rbuild	(revision 47065)
+++ crt/crt.rbuild	(working copy)
@@ -56,6 +56,7 @@
 		<file>checkesp.c</file>
 		<file>cpp.c</file>
 		<file>cppexcept.c</file>
+		<file>except.c</file>
 		<file>matherr.c</file>
 		<if property="ARCH" value="i386">
 			<directory name="i386">
@@ -328,7 +329,6 @@
 		<file>gcvt.c</file>
 		<file>getenv.c</file>
 		<file>makepath.c</file>
-		<file>malloc.c</file>
 		<file>mbtowc.c</file>
 		<file>mbstowcs.c</file>
 		<file>obsol.c</file>
@@ -396,7 +396,6 @@
 		<file>ctype.c</file>
 		<file>itoa.c</file>
 		<file>itow.c</file>
-		<file>lasttok.c</file>
 		<file>scanf.c</file>
 		<file>splitp.c</file>
 		<file>strcoll.c</file>
@@ -417,6 +416,7 @@
 		<file>strtoi64.c</file>
 		<file>strtok.c</file>
 		<file>strtol.c</file>
+		<file>strtold.c</file>
 		<file>strtoul.c</file>
 		<file>strtoull.c</file>
 		<file>strupr.c</file>
Index: crt/except/amd64/seh.s
===================================================================
--- crt/except/amd64/seh.s	(revision 47065)
+++ crt/except/amd64/seh.s	(working copy)
@@ -17,11 +17,11 @@
 
 /* GLOBALS *******************************************************************/
 
-.globl __global_unwind2
-.globl __local_unwind2
-.globl __abnormal_termination
-.globl __except_handler2
-.globl __except_handler3
+.globl _global_unwind2
+.globl _local_unwind2
+.globl _abnormal_termination
+.globl _except_handler2
+.globl _except_handler3
 
 /* FUNCTIONS *****************************************************************/
 
@@ -31,26 +31,26 @@
 .endfunc
 
 .func _global_unwind2
-__global_unwind2:
+_global_unwind2:
     ret
 .endfunc
 
 .func _abnormal_termination
-__abnormal_termination:
+_abnormal_termination:
     ret
 .endfunc
 
 .func _local_unwind2
-__local_unwind2:
+_local_unwind2:
     ret
 .endfunc
 
 .func _except_handler2
-__except_handler2:
+_except_handler2:
     ret
 .endfunc
 
 .func _except_handler3
-__except_handler3:
+_except_handler3:
     ret
 .endfunc
Index: crt/except/cpp.c
===================================================================
--- crt/except/cpp.c	(revision 47065)
+++ crt/except/cpp.c	(working copy)
@@ -21,6 +21,7 @@
 
 #include <precomp.h>
 
+#include <wine/exception.h>
 #include <internal/wine/msvcrt.h>
 #include <internal/wine/cppexcept.h>
 
@@ -62,18 +63,18 @@
 
 #define THISCALL(func) __thiscall_ ## func
 #define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func)
-#define DEFINE_THISCALL_WRAPPER(func) \
-    extern void THISCALL(func)(); \
+#define DEFINE_THISCALL_WRAPPER(func,args) \
+    extern void THISCALL(func)(void); \
     __ASM_GLOBAL_FUNC(__thiscall_ ## func, \
                       "popl %eax\n\t" \
                       "pushl %ecx\n\t" \
                       "pushl %eax\n\t" \
-                      "jmp " __ASM_NAME(#func) )
+                      "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
 #else /* __i386__ */
 
 #define THISCALL(func) func
 #define THISCALL_NAME(func) __ASM_NAME(#func)
-#define DEFINE_THISCALL_WRAPPER(func) /* nothing */
+#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
 
 #endif /* __i386__ */
 
@@ -125,7 +126,7 @@
   _this->vtable = &MSVCRT_exception_vtable;
   if (*name)
   {
-    size_t name_len = strlen(*name) + 1;
+    unsigned int name_len = strlen(*name) + 1;
     _this->name = MSVCRT_malloc(name_len);
     memcpy(_this->name, *name, name_len);
     _this->do_free = TRUE;
@@ -140,7 +141,7 @@
 /******************************************************************
  *		??0exception@@QAE@ABQBD@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8)
 exception * __stdcall MSVCRT_exception_ctor(exception * _this, const char ** name)
 {
   TRACE("(%p,%s)\n", _this, *name);
@@ -149,9 +150,22 @@
 }
 
 /******************************************************************
+ *		??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
+ */
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12)
+exception * __stdcall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
+{
+  TRACE("(%p,%s)\n", _this, *name);
+  _this->vtable = &MSVCRT_exception_vtable;
+  _this->name = *name;
+  _this->do_free = FALSE;
+  return _this;
+}
+
+/******************************************************************
  *		??0exception@@QAE@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8)
 exception * __stdcall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
 {
   TRACE("(%p,%p)\n", _this, rhs);
@@ -171,7 +185,7 @@
 /******************************************************************
  *		??0exception@@QAE@XZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4)
 exception * __stdcall MSVCRT_exception_default_ctor(exception * _this)
 {
   static const char* empty = NULL;
@@ -184,7 +198,7 @@
 /******************************************************************
  *		??1exception@@UAE@XZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4)
 void __stdcall MSVCRT_exception_dtor(exception * _this)
 {
   TRACE("(%p)\n", _this);
@@ -195,7 +209,7 @@
 /******************************************************************
  *		??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals)
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8)
 exception * __stdcall MSVCRT_exception_opequals(exception * _this, const exception * rhs)
 {
   TRACE("(%p %p)\n", _this, rhs);
@@ -211,7 +225,7 @@
 /******************************************************************
  *		??_Eexception@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8)
 void * __stdcall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags)
 {
     TRACE("(%p %x)\n", _this, flags);
@@ -234,7 +248,7 @@
 /******************************************************************
  *		??_Gexception@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8)
 void * __stdcall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags)
 {
     TRACE("(%p %x)\n", _this, flags);
@@ -246,7 +260,7 @@
 /******************************************************************
  *		?what@exception@@UBEPBDXZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception)
+DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4)
 const char * __stdcall MSVCRT_what_exception(exception * _this)
 {
   TRACE("(%p) returning %s\n", _this, _this->name);
@@ -256,7 +270,7 @@
 /******************************************************************
  *		??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8)
 bad_typeid * __stdcall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
 {
   TRACE("(%p %p)\n", _this, rhs);
@@ -268,7 +282,7 @@
 /******************************************************************
  *		??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8)
 bad_typeid * __stdcall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
 {
   TRACE("(%p %s)\n", _this, name);
@@ -278,9 +292,18 @@
 }
 
 /******************************************************************
+ *		??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
+ */
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4)
+bad_typeid * __stdcall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this)
+{
+  return MSVCRT_bad_typeid_ctor( _this, "bad typeid" );
+}
+
+/******************************************************************
  *		??1bad_typeid@@UAE@XZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4)
 void __stdcall MSVCRT_bad_typeid_dtor(bad_typeid * _this)
 {
   TRACE("(%p)\n", _this);
@@ -290,7 +313,7 @@
 /******************************************************************
  *		??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8)
 bad_typeid * __stdcall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
 {
   TRACE("(%p %p)\n", _this, rhs);
@@ -301,7 +324,7 @@
 /******************************************************************
  *              ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8)
 void * __stdcall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags)
 {
     TRACE("(%p %x)\n", _this, flags);
@@ -324,7 +347,7 @@
 /******************************************************************
  *		??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8)
 void * __stdcall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
 {
     TRACE("(%p %x)\n", _this, flags);
@@ -336,7 +359,7 @@
 /******************************************************************
  *		??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8)
 __non_rtti_object * __stdcall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this,
                                                                  const __non_rtti_object * rhs)
 {
@@ -349,7 +372,7 @@
 /******************************************************************
  *		??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8)
 __non_rtti_object * __stdcall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
                                                             const char * name)
 {
@@ -362,7 +385,7 @@
 /******************************************************************
  *		??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4)
 void __stdcall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
 {
   TRACE("(%p)\n", _this);
@@ -372,7 +395,7 @@
 /******************************************************************
  *		??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals)
+DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8)
 __non_rtti_object * __stdcall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this,
                                                                 const __non_rtti_object *rhs)
 {
@@ -384,7 +407,7 @@
 /******************************************************************
  *		??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8)
 void * __stdcall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags)
 {
     TRACE("(%p %x)\n", _this, flags);
@@ -407,7 +430,7 @@
 /******************************************************************
  *		??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8)
 void * __stdcall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags)
 {
   TRACE("(%p %x)\n", _this, flags);
@@ -417,9 +440,10 @@
 }
 
 /******************************************************************
+ *		??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
  *		??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8)
 bad_cast * __stdcall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
 {
   TRACE("(%p %s)\n", _this, *name);
@@ -431,7 +455,7 @@
 /******************************************************************
  *		??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8)
 bad_cast * __stdcall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
 {
   TRACE("(%p %p)\n", _this, rhs);
@@ -441,9 +465,30 @@
 }
 
 /******************************************************************
+ *		??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
+ */
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8)
+bad_cast * __stdcall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name)
+{
+  TRACE("(%p %s)\n", _this, name);
+  EXCEPTION_ctor(_this, &name);
+  _this->vtable = &MSVCRT_bad_cast_vtable;
+  return _this;
+}
+
+/******************************************************************
+ *		??_Fbad_cast@@QAEXXZ (MSVCRT.@)
+ */
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4)
+bad_cast * __stdcall MSVCRT_bad_cast_default_ctor(bad_cast * _this)
+{
+  return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" );
+}
+
+/******************************************************************
  *		??1bad_cast@@UAE@XZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4)
 void __stdcall MSVCRT_bad_cast_dtor(bad_cast * _this)
 {
   TRACE("(%p)\n", _this);
@@ -453,7 +498,7 @@
 /******************************************************************
  *		??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8)
 bad_cast * __stdcall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
 {
   TRACE("(%p %p)\n", _this, rhs);
@@ -464,7 +509,7 @@
 /******************************************************************
  *              ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8)
 void * __stdcall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
 {
     TRACE("(%p %x)\n", _this, flags);
@@ -487,7 +532,7 @@
 /******************************************************************
  *		??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8)
 void * __stdcall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
 {
   TRACE("(%p %x)\n", _this, flags);
@@ -499,7 +544,7 @@
 /******************************************************************
  *		??8type_info@@QBEHABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals)
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8)
 int __stdcall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs)
 {
     int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
@@ -510,7 +555,7 @@
 /******************************************************************
  *		??9type_info@@QBEHABV0@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals)
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8)
 int __stdcall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs)
 {
     int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
@@ -521,7 +566,7 @@
 /******************************************************************
  *		?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before)
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8)
 int __stdcall MSVCRT_type_info_before(type_info * _this, const type_info * rhs)
 {
     int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
@@ -532,7 +577,7 @@
 /******************************************************************
  *		??1type_info@@UAE@XZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4)
 void __stdcall MSVCRT_type_info_dtor(type_info * _this)
 {
   TRACE("(%p)\n", _this);
@@ -542,7 +587,7 @@
 /******************************************************************
  *		?name@type_info@@QBEPBDXZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name)
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4)
 const char * __stdcall MSVCRT_type_info_name(type_info * _this)
 {
   if (!_this->name)
@@ -583,7 +628,7 @@
 /******************************************************************
  *		?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
  */
-DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name)
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4)
 const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this)
 {
   TRACE("(%p) returning %s\n", _this, _this->mangled);
@@ -591,7 +636,7 @@
 }
 
 /* Unexported */
-DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor)
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8)
 void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
 {
     TRACE("(%p %x)\n", _this, flags);
@@ -613,8 +658,24 @@
 
 /* vtables */
 
+#ifdef _WIN64
+
 #define __ASM_VTABLE(name,funcs) \
     __asm__(".data\n" \
+            "\t.align 8\n" \
+            "\t.quad " __ASM_NAME(#name "_rtti") "\n" \
+            "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \
+            __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \
+            "\t.quad " THISCALL_NAME(MSVCRT_ ## name ## _vector_dtor) "\n" \
+            funcs "\n\t.text");
+
+#define __ASM_EXCEPTION_VTABLE(name) \
+    __ASM_VTABLE(name, "\t.quad " THISCALL_NAME(MSVCRT_what_exception) )
+
+#else
+
+#define __ASM_VTABLE(name,funcs) \
+    __asm__(".data\n" \
             "\t.align 4\n" \
             "\t.long " __ASM_NAME(#name "_rtti") "\n" \
             "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \
@@ -625,6 +686,8 @@
 #define __ASM_EXCEPTION_VTABLE(name) \
     __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCRT_what_exception) )
 
+#endif /* _WIN64 */
+
 #ifndef __GNUC__
 void __asm_dummy_vtables(void) {
 #endif
Index: crt/except/cppexcept.c
===================================================================
--- crt/except/cppexcept.c	(revision 47065)
+++ crt/except/cppexcept.c	(working copy)
@@ -27,6 +27,7 @@
 #include <precomp.h>
 #include <stdarg.h>
 
+#include <wine/exception.h>
 #include <internal/wine/msvcrt.h>
 #include <internal/wine/cppexcept.h>
 
@@ -123,7 +124,6 @@
                  descr->tryblock[i].start_level, descr->tryblock[i].end_level,
                  descr->tryblock[i].catch_level, descr->tryblock[i].catchblock,
                  descr->tryblock[i].catchblock_count );
-
         for (j = 0; j < descr->tryblock[i].catchblock_count; j++)
         {
             const catchblock_info *ptr = &descr->tryblock[i].catchblock[j];
@@ -133,6 +133,10 @@
         }
     }
 #endif
+    if (descr->magic <= CXX_FRAME_MAGIC_VC6) return;
+    TRACE( "expect list: %p\n", descr->expect_list );
+    if (descr->magic <= CXX_FRAME_MAGIC_VC7) return;
+    TRACE( "flags: %08x\n", descr->flags );
 }
 
 /* check if the exception type is caught by a given catch block, and return the type that matched */
@@ -194,7 +198,7 @@
 /* unwind the local function up to a given trylevel */
 static void cxx_local_unwind( cxx_exception_frame* frame, const cxx_function_descr *descr, int last_level)
 {
-    void (*handler)();
+    void (*handler)(void);
     int trylevel = frame->trylevel;
 
     while (trylevel != last_level)
@@ -358,11 +362,16 @@
 {
     cxx_exception_type *exc_type;
 
-    if (descr->magic != CXX_FRAME_MAGIC)
+    if (descr->magic < CXX_FRAME_MAGIC_VC6 || descr->magic > CXX_FRAME_MAGIC_VC8)
     {
         ERR( "invalid frame magic %x\n", descr->magic );
         return ExceptionContinueSearch;
     }
+    if (descr->magic >= CXX_FRAME_MAGIC_VC8 &&
+        (descr->flags & FUNC_DESCR_SYNCHRONOUS) &&
+        (rec->ExceptionCode != CXX_EXCEPTION))
+        return ExceptionContinueSearch;  /* handle only c++ exceptions */
+
     if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND))
     {
         if (descr->unwind_count && !nested_trylevel) cxx_local_unwind( frame, descr, -1 );
@@ -374,7 +383,7 @@
     {
         exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
 
-        if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC &&
+        if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8 &&
                 exc_type->custom_handler)
         {
             return exc_type->custom_handler( rec, frame, context, dispatch,
@@ -408,14 +417,22 @@
                                       PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch );
 __ASM_GLOBAL_FUNC( __CxxFrameHandler,
                    "pushl $0\n\t"        /* nested_trylevel */
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                    "pushl $0\n\t"        /* nested_frame */
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                    "pushl %eax\n\t"      /* descr */
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                    "pushl 28(%esp)\n\t"  /* dispatch */
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                    "pushl 28(%esp)\n\t"  /* context */
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                    "pushl 28(%esp)\n\t"  /* frame */
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                    "pushl 28(%esp)\n\t"  /* rec */
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
                    "call " __ASM_NAME("cxx_frame_handler") "\n\t"
                    "add $28,%esp\n\t"
+                   __ASM_CFI(".cfi_adjust_cfa_offset -28\n\t")
                    "ret" )
 
 
@@ -435,14 +452,25 @@
 
 #endif  /* __i386__ */
 
+
 /*********************************************************************
+ *		__CppXcptFilter (MSVCRT.@)
+ */
+int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr)
+{
+    /* only filter c++ exceptions */
+    if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH;
+    return _XcptFilter( ex, ptr );
+}
+
+/*********************************************************************
  *		_CxxThrowException (MSVCRT.@)
  */
 void CDECL _CxxThrowException( exception *object, const cxx_exception_type *type )
 {
     ULONG_PTR args[3];
 
-    args[0] = CXX_FRAME_MAGIC;
+    args[0] = CXX_FRAME_MAGIC_VC6;
     args[1] = (ULONG_PTR)object;
     args[2] = (ULONG_PTR)type;
     RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
@@ -462,7 +490,7 @@
 
   if (rec->ExceptionCode == CXX_EXCEPTION &&
       rec->NumberParameters == 3 &&
-      rec->ExceptionInformation[0] == CXX_FRAME_MAGIC &&
+      rec->ExceptionInformation[0] == CXX_FRAME_MAGIC_VC6 &&
       rec->ExceptionInformation[2])
   {
     ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record;
Index: crt/except/except.c
===================================================================
--- crt/except/except.c	(revision 0)
+++ crt/except/except.c	(revision 0)
@@ -0,0 +1,220 @@
+/*
+ * msvcrt.dll exception handling
+ *
+ * Copyright 2000 Jon Griffiths
+ * Copyright 2005 Juan Lang
+ *
+ * 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
+ *
+ * FIXME: Incomplete support for nested exceptions/try block cleanup.
+ */
+
+#include <precomp.h>
+#include "excpt.h"
+#include <wine/exception.h>
+
+void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame);
+
+/* VC++ extensions to Win32 SEH */
+typedef struct _SCOPETABLE
+{
+  int previousTryLevel;
+  int (*lpfnFilter)(PEXCEPTION_POINTERS);
+  int (*lpfnHandler)(void);
+} SCOPETABLE, *PSCOPETABLE;
+
+typedef struct _MSVCRT_EXCEPTION_FRAME
+{
+  EXCEPTION_REGISTRATION_RECORD *prev;
+  void (*handler)(PEXCEPTION_RECORD, EXCEPTION_REGISTRATION_RECORD*,
+                  PCONTEXT, PEXCEPTION_RECORD);
+  PSCOPETABLE scopetable;
+  int trylevel;
+  int _ebp;
+  PEXCEPTION_POINTERS xpointers;
+} MSVCRT_EXCEPTION_FRAME;
+
+typedef struct
+{
+  int   gs_cookie_offset;
+  ULONG gs_cookie_xor;
+  int   eh_cookie_offset;
+  ULONG eh_cookie_xor;
+  SCOPETABLE entries[1];
+} SCOPETABLE_V4;
+
+#ifdef __i386__
+
+static const SCOPETABLE_V4 *get_scopetable_v4( MSVCRT_EXCEPTION_FRAME *frame, ULONG_PTR cookie )
+{
+    return (const SCOPETABLE_V4 *)((ULONG_PTR)frame->scopetable ^ cookie);
+}
+
+#if defined(__GNUC__)
+static inline void call_finally_block( void *code_block, void *base_ptr )
+{
+    __asm__ __volatile__ ("movl %1,%%ebp; call *%%eax"
+                          : : "a" (code_block), "g" (base_ptr));
+}
+
+static inline int call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *ebp )
+{
+    int ret;
+    __asm__ __volatile__ ("pushl %%ebp; pushl %3; movl %2,%%ebp; call *%%eax; popl %%ebp; popl %%ebp"
+                          : "=a" (ret)
+                          : "0" (func), "r" (ebp), "r" (arg)
+                          : "ecx", "edx", "memory" );
+    return ret;
+}
+static inline int call_unwind_func( int (*func)(void), void *ebp )
+{
+    int ret;
+    __asm__ __volatile__ ("pushl %%ebp\n\t"
+                          "pushl %%ebx\n\t"
+                          "pushl %%esi\n\t"
+                          "pushl %%edi\n\t"
+                          "movl %2,%%ebp\n\t"
+                          "call *%0\n\t"
+                          "popl %%edi\n\t"
+                          "popl %%esi\n\t"
+                          "popl %%ebx\n\t"
+                          "popl %%ebp"
+                          : "=a" (ret)
+                          : "0" (func), "r" (ebp)
+                          : "ecx", "edx", "memory" );
+    return ret;
+}
+#endif
+
+static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec,
+                                   EXCEPTION_REGISTRATION_RECORD* frame,
+                                   PCONTEXT context,
+                                   EXCEPTION_REGISTRATION_RECORD** dispatch)
+{
+  if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
+    return ExceptionContinueSearch;
+  *dispatch = frame;
+  return ExceptionCollidedUnwind;
+}
+
+void msvcrt_local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp )
+{
+    EXCEPTION_REGISTRATION_RECORD reg;
+    const SCOPETABLE_V4 *scopetable = get_scopetable_v4( frame, *cookie );
+
+    TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel);
+
+    /* Register a handler in case of a nested exception */
+    reg.Handler = (PEXCEPTION_ROUTINE)MSVCRT_nested_handler;
+    reg.Next = NtCurrentTeb()->NtTib.ExceptionList;
+    __wine_push_frame(&reg);
+
+    while (frame->trylevel != -2 && frame->trylevel != trylevel)
+    {
+        int level = frame->trylevel;
+        frame->trylevel = scopetable->entries[level].previousTryLevel;
+        if (!scopetable->entries[level].lpfnFilter)
+        {
+            TRACE( "__try block cleanup level %d handler %p ebp %p\n",
+                   level, scopetable->entries[level].lpfnHandler, ebp );
+            call_unwind_func( scopetable->entries[level].lpfnHandler, ebp );
+        }
+    }
+    __wine_pop_frame(&reg);
+    TRACE("unwound OK\n");
+}
+
+/*********************************************************************
+ *		_except_handler4_common (MSVCRT.@)
+ */
+int CDECL _except_handler4_common( ULONG *cookie, void (*check_cookie)(void),
+                                   EXCEPTION_RECORD *rec, MSVCRT_EXCEPTION_FRAME *frame,
+                                   CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
+{
+    int retval, trylevel;
+    EXCEPTION_POINTERS exceptPtrs;
+    const SCOPETABLE_V4 *scope_table = get_scopetable_v4( frame, *cookie );
+
+    TRACE( "exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x\n",
+           rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
+           frame->handler, context, dispatcher, *cookie, scope_table,
+           scope_table->gs_cookie_offset, scope_table->gs_cookie_xor,
+           scope_table->eh_cookie_offset, scope_table->eh_cookie_xor );
+
+    /* FIXME: no cookie validation yet */
+
+    if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
+    {
+        /* Unwinding the current frame */
+        msvcrt_local_unwind4( cookie, frame, -2, &frame->_ebp );
+        TRACE("unwound current frame, returning ExceptionContinueSearch\n");
+        return ExceptionContinueSearch;
+    }
+    else
+    {
+        /* Hunting for handler */
+        exceptPtrs.ExceptionRecord = rec;
+        exceptPtrs.ContextRecord = context;
+        *((DWORD *)frame-1) = (DWORD)&exceptPtrs;
+        trylevel = frame->trylevel;
+
+        while (trylevel != -2)
+        {
+            TRACE( "level %d prev %d filter %p\n", trylevel,
+                   scope_table->entries[trylevel].previousTryLevel,
+                   scope_table->entries[trylevel].lpfnFilter );
+            if (scope_table->entries[trylevel].lpfnFilter)
+            {
+                retval = call_filter( scope_table->entries[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp );
+
+                TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ?
+                      "CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ?
+                      "EXECUTE_HANDLER" : "CONTINUE_SEARCH");
+
+                if (retval == EXCEPTION_CONTINUE_EXECUTION)
+                    return ExceptionContinueExecution;
+
+                if (retval == EXCEPTION_EXECUTE_HANDLER)
+                {
+                    /* Unwind all higher frames, this one will handle the exception */
+                    _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame);
+                    msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp );
+
+                    /* Set our trylevel to the enclosing block, and call the __finally
+                     * code, which won't return
+                     */
+                    frame->trylevel = scope_table->entries[trylevel].previousTryLevel;
+                    TRACE("__finally block %p\n",scope_table->entries[trylevel].lpfnHandler);
+                    call_finally_block(scope_table->entries[trylevel].lpfnHandler, &frame->_ebp);
+                    ERR("Returned from __finally block - expect crash!\n");
+                }
+            }
+            trylevel = scope_table->entries[trylevel].previousTryLevel;
+        }
+    }
+    TRACE("reached -2, returning ExceptionContinueSearch\n");
+    return ExceptionContinueSearch;
+}
+
+#endif
+
+/******************************************************************
+ *		__uncaught_exception
+ */
+BOOL CDECL __uncaught_exception(void)
+{
+    return FALSE;
+}
+

Property changes on: crt\except\except.c
___________________________________________________________________
Added: svn:eol-style
   + native

Index: crt/except/xcptfil.c
===================================================================
--- crt/except/xcptfil.c	(revision 47065)
+++ crt/except/xcptfil.c	(working copy)
@@ -23,8 +23,8 @@
 /*
  * @implemented
  */
-int
-_XcptFilter(DWORD ExceptionCode,
+int CDECL
+_XcptFilter(NTSTATUS ExceptionCode,
             struct _EXCEPTION_POINTERS *  except)
 {
     LONG ret = EXCEPTION_CONTINUE_SEARCH;
@@ -61,7 +61,8 @@
         {
             if (handler != SIG_IGN)
             {
-                int i, float_signal = _FPE_INVALID;
+                unsigned int i;
+                int float_signal = _FPE_INVALID;
 
                 sighandlers[SIGFPE] = SIG_DFL;
                 for (i = 0; i < sizeof(float_exception_map) /
@@ -80,6 +81,7 @@
         }
         break;
     case EXCEPTION_ILLEGAL_INSTRUCTION:
+    case EXCEPTION_PRIV_INSTRUCTION:
         if ((handler = sighandlers[SIGILL]) != SIG_DFL)
         {
             if (handler != SIG_IGN)
@@ -94,14 +96,3 @@
     return ret;
 }
 
-int CDECL __CppXcptFilter(unsigned long ex, PEXCEPTION_POINTERS ptr)
-{
-     /* only filter c++ exceptions */
-     if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH;
-     return _XcptFilter( ex, ptr );
-}
-
-
-
-
-
Index: crt/float/i386/cntrlfp.c
===================================================================
--- crt/float/i386/cntrlfp.c	(revision 47065)
+++ crt/float/i386/cntrlfp.c	(working copy)
@@ -104,3 +104,25 @@
 
   return flags;
 }
+
+/*********************************************************************
+ *              _controlfp_s (MSVCRT.@)
+ */
+int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
+{
+#ifdef __i386__
+    unsigned int flags;
+
+    FIXME("(%p %u %u) semi-stub\n", cur, newval, mask);
+
+    flags = _control87( newval, mask & ~_EM_DENORMAL );
+
+    if(cur)
+        *cur = flags;
+
+    return 0;
+#else
+    FIXME(":Not Implemented!\n");
+    return 0;
+#endif
+}
Index: crt/include/internal/wine/cppexcept.h
===================================================================
--- crt/include/internal/wine/cppexcept.h	(revision 47065)
+++ crt/include/internal/wine/cppexcept.h	(working copy)
@@ -15,7 +15,7 @@
  *
  * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #ifndef __MSVCRT_CPPEXCEPT_H
@@ -23,71 +23,19 @@
 
 #include <pseh/pseh2.h>
 
+#define CXX_FRAME_MAGIC_VC6 0x19930520
+#define CXX_FRAME_MAGIC_VC7 0x19930521
+#define CXX_FRAME_MAGIC_VC8 0x19930522
+#define CXX_EXCEPTION       0xe06d7363
+
 /* Macros to define assembler functions somewhat portably */
 
-#define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"
-#define __ASM_NAME(name) "_" name
-
-#ifdef __GNUC__
-# define __ASM_GLOBAL_FUNC(name,code) \
-      __asm__( ".align 4\n\t" \
-               ".globl " __ASM_NAME(#name) "\n\t" \
-               __ASM_FUNC(#name) "\n" \
-               __ASM_NAME(#name) ":\n\t" \
-               code );
-#else  /* __GNUC__ */
-# define __ASM_GLOBAL_FUNC(name,code) \
-      void __asm_dummy_##name(void) { \
-          asm( ".align 4\n\t" \
-               ".globl " __ASM_NAME(#name) "\n\t" \
-               __ASM_FUNC(#name) "\n" \
-               __ASM_NAME(#name) ":\n\t" \
-               code ); \
-      }
-#endif  /* __GNUC__ */
-
 #define EH_NONCONTINUABLE   0x01
 #define EH_UNWINDING        0x02
 #define EH_EXIT_UNWIND      0x04
 #define EH_STACK_INVALID    0x08
 #define EH_NESTED_CALL      0x10
 
-#ifndef _M_ARM
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4733)
-#endif
-
-static inline EXCEPTION_REGISTRATION_RECORD *__wine_push_frame( EXCEPTION_REGISTRATION_RECORD *frame )
-{
-    frame->Next = (struct _EXCEPTION_REGISTRATION_RECORD *)__readfsdword(0);
-	__writefsdword(0, (unsigned long)frame);
-    return frame->Next;
-}
-
-static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTRATION_RECORD *frame )
-{
-	__writefsdword(0, (unsigned long)frame->Next);
-    return frame->Next;
-}
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#endif
-
-#define __TRY _SEH2_TRY
-#define __EXCEPT(func) _SEH2_EXCEPT(func(_SEH2_GetExceptionInformation()))
-#define __EXCEPT_PAGE_FAULT _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION)
-#define __EXCEPT_ALL _SEH2_EXCEPT(_SEH_EXECUTE_HANDLER)
-#define __ENDTRY _SEH2_END
-#define __FINALLY(func) _SEH2_FINALLY { func(!_SEH2_AbnormalTermination()); }
-
-#define CXX_FRAME_MAGIC    0x19930520
-#define CXX_EXCEPTION      0xe06d7363
-
 typedef void (*vtable_ptr)();
 
 /* type_info object, see cpp.c for inplementation */
@@ -117,10 +65,10 @@
 /* info about a single catch {} block */
 typedef struct __catchblock_info
 {
-    UINT       flags;         /* flags (see below) */
-    type_info *type_info;     /* C++ type caught by this block */
-    int        offset;        /* stack offset to copy exception object to */
-    void     (*handler)();    /* catch block handler code */
+    UINT             flags;         /* flags (see below) */
+    const type_info *type_info;     /* C++ type caught by this block */
+    int              offset;        /* stack offset to copy exception object to */
+    void           (*handler)(void);/* catch block handler code */
 } catchblock_info;
 #define TYPE_FLAG_CONST      1
 #define TYPE_FLAG_VOLATILE   2
@@ -129,31 +77,36 @@
 /* info about a single try {} block */
 typedef struct __tryblock_info
 {
-    int              start_level;      /* start trylevel of that block */
-    int              end_level;        /* end trylevel of that block */
-    int              catch_level;      /* initial trylevel of the catch block */
-    int              catchblock_count; /* count of catch blocks in array */
-    catchblock_info *catchblock;       /* array of catch blocks */
+    int                    start_level;      /* start trylevel of that block */
+    int                    end_level;        /* end trylevel of that block */
+    int                    catch_level;      /* initial trylevel of the catch block */
+    int                    catchblock_count; /* count of catch blocks in array */
+    const catchblock_info *catchblock;       /* array of catch blocks */
 } tryblock_info;
 
 /* info about the unwind handler for a given trylevel */
 typedef struct __unwind_info
 {
     int    prev;          /* prev trylevel unwind handler, to run after this one */
-    void (*handler)();    /* unwind handler */
+    void (*handler)(void);/* unwind handler */
 } unwind_info;
 
 /* descriptor of all try blocks of a given function */
 typedef struct __cxx_function_descr
 {
-    UINT           magic;          /* must be CXX_FRAME_MAGIC */
-    UINT           unwind_count;   /* number of unwind handlers */
-    unwind_info   *unwind_table;   /* array of unwind handlers */
-    UINT           tryblock_count; /* number of try blocks */
-    tryblock_info *tryblock;       /* array of try blocks */
-    UINT           unknown[3];
+    UINT                 magic;          /* must be CXX_FRAME_MAGIC */
+    UINT                 unwind_count;   /* number of unwind handlers */
+    const unwind_info   *unwind_table;   /* array of unwind handlers */
+    UINT                 tryblock_count; /* number of try blocks */
+    const tryblock_info *tryblock;       /* array of try blocks */
+    UINT                 ipmap_count;
+    const void          *ipmap;
+    const void          *expect_list;    /* expected exceptions list when magic >= VC7 */
+    UINT                 flags;          /* flags when magic >= VC8 */
 } cxx_function_descr;
 
+#define FUNC_DESCR_SYNCHRONOUS  1        /* synchronous exceptions only (built with /EHs) */
+
 typedef void (*cxx_copy_ctor)(void);
 
 /* offsets for computing the this pointer */
@@ -192,18 +145,20 @@
 typedef struct __cxx_exception_type
 {
     UINT                       flags;            /* TYPE_FLAG flags */
-    void                     (*destructor)();    /* exception object destructor */
+    void                     (*destructor)(void);/* exception object destructor */
     cxx_exc_custom_handler     custom_handler;   /* custom handler for this exception */
     const cxx_type_info_table *type_info_table;  /* list of types for this exception object */
 } cxx_exception_type;
 
-void _CxxThrowException(exception*,const cxx_exception_type*);
+void CDECL _CxxThrowException(exception*,const cxx_exception_type*);
+int CDECL _XcptFilter(NTSTATUS, PEXCEPTION_POINTERS);
+int CDECL __CppXcptFilter(NTSTATUS, PEXCEPTION_POINTERS);
 
 static inline const char *dbgstr_type_info( const type_info *info )
 {
     if (!info) return "{}";
-    return "{}";/*sprintf( "{vtable=%p name=%s (%s)}",
-                             info->vtable, info->mangled, info->name ? info->name : "" );*/
+    return wine_dbg_sprintf( "{vtable=%p name=%s (%s)}",
+                             info->vtable, info->mangled, info->name ? info->name : "" );
 }
 
 /* compute the this pointer for a base class of a given type */
Index: crt/include/internal/wine/msvcrt.h
===================================================================
--- crt/include/internal/wine/msvcrt.h	(revision 47065)
+++ crt/include/internal/wine/msvcrt.h	(working copy)
@@ -80,12 +80,14 @@
     unexpected_function             unexpected_handler;
     _se_translator_function         se_translator;
     EXCEPTION_RECORD               *exc_record;
+    struct localeinfo_struct       *locale;
 } MSVCRT_thread_data;
 
 extern MSVCRT_thread_data *msvcrt_get_thread_data(void);
 
 extern int MSVCRT_current_lc_all_cp;
-
+extern WORD MSVCRT__ctype [257];
+_locale_t get_locale(void);
 void _purecall(void);
 void   MSVCRT__set_errno(int);
 char*  msvcrt_strndup(const char*,unsigned int);
Index: crt/locale/locale.c
===================================================================
--- crt/locale/locale.c	(revision 47065)
+++ crt/locale/locale.c	(working copy)
@@ -2,12 +2,27 @@
  * Some stuff takem from wine msvcrt\locale.c
  *
  * Copyright 2000 Jon Griffiths
+ *
+ * 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 <precomp.h>
 #include <locale.h>
-
+#include <internal/wine/msvcrt.h>
 #include "mbctype.h"
+#include "mbstring.h"
 
 // mtdll.h
 #define _SETLOCALE_LOCK 19
@@ -26,99 +41,28 @@
  * string to produce lc_all.
  */
 #define MAX_ELEM_LEN 64 /* Max length of country/language/CP string */
-
+#define MAX_LOCALE_LENGTH 256
+_locale_t MSVCRT_locale = NULL;
 unsigned char _mbctype[257] = { 0 };
 int g_mbcp_is_multibyte = 0;
-
-/* It seems that the data about valid trail bytes is not available from kernel32
- * so we have to store is here. The format is the same as for lead bytes in CPINFO */
-struct cp_extra_info_t
-{
-    int cp;
-    BYTE TrailBytes[MAX_LEADBYTES];
-};
-
-static struct cp_extra_info_t g_cpextrainfo[] =
-{
-    {932, {0x40, 0x7e, 0x80, 0xfc, 0, 0}},
-    {936, {0x40, 0xfe, 0, 0}},
-    {949, {0x41, 0xfe, 0, 0}},
-    {950, {0x40, 0x7e, 0xa1, 0xfe, 0, 0}},
-    {1361, {0x31, 0x7e, 0x81, 0xfe, 0, 0}},
-    {20932, {1, 255, 0, 0}},  /* seems to give different results on different systems */
-    {0, {1, 255, 0, 0}}       /* match all with FIXME */
-};
-
-
 char MSVCRT_current_lc_all[MAX_LOCALE_LENGTH] = { 0 };
 LCID MSVCRT_current_lc_all_lcid = 0;
 int MSVCRT___lc_codepage = 0;
 int MSVCRT___lc_collate_cp = 0;
 HANDLE MSVCRT___lc_handle[MSVCRT_LC_MAX - MSVCRT_LC_MIN + 1] = { 0 };
+unsigned char charmax = CHAR_MAX;
 
 /* MT */
 #define LOCK_LOCALE   _mlock(_SETLOCALE_LOCK);
 #define UNLOCK_LOCALE _munlock(_SETLOCALE_LOCK);
 
 #define MSVCRT_LEADBYTE  0x8000
+#define MSVCRT_C1_DEFINED 0x200
 
-typedef struct {
-  char search_language[MAX_ELEM_LEN];
-  char search_country[MAX_ELEM_LEN];
-  char search_codepage[MAX_ELEM_LEN];
-  char found_language[MAX_ELEM_LEN];
-  char found_country[MAX_ELEM_LEN];
-  char found_codepage[MAX_ELEM_LEN];
-  unsigned int match_flags;
-  LANGID found_lang_id;
-} locale_search_t;
-
 unsigned int __setlc_active;
 unsigned int __unguarded_readlc_active;
 int _current_category;	/* used by setlocale */
 const char *_current_locale;
-
-
-int parse_locale(const char *locale, char *lang, char *country, char *code_page);
-
-#define _C_ _CONTROL
-#define _S_ _SPACE
-#define _P_ _PUNCT
-#define _D_ _DIGIT
-#define _H_ _HEX
-#define _U_ _UPPER
-#define _L_ _LOWER
-
-WORD MSVCRT__ctype [257] = {
-  0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
-  _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
-  _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_BLANK,
-  _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
-  _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
-  _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
-  _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
-  _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
-  _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
-  _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
-  _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
-  _C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* Internal: Current ctype table for locale */
-WORD MSVCRT_current_ctype[257];
-
-/* pctype is used by macros in the Win32 headers. It must point
- * To a table of flags exactly like ctype. To allow locale
- * changes to affect ctypes (i.e. isleadbyte), we use a second table
- * and update its flags whenever the current locale changes.
- */
-WORD* MSVCRT__pctype = MSVCRT_current_ctype + 1;
-
 /* Friendly country strings & iso codes for synonym support.
  * Based on MS documentation for setlocale().
  */
@@ -140,18 +84,13 @@
   "America","US"
 };
 
-/* Note: Flags are weighted in order of matching importance */
-#define FOUND_LANGUAGE         0x4
-#define FOUND_COUNTRY          0x2
-#define FOUND_CODEPAGE         0x1
-
 /* INTERNAL: Map a synonym to an ISO code */
 static void remap_synonym(char *name)
 {
-  size_t i;
+  unsigned int i;
   for (i = 0; i < sizeof(_country_synonyms)/sizeof(char*); i += 2 )
   {
-    if (!_stricmp(_country_synonyms[i],name))
+    if (!strcasecmp(_country_synonyms[i],name))
     {
       TRACE(":Mapping synonym %s to %s\n",name,_country_synonyms[i+1]);
       name[0] = _country_synonyms[i+1][0];
@@ -162,6 +101,22 @@
   }
 }
 
+/* Note: Flags are weighted in order of matching importance */
+#define FOUND_LANGUAGE         0x4
+#define FOUND_COUNTRY          0x2
+#define FOUND_CODEPAGE         0x1
+
+typedef struct {
+  char search_language[MAX_ELEM_LEN];
+  char search_country[MAX_ELEM_LEN];
+  char search_codepage[MAX_ELEM_LEN];
+  char found_language[MAX_ELEM_LEN];
+  char found_country[MAX_ELEM_LEN];
+  char found_codepage[MAX_ELEM_LEN];
+  unsigned int match_flags;
+  LANGID found_lang_id;
+} locale_search_t;
+
 #define CONTINUE_LOOKING TRUE
 #define STOP_LOOKING     FALSE
 
@@ -173,10 +128,9 @@
   if (!buff[0] || !cmp[0])
     return 0;
   /* Partial matches are allowed, e.g. "Germ" matches "Germany" */
-  return !_strnicmp(cmp, buff, strlen(cmp));
+  return !strncasecmp(cmp, buff, strlen(cmp));
 }
 
-
 static BOOL CALLBACK
 find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LONG_PTR lParam)
 {
@@ -244,396 +198,1108 @@
   return CONTINUE_LOOKING;
 }
 
+extern int atoi(const char *);
+
 /* Internal: Find the LCID for a locale specification */
-static LCID MSVCRT_locale_to_LCID(locale_search_t* locale)
+static LCID MSVCRT_locale_to_LCID(const char *locale)
 {
-  LCID lcid;
-  EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR)RT_STRING,
-			 (LPCSTR)LOCALE_ILANGUAGE,find_best_locale_proc,
-			 (LONG_PTR)locale);
+    LCID lcid;
+    locale_search_t search;
+    char *cp, *region;
 
-  if (!locale->match_flags)
-    return 0;
+    memset(&search, 0, sizeof(locale_search_t));
 
-  /* If we were given something that didn't match, fail */
-  if (locale->search_country[0] && !(locale->match_flags & FOUND_COUNTRY))
-    return 0;
+    cp = strchr(locale, '.');
+    region = strchr(locale, '_');
 
-  lcid =  MAKELCID(locale->found_lang_id, SORT_DEFAULT);
+    lstrcpynA(search.search_language, locale, MAX_ELEM_LEN);
+    if(region) {
+        lstrcpynA(search.search_country, region+1, MAX_ELEM_LEN);
+        if(region-locale < MAX_ELEM_LEN)
+            search.search_language[region-locale] = '\0';
+    } else
+        search.search_country[0] = '\0';
 
-  /* Populate partial locale, translating LCID to locale string elements */
-  if (!locale->found_codepage[0])
-  {
-    /* Even if a codepage is not enumerated for a locale
-     * it can be set if valid */
-    if (locale->search_codepage[0])
-    {
-      if (IsValidCodePage(atoi(locale->search_codepage)))
-        memcpy(locale->found_codepage,locale->search_codepage,MAX_ELEM_LEN);
-      else
-      {
-        /* Special codepage values: OEM & ANSI */
-        if (_stricmp(locale->search_codepage,"OCP"))
-        {
-          GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
-                         locale->found_codepage, MAX_ELEM_LEN);
+    if(cp) {
+        lstrcpynA(search.search_codepage, cp+1, MAX_ELEM_LEN);
+        if(cp-region-1 < MAX_ELEM_LEN)
+          search.search_country[cp-region-1] = '\0';
+        if(cp-locale < MAX_ELEM_LEN)
+            search.search_language[cp-locale] = '\0';
+    } else
+        search.search_codepage[0] = '\0';
+
+    /* FIXME:  MSVCRT_locale_to_LCID is not finding remaped values */
+    remap_synonym(search.search_country);
+
+    EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR)RT_STRING,
+            (LPCSTR)LOCALE_ILANGUAGE,find_best_locale_proc,
+            (LONG_PTR)&search);
+
+    if (!search.match_flags)
+        return -1;
+
+    /* If we were given something that didn't match, fail */
+    if (search.search_country[0] && !(search.match_flags & FOUND_COUNTRY))
+        return -1;
+
+    lcid =  MAKELCID(search.found_lang_id, SORT_DEFAULT);
+
+    /* Populate partial locale, translating LCID to locale string elements */
+    if (!search.found_codepage[0]) {
+        /* Even if a codepage is not enumerated for a locale
+         * it can be set if valid */
+        if (search.search_codepage[0]) {
+            if (IsValidCodePage(atoi(search.search_codepage)))
+                memcpy(search.found_codepage,search.search_codepage,MAX_ELEM_LEN);
+            else {
+                /* Special codepage values: OEM & ANSI */
+                if (strcasecmp(search.search_codepage,"OCP")) {
+                    GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
+                            search.found_codepage, MAX_ELEM_LEN);
+                } else if (strcasecmp(search.search_codepage,"ACP")) {
+                    GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
+                            search.found_codepage, MAX_ELEM_LEN);
+                } else
+                    return -1;
+
+                if (!atoi(search.found_codepage))
+                    return -1;
+            }
+        } else {
+            /* Prefer ANSI codepages if present */
+            GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
+                    search.found_codepage, MAX_ELEM_LEN);
+            if (!search.found_codepage[0] || !atoi(search.found_codepage))
+                GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
+                        search.found_codepage, MAX_ELEM_LEN);
         }
-        if (_stricmp(locale->search_codepage,"ACP"))
-        {
-          GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
-                         locale->found_codepage, MAX_ELEM_LEN);
+    }
+
+    GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE,
+            search.found_language, MAX_ELEM_LEN);
+    GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY|LOCALE_NOUSEROVERRIDE,
+            search.found_country, MAX_ELEM_LEN);
+    return lcid;
+}
+
+/* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */
+static BOOL update_threadlocinfo_category(LCID lcid, _locale_t loc, int category)
+{
+    char buf[256], *p;
+    int len;
+
+    if(GetLocaleInfoA(lcid, LOCALE_ILANGUAGE, buf, 256)) {
+        p = buf;
+
+        loc->locinfo->lc_id[category].wLanguage = 0;
+        while(*p) {
+            loc->locinfo->lc_id[category].wLanguage *= 16;
+
+            if(*p <= '9')
+                loc->locinfo->lc_id[category].wLanguage += *p-'0';
+            else
+                loc->locinfo->lc_id[category].wLanguage += *p-'a'+10;
+
+            p++;
         }
-        else
-          return 0;
 
-        if (!atoi(locale->found_codepage))
-           return 0;
-      }
+        loc->locinfo->lc_id[category].wCountry =
+            loc->locinfo->lc_id[category].wLanguage;
     }
-    else
-    {
-      /* Prefer ANSI codepages if present */
-      GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
-                     locale->found_codepage, MAX_ELEM_LEN);
-      if (!locale->found_codepage[0] || !atoi(locale->found_codepage))
-          GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
-                         locale->found_codepage, MAX_ELEM_LEN);
+
+    if(GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, buf, 256))
+        loc->locinfo->lc_id[category].wCodePage = atoi(buf);
+
+    loc->locinfo->lc_handle[category] = lcid;
+
+    len = 0;
+    len += GetLocaleInfoA(lcid, LOCALE_SLANGUAGE, buf, 256);
+    buf[len-1] = '_';
+    len += GetLocaleInfoA(lcid, LOCALE_SCOUNTRY, &buf[len], 256-len);
+    buf[len-1] = '.';
+    len += GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, &buf[len], 256-len);
+
+    loc->locinfo->lc_category[category].locale = malloc(sizeof(char[len]));
+    loc->locinfo->lc_category[category].refcount = malloc(sizeof(int));
+    if(!loc->locinfo->lc_category[category].locale
+            || !loc->locinfo->lc_category[category].refcount) {
+        free(loc->locinfo->lc_category[category].locale);
+        free(loc->locinfo->lc_category[category].refcount);
+        loc->locinfo->lc_category[category].locale = NULL;
+        loc->locinfo->lc_category[category].refcount = NULL;
+        return TRUE;
     }
-  }
-  GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE,
-                 locale->found_language, MAX_ELEM_LEN);
-  GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY|LOCALE_NOUSEROVERRIDE,
-                 locale->found_country, MAX_ELEM_LEN);
-  return lcid;
+    memcpy(loc->locinfo->lc_category[category].locale, buf, sizeof(char[len]));
+    *loc->locinfo->lc_category[category].refcount = 1;
+
+    return FALSE;
 }
 
-/* INTERNAL: Set ctype behaviour for a codepage */
-static void msvcrt_set_ctype(unsigned int codepage, LCID lcid)
-{
-  CPINFO cp;
+/* INTERNAL: swap pointers values */
+static inline void swap_pointers(void **p1, void **p2) {
+    void *hlp;
 
-  memset(&cp, 0, sizeof(CPINFO));
+    hlp = *p1;
+    *p1 = *p2;
+    *p2 = hlp;
+}
 
-  if (GetCPInfo(codepage, &cp))
-  {
-    int i;
-    char str[3];
-    unsigned char *traverse = cp.LeadByte;
+/* INTERNAL: returns _locale_t struct for current locale */
+_locale_t get_locale(void) {
+    MSVCRT_thread_data *data = msvcrt_get_thread_data();
 
-    memset(MSVCRT_current_ctype, 0, sizeof(MSVCRT__ctype));
-    MSVCRT___lc_codepage = codepage;
-    MSVCRT___lc_collate_cp = codepage;
+    if(!data || !data->locale)
+        return MSVCRT_locale;
 
-    /* Switch ctype macros to MBCS if needed */
-    __mb_cur_max = cp.MaxCharSize;
+    return data->locale;
+}
 
-    /* Set remaining ctype flags: FIXME: faster way to do this? */
-    str[1] = str[2] = 0;
-    for (i = 0; i < 256; i++)
-    {
-      if (!(MSVCRT__pctype[i] & MSVCRT_LEADBYTE))
-      {
-        str[0] = i;
-        GetStringTypeA(lcid, CT_CTYPE1, str, 1, MSVCRT__pctype + i);
-      }
+/* INTERNAL: constructs string returned by setlocale */
+static inline char* construct_lc_all(_locale_t cur) {
+    static char current_lc_all[MAX_LOCALE_LENGTH];
+
+    int i;
+
+    for(i=MSVCRT_LC_MIN+1; i<MSVCRT_LC_MAX; i++) {
+        if(strcmp(cur->locinfo->lc_category[i].locale,
+                    cur->locinfo->lc_category[i+1].locale))
+            break;
     }
 
-    /* Set leadbyte flags */
-    while (traverse[0] || traverse[1])
-    {
-      for( i = traverse[0]; i <= traverse[1]; i++ )
-        MSVCRT_current_ctype[i+1] |= MSVCRT_LEADBYTE;
-      traverse += 2;
-    };
-  }
+    if(i==MSVCRT_LC_MAX)
+        return cur->locinfo->lc_category[MSVCRT_LC_COLLATE].locale;
+
+    sprintf(current_lc_all,
+            "LC_COLLATE=%s;LC_CTYPE=%s;LC_MONETARY=%s;LC_NUMERIC=%s;LC_TIME=%s",
+            cur->locinfo->lc_category[MSVCRT_LC_COLLATE].locale,
+            cur->locinfo->lc_category[MSVCRT_LC_CTYPE].locale,
+            cur->locinfo->lc_category[MSVCRT_LC_MONETARY].locale,
+            cur->locinfo->lc_category[MSVCRT_LC_NUMERIC].locale,
+            cur->locinfo->lc_category[MSVCRT_LC_TIME].locale);
+
+    return current_lc_all;
 }
 
 
-/*
- * @implemented
+/*********************************************************************
+ *		wsetlocale (MSVCRT.@)
  */
-char *setlocale(int category, const char *locale)
+MSVCRT_wchar_t* CDECL _wsetlocale(int category, const MSVCRT_wchar_t* locale)
 {
-  LCID lcid = 0;
-  locale_search_t lc;
-  int haveLang, haveCountry, haveCP;
-  char* next;
-  int lc_all = 0;
+  static MSVCRT_wchar_t fake[] = {
+    'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ',
+    'S','t','a','t','e','s','.','1','2','5','2',0 };
 
-  TRACE("(%d %s)\n",category,locale);
+  FIXME("%d %s\n", category, debugstr_w(locale));
 
-  if (category < MSVCRT_LC_MIN || category > MSVCRT_LC_MAX)
-    return NULL;
+  return fake;
+}
 
-  if (locale == NULL)
-  {
-    /* Report the current Locale */
-    return MSVCRT_current_lc_all;
-  }
+/*********************************************************************
+ *		_Getdays (MSVCRT.@)
+ */
+const char* CDECL _Getdays(void)
+{
+  static const char MSVCRT_days[] = ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:"
+                            "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
+  /* FIXME: Use locale */
+  TRACE("(void) semi-stub\n");
+  return MSVCRT_days;
+}
 
-  LOCK_LOCALE;
+/*********************************************************************
+ *		_Getmonths (MSVCRT.@)
+ */
+const char* CDECL _Getmonths(void)
+{
+  static const char MSVCRT_months[] = ":Jan:January:Feb:February:Mar:March:Apr:"
+                "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:"
+                "October:Nov:November:Dec:December";
+  /* FIXME: Use locale */
+  TRACE("(void) semi-stub\n");
+  return MSVCRT_months;
+}
 
-  if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_')
-  {
-    WARN(":restore previous locale not implemented!\n");
-    /* FIXME: Easiest way to do this is parse the string and
-     * call this function recursively with its elements,
-     * Where they differ for each lc_ type.
-     */
-    UNLOCK_LOCALE;
-    return MSVCRT_current_lc_all;
-  }
+/*********************************************************************
+ *		_Gettnames (MSVCRT.@)
+ */
+const char* CDECL _Gettnames(void)
+{
+  /* FIXME: */
+  TRACE("(void) stub\n");
+  return "";
+}
 
-  /* Default Locale: Special case handling */
-  if (!strlen(locale) || ((toupper(locale[0]) == 'C') && !locale[1]))
-  {
-    MSVCRT_current_lc_all[0] = 'C';
-    MSVCRT_current_lc_all[1] = '\0';
-    MSVCRT___lc_codepage = GetACP();
-    MSVCRT___lc_collate_cp = GetACP();
+/*********************************************************************
+ *		_Strftime (MSVCRT.@)
+ */
+const char* CDECL _Strftime(char *out, unsigned int len, const char *fmt,
+                            const void *tm, void *foo)
+{
+  /* FIXME: */
+  TRACE("(%p %d %s %p %p) stub\n", out, len, fmt, tm, foo);
+  return "";
+}
 
-    switch (category) {
-    case MSVCRT_LC_ALL:
-      lc_all = 1; /* Fall through all cases ... */
-    case MSVCRT_LC_COLLATE:
-      if (!lc_all) break;
-    case MSVCRT_LC_CTYPE:
-      /* Restore C locale ctype info */
-      __mb_cur_max = 1;
-      memcpy(MSVCRT_current_ctype, MSVCRT__ctype, sizeof(MSVCRT__ctype));
-      if (!lc_all) break;
-    case MSVCRT_LC_MONETARY:
-      if (!lc_all) break;
-    case MSVCRT_LC_NUMERIC:
-      if (!lc_all) break;
-    case MSVCRT_LC_TIME:
-      break;
+/*********************************************************************
+ *		__crtLCMapStringA (MSVCRT.@)
+ */
+int CDECL __crtLCMapStringA(
+  LCID lcid, DWORD mapflags, const char* src, int srclen, char* dst,
+  int dstlen, unsigned int codepage, int xflag
+) {
+  FIXME("(lcid %x, flags %x, %s(%d), %p(%d), %x, %d), partial stub!\n",
+        lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag);
+  /* FIXME: A bit incorrect. But msvcrt itself just converts its
+   * arguments to wide strings and then calls LCMapStringW
+   */
+  return LCMapStringA(lcid,mapflags,src,srclen,dst,dstlen);
+}
+
+/*********************************************************************
+ *		__crtCompareStringA (MSVCRT.@)
+ */
+int CDECL __crtCompareStringA( LCID lcid, DWORD flags, const char *src1, int len1,
+                               const char *src2, int len2 )
+{
+    FIXME("(lcid %x, flags %x, %s(%d), %s(%d), partial stub\n",
+          lcid, flags, debugstr_a(src1), len1, debugstr_a(src2), len2 );
+    /* FIXME: probably not entirely right */
+    return CompareStringA( lcid, flags, src1, len1, src2, len2 );
+}
+
+/*********************************************************************
+ *		__crtCompareStringW (MSVCRT.@)
+ */
+int CDECL __crtCompareStringW( LCID lcid, DWORD flags, const MSVCRT_wchar_t *src1, int len1,
+                               const MSVCRT_wchar_t *src2, int len2 )
+{
+    FIXME("(lcid %x, flags %x, %s(%d), %s(%d), partial stub\n",
+          lcid, flags, debugstr_w(src1), len1, debugstr_w(src2), len2 );
+    /* FIXME: probably not entirely right */
+    return CompareStringW( lcid, flags, src1, len1, src2, len2 );
+}
+
+/*********************************************************************
+ *		__crtGetLocaleInfoW (MSVCRT.@)
+ */
+int CDECL __crtGetLocaleInfoW( LCID lcid, LCTYPE type, MSVCRT_wchar_t *buffer, int len )
+{
+    FIXME("(lcid %x, type %x, %p(%d), partial stub\n", lcid, type, buffer, len );
+    /* FIXME: probably not entirely right */
+    return GetLocaleInfoW( lcid, type, buffer, len );
+}
+
+/*********************************************************************
+ *              btowc(MSVCRT.@)
+ */
+wint_t CDECL btowc(int c)
+{
+    _locale_t locale = get_locale();
+    unsigned char letter = c;
+    wchar_t ret;
+
+    if(!MultiByteToWideChar(locale->locinfo->lc_handle[MSVCRT_LC_CTYPE],
+                0, (LPCSTR)&letter, 1, &ret, 1))
+        return 0;
+
+    return ret;
+}
+
+/*********************************************************************
+ *              __crtGetStringTypeW(MSVCRT.@)
+ *
+ * This function was accepting different number of arguments in older
+ * versions of msvcrt.
+ */
+BOOL CDECL __crtGetStringTypeW(DWORD unk, DWORD type,
+        MSVCRT_wchar_t *buffer, int len, WORD *out)
+{
+    FIXME("(unk %x, type %x, wstr %p(%d), %p) partial stub\n",
+            unk, type, buffer, len, out);
+
+    return GetStringTypeW(type, buffer, len, out);
+}
+
+/*********************************************************************
+ *		localeconv (MSVCRT.@)
+ */
+struct lconv * CDECL localeconv(void)
+{
+    return get_locale()->locinfo->lconv;
+}
+
+/*********************************************************************
+ *		__lconv_init (MSVCRT.@)
+ */
+void CDECL __lconv_init(void)
+{
+    /* this is used to make chars unsigned */
+    charmax = 255;
+}
+
+/*********************************************************************
+ *      ___lc_handle_func (MSVCRT.@)
+ */
+HANDLE * CDECL ___lc_handle_func(void)
+{
+    return MSVCRT___lc_handle;
+}
+
+/*********************************************************************
+ *      ___lc_codepage_func (MSVCRT.@)
+ */
+int CDECL ___lc_codepage_func(void)
+{
+    return MSVCRT___lc_codepage;
+}
+
+/*********************************************************************
+ *      ___lc_collate_cp_func (MSVCRT.@)
+ */
+int CDECL ___lc_collate_cp_func(void)
+{
+    return get_locale()->locinfo->lc_collate_cp;
+}
+
+/* _free_locale - not exported in native msvcrt */
+void CDECL _free_locale(_locale_t locale)
+{
+    int i;
+
+    for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) {
+        free(locale->locinfo->lc_category[i].locale);
+        free(locale->locinfo->lc_category[i].refcount);
     }
-    UNLOCK_LOCALE;
-    return MSVCRT_current_lc_all;
-  }
 
-  /* Get locale elements */
-  haveLang = haveCountry = haveCP = 0;
-  memset(&lc,0,sizeof(lc));
+    if(locale->locinfo->lconv) {
+        free(locale->locinfo->lconv->decimal_point);
+        free(locale->locinfo->lconv->thousands_sep);
+        free(locale->locinfo->lconv->grouping);
+        free(locale->locinfo->lconv->int_curr_symbol);
+        free(locale->locinfo->lconv->currency_symbol);
+        free(locale->locinfo->lconv->mon_decimal_point);
+        free(locale->locinfo->lconv->mon_thousands_sep);
+        free(locale->locinfo->lconv->mon_grouping);
+        free(locale->locinfo->lconv->positive_sign);
+        free(locale->locinfo->lconv->negative_sign);
+    }
+    free(locale->locinfo->lconv_intl_refcount);
+    free(locale->locinfo->lconv_num_refcount);
+    free(locale->locinfo->lconv_mon_refcount);
+    free(locale->locinfo->lconv);
 
-  next = strchr(locale,'_');
-  if (next && next != locale)
-  {
-    haveLang = 1;
-    memcpy(lc.search_language,locale,next-locale);
-    locale += next-locale+1;
-  }
+    free(locale->locinfo->ctype1_refcount);
+    free(locale->locinfo->ctype1);
 
-  next = strchr(locale,'.');
-  if (next)
-  {
-    haveCP = 1;
-    if (next == locale)
-    {
-      locale++;
-      lstrcpynA(lc.search_codepage, locale, MAX_ELEM_LEN);
+    free((void*)locale->locinfo->pclmap);
+    free((void*)locale->locinfo->pcumap);
+
+    free(locale->locinfo);
+    free(locale->mbcinfo);
+    free(locale);
+}
+
+/* _create_locale - not exported in native msvcrt */
+_locale_t _create_locale(int category, const char *locale)
+{
+    static const char collate[] = "COLLATE=";
+    static const char ctype[] = "CTYPE=";
+    static const char monetary[] = "MONETARY=";
+    static const char numeric[] = "NUMERIC=";
+    static const char time[] = "TIME=";
+
+    _locale_t loc;
+    LCID lcid[6] = { 0 };
+    char buf[256];
+    int i;
+
+    TRACE("(%d %s)\n", category, locale);
+
+    if(category<MSVCRT_LC_MIN || category>MSVCRT_LC_MAX || !locale)
+        return NULL;
+
+    if(locale[0]=='C' && !locale[1])
+        lcid[0] = CP_ACP;
+    else if(!locale[0])
+        lcid[0] = GetSystemDefaultLCID();
+    else if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_') {
+        char *p;
+
+        while(1) {
+            locale += 3; /* LC_ */
+            if(!memcmp(locale, collate, sizeof(collate)-1)) {
+                i = MSVCRT_LC_COLLATE;
+                locale += sizeof(collate)-1;
+            } else if(!memcmp(locale, ctype, sizeof(ctype)-1)) {
+                i = MSVCRT_LC_CTYPE;
+                locale += sizeof(ctype)-1;
+            } else if(!memcmp(locale, monetary, sizeof(monetary)-1)) {
+                i = MSVCRT_LC_MONETARY;
+                locale += sizeof(monetary)-1;
+            } else if(!memcmp(locale, numeric, sizeof(numeric)-1)) {
+                i = MSVCRT_LC_NUMERIC;
+                locale += sizeof(numeric)-1;
+            } else if(!memcmp(locale, time, sizeof(time)-1)) {
+                i = MSVCRT_LC_TIME;
+                locale += sizeof(time)-1;
+            } else
+                return NULL;
+
+            p = strchr(locale, ';');
+            if(locale[0]=='C' && (locale[1]==';' || locale[1]=='\0'))
+                lcid[i] = 0;
+            else if(p) {
+                memcpy(buf, locale, p-locale);
+                lcid[i] = MSVCRT_locale_to_LCID(buf);
+            } else
+                lcid[i] = MSVCRT_locale_to_LCID(locale);
+
+            if(lcid[i] == -1)
+                return NULL;
+
+            if(!p || *(p+1)!='L' || *(p+2)!='C' || *(p+3)!='_')
+                break;
+
+            locale = p+1;
+        }
+    } else {
+        lcid[0] = MSVCRT_locale_to_LCID(locale);
+        if(lcid[0] == -1)
+            return NULL;
     }
-    else
-    {
-      if (haveLang)
-      {
-        haveCountry = 1;
-        memcpy(lc.search_country,locale,next-locale);
-        locale += next-locale+1;
-      }
-      else
-      {
-        haveLang = 1;
-        memcpy(lc.search_language,locale,next-locale);
-        locale += next-locale+1;
-      }
-      lstrcpynA(lc.search_codepage, locale, MAX_ELEM_LEN);
+
+    for(i=1; i<6; i++) {
+        if(!lcid[i])
+            lcid[i] = lcid[0];
     }
-  }
-  else
-  {
-    if (haveLang)
-    {
-      haveCountry = 1;
-      lstrcpynA(lc.search_country, locale, MAX_ELEM_LEN);
+
+    loc = malloc(sizeof(_locale_tstruct));
+    if(!loc)
+        return NULL;
+
+    loc->locinfo = malloc(sizeof(threadlocinfo));
+    if(!loc->locinfo) {
+        free(loc);
+        return NULL;
     }
-    else
-    {
-      haveLang = 1;
-      lstrcpynA(lc.search_language, locale, MAX_ELEM_LEN);
+
+    loc->mbcinfo = malloc(sizeof(threadmbcinfo));
+    if(!loc->mbcinfo) {
+        free(loc->locinfo);
+        free(loc);
+        return NULL;
     }
-  }
 
-  if (haveCountry)
-    remap_synonym(lc.search_country);
+    memset(loc->locinfo, 0, sizeof(threadlocinfo));
+    memset(loc->mbcinfo, 0, sizeof(threadmbcinfo));
 
-  if (haveCP && !haveCountry && !haveLang)
-  {
-    ERR(":Codepage only locale not implemented\n");
-    /* FIXME: Use default lang/country and skip locale_to_LCID()
-     * call below...
-     */
-    UNLOCK_LOCALE;
-    return NULL;
-  }
+    loc->locinfo->lconv = malloc(sizeof(struct lconv));
+    if(!loc->locinfo->lconv) {
+        _free_locale(loc);
+        return NULL;
+    }
+    memset(loc->locinfo->lconv, 0, sizeof(struct lconv));
 
-  lcid = MSVCRT_locale_to_LCID(&lc);
+    loc->locinfo->pclmap = malloc(sizeof(char[256]));
+    loc->locinfo->pcumap = malloc(sizeof(char[256]));
+    if(!loc->locinfo->pclmap || !loc->locinfo->pcumap) {
+        _free_locale(loc);
+        return NULL;
+    }
 
-  TRACE(":found LCID %d\n",lcid);
+    loc->locinfo->refcount = 1;
 
-  if (lcid == 0)
-  {
-    UNLOCK_LOCALE;
-    return NULL;
-  }
+    if(lcid[MSVCRT_LC_COLLATE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_COLLATE)) {
+        if(update_threadlocinfo_category(lcid[MSVCRT_LC_COLLATE], loc, MSVCRT_LC_COLLATE)) {
+            _free_locale(loc);
+            return NULL;
+        }
+    } else
+        loc->locinfo->lc_category[MSVCRT_LC_COLLATE].locale = _strdup("C");
 
-  MSVCRT_current_lc_all_lcid = lcid;
+    if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) {
+        CPINFO cp;
 
-  _snprintf(MSVCRT_current_lc_all,MAX_LOCALE_LENGTH,"%s_%s.%s",
-	   lc.found_language,lc.found_country,lc.found_codepage);
+        if(update_threadlocinfo_category(lcid[MSVCRT_LC_CTYPE], loc, MSVCRT_LC_CTYPE)) {
+            _free_locale(loc);
+            return NULL;
+        }
 
-  switch (category) {
-  case MSVCRT_LC_ALL:
-    lc_all = 1; /* Fall through all cases ... */
-  case MSVCRT_LC_COLLATE:
-    if (!lc_all) break;
-  case MSVCRT_LC_CTYPE:
-    msvcrt_set_ctype(atoi(lc.found_codepage),lcid);
-    if (!lc_all) break;
-  case MSVCRT_LC_MONETARY:
-    if (!lc_all) break;
-  case MSVCRT_LC_NUMERIC:
-    if (!lc_all) break;
-  case MSVCRT_LC_TIME:
-    break;
-  }
-  UNLOCK_LOCALE;
-  return MSVCRT_current_lc_all;
+        loc->locinfo->lc_codepage = loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage;
+        loc->locinfo->lc_collate_cp = loc->locinfo->lc_codepage;
+        loc->locinfo->lc_clike = 1;
+        if(!GetCPInfo(loc->locinfo->lc_codepage, &cp)) {
+            _free_locale(loc);
+            return NULL;
+        }
+        loc->locinfo->mb_cur_max = cp.MaxCharSize;
+
+        loc->locinfo->ctype1_refcount = malloc(sizeof(int));
+        loc->locinfo->ctype1 = malloc(sizeof(short[257]));
+        if(!loc->locinfo->ctype1_refcount || !loc->locinfo->ctype1) {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        *loc->locinfo->ctype1_refcount = 1;
+        loc->locinfo->ctype1[0] = 0;
+        loc->locinfo->pctype = loc->locinfo->ctype1+1;
+
+        buf[1] = buf[2] = '\0';
+        for(i=1; i<257; i++) {
+            buf[0] = i-1;
+
+            GetStringTypeA(lcid[MSVCRT_LC_CTYPE], CT_CTYPE1, buf,
+                    1, loc->locinfo->ctype1+i);
+            loc->locinfo->ctype1[i] |= 0x200;
+        }
+    } else {
+        loc->locinfo->lc_clike = 1;
+        loc->locinfo->mb_cur_max = 1;
+        loc->locinfo->pctype = (unsigned short*)ctype+1;
+        loc->locinfo->lc_category[MSVCRT_LC_CTYPE].locale = _strdup("C");
+    }
+
+    for(i=0; i<256; i++)
+        buf[i] = i;
+
+    LCMapStringA(lcid[MSVCRT_LC_CTYPE], LCMAP_LOWERCASE, buf, 256,
+            (char*)loc->locinfo->pclmap, 256);
+    LCMapStringA(lcid[MSVCRT_LC_CTYPE], LCMAP_UPPERCASE, buf, 256,
+            (char*)loc->locinfo->pcumap, 256);
+
+    loc->mbcinfo->refcount = 1;
+    loc->mbcinfo->mbcodepage = loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage;
+
+    for(i=0; i<256; i++) {
+        if(loc->locinfo->pclmap[i] != i) {
+            loc->mbcinfo->mbctype[i+1] |= 0x10;
+            loc->mbcinfo->mbcasemap[i] = loc->locinfo->pclmap[i];
+        } else if(loc->locinfo->pcumap[i] != i) {
+            loc->mbcinfo->mbctype[i+1] |= 0x20;
+            loc->mbcinfo->mbcasemap[i] = loc->locinfo->pcumap[i];
+        }
+    }
+
+    if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) {
+        if(update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY], loc, MSVCRT_LC_MONETARY)) {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        loc->locinfo->lconv_intl_refcount = malloc(sizeof(int));
+        loc->locinfo->lconv_mon_refcount = malloc(sizeof(int));
+        if(!loc->locinfo->lconv_intl_refcount || !loc->locinfo->lconv_mon_refcount) {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        *loc->locinfo->lconv_intl_refcount = 1;
+        *loc->locinfo->lconv_mon_refcount = 1;
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SINTLSYMBOL, buf, 256);
+        if(i && (loc->locinfo->lconv->int_curr_symbol = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->int_curr_symbol, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SCURRENCY, buf, 256);
+        if(i && (loc->locinfo->lconv->currency_symbol = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->currency_symbol, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SMONDECIMALSEP, buf, 256);
+        if(i && (loc->locinfo->lconv->mon_decimal_point = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->mon_decimal_point, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SMONTHOUSANDSEP, buf, 256);
+        if(i && (loc->locinfo->lconv->mon_thousands_sep = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->mon_thousands_sep, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SMONGROUPING, buf, 256);
+        if(i>1)
+            i = i/2 + (buf[i-2]=='0'?0:1);
+        if(i && (loc->locinfo->lconv->mon_grouping = malloc(sizeof(char[i])))) {
+            for(i=0; buf[i+1]==';'; i+=2)
+                loc->locinfo->lconv->mon_grouping[i/2] = buf[i]-'0';
+            loc->locinfo->lconv->mon_grouping[i/2] = buf[i]-'0';
+            if(buf[i] != '0')
+                loc->locinfo->lconv->mon_grouping[i/2+1] = 127;
+        } else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SPOSITIVESIGN, buf, 256);
+        if(i && (loc->locinfo->lconv->positive_sign = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->positive_sign, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SNEGATIVESIGN, buf, 256);
+        if(i && (loc->locinfo->lconv->negative_sign = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->negative_sign, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IINTLCURRDIGITS, buf, 256))
+            loc->locinfo->lconv->int_frac_digits = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_ICURRDIGITS, buf, 256))
+            loc->locinfo->lconv->frac_digits = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IPOSSYMPRECEDES, buf, 256))
+            loc->locinfo->lconv->p_cs_precedes = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IPOSSEPBYSPACE, buf, 256))
+            loc->locinfo->lconv->p_sep_by_space = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_INEGSYMPRECEDES, buf, 256))
+            loc->locinfo->lconv->n_cs_precedes = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_INEGSEPBYSPACE, buf, 256))
+            loc->locinfo->lconv->n_sep_by_space = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_IPOSSIGNPOSN, buf, 256))
+            loc->locinfo->lconv->p_sign_posn = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_INEGSIGNPOSN, buf, 256))
+            loc->locinfo->lconv->n_sign_posn = atoi(buf);
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+    } else {
+        loc->locinfo->lconv->int_curr_symbol = malloc(sizeof(char));
+        loc->locinfo->lconv->currency_symbol = malloc(sizeof(char));
+        loc->locinfo->lconv->mon_decimal_point = malloc(sizeof(char));
+        loc->locinfo->lconv->mon_thousands_sep = malloc(sizeof(char));
+        loc->locinfo->lconv->mon_grouping = malloc(sizeof(char));
+        loc->locinfo->lconv->positive_sign = malloc(sizeof(char));
+        loc->locinfo->lconv->negative_sign = malloc(sizeof(char));
+
+        if(!loc->locinfo->lconv->int_curr_symbol || !loc->locinfo->lconv->currency_symbol
+                || !loc->locinfo->lconv->mon_decimal_point || !loc->locinfo->lconv->mon_thousands_sep
+                || !loc->locinfo->lconv->mon_grouping || !loc->locinfo->lconv->positive_sign
+                || !loc->locinfo->lconv->negative_sign) {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        loc->locinfo->lconv->int_curr_symbol[0] = '\0';
+        loc->locinfo->lconv->currency_symbol[0] = '\0';
+        loc->locinfo->lconv->mon_decimal_point[0] = '\0';
+        loc->locinfo->lconv->mon_thousands_sep[0] = '\0';
+        loc->locinfo->lconv->mon_grouping[0] = '\0';
+        loc->locinfo->lconv->positive_sign[0] = '\0';
+        loc->locinfo->lconv->negative_sign[0] = '\0';
+        loc->locinfo->lconv->int_frac_digits = 127;
+        loc->locinfo->lconv->frac_digits = 127;
+        loc->locinfo->lconv->p_cs_precedes = 127;
+        loc->locinfo->lconv->p_sep_by_space = 127;
+        loc->locinfo->lconv->n_cs_precedes = 127;
+        loc->locinfo->lconv->n_sep_by_space = 127;
+        loc->locinfo->lconv->p_sign_posn = 127;
+        loc->locinfo->lconv->n_sign_posn = 127;
+
+        loc->locinfo->lc_category[MSVCRT_LC_MONETARY].locale = _strdup("C");
+    }
+
+    if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) {
+        if(update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC], loc, MSVCRT_LC_NUMERIC)) {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        if(!loc->locinfo->lconv_intl_refcount)
+            loc->locinfo->lconv_intl_refcount = malloc(sizeof(int));
+        loc->locinfo->lconv_num_refcount = malloc(sizeof(int));
+        if(!loc->locinfo->lconv_intl_refcount || !loc->locinfo->lconv_num_refcount) {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        *loc->locinfo->lconv_intl_refcount = 1;
+        *loc->locinfo->lconv_num_refcount = 1;
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_SDECIMAL, buf, 256);
+        if(i && (loc->locinfo->lconv->decimal_point = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->decimal_point, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_STHOUSAND, buf, 256);
+        if(i && (loc->locinfo->lconv->thousands_sep = malloc(sizeof(char[i]))))
+            memcpy(loc->locinfo->lconv->thousands_sep, buf, sizeof(char[i]));
+        else {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_SGROUPING, buf, 256);
+        if(i>1)
+            i = i/2 + (buf[i-2]=='0'?0:1);
+        if(i && (loc->locinfo->lconv->grouping = malloc(sizeof(char[i])))) {
+            for(i=0; buf[i+1]==';'; i+=2)
+                loc->locinfo->lconv->grouping[i/2] = buf[i]-'0';
+            loc->locinfo->lconv->grouping[i/2] = buf[i]-'0';
+            if(buf[i] != '0')
+                loc->locinfo->lconv->grouping[i/2+1] = 127;
+        } else {
+            _free_locale(loc);
+            return NULL;
+        }
+    } else {
+        loc->locinfo->lconv->decimal_point = malloc(sizeof(char[2]));
+        loc->locinfo->lconv->thousands_sep = malloc(sizeof(char));
+        loc->locinfo->lconv->grouping = malloc(sizeof(char));
+        if(!loc->locinfo->lconv->decimal_point || !loc->locinfo->lconv->thousands_sep
+                || !loc->locinfo->lconv->grouping) {
+            _free_locale(loc);
+            return NULL;
+        }
+
+        loc->locinfo->lconv->decimal_point[0] = '.';
+        loc->locinfo->lconv->decimal_point[1] = '\0';
+        loc->locinfo->lconv->thousands_sep[0] = '\0';
+        loc->locinfo->lconv->grouping[0] = '\0';
+
+        loc->locinfo->lc_category[MSVCRT_LC_NUMERIC].locale = _strdup("C");
+    }
+
+    if(lcid[MSVCRT_LC_TIME] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_TIME)) {
+        if(update_threadlocinfo_category(lcid[MSVCRT_LC_TIME], loc, MSVCRT_LC_TIME)) {
+            _free_locale(loc);
+            return NULL;
+        }
+    } else
+        loc->locinfo->lc_category[MSVCRT_LC_TIME].locale = _strdup("C");
+
+    return loc;
 }
 
-/*
- * @unimplemented
- */
-wchar_t* _wsetlocale(int category, const wchar_t* locale)
+/* _configthreadlocale - not exported in native msvcrt */
+int CDECL _configthreadlocale(int type)
 {
-  static wchar_t fake[] = {
-    'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ',
-    'S','t','a','t','e','s','.','1','2','5','2',0 };
+    MSVCRT_thread_data *data = msvcrt_get_thread_data();
+    int ret;
 
-  TRACE("%d %S\n", category, locale);
+    if(!data)
+        return -1;
 
-  return fake;
-}
+    ret = (data->locale ? _ENABLE_PER_THREAD_LOCALE : _DISABLE_PER_THREAD_LOCALE);
 
-/*
+    if(type == _ENABLE_PER_THREAD_LOCALE) {
+        if(!data->locale) {
+            /* Copy current global locale */
+            data->locale = _create_locale(MSVCRT_LC_ALL, setlocale(MSVCRT_LC_ALL, NULL));
+            if(!data->locale)
+                return -1;
+        }
 
-locale  "lang[_country[.code_page]]"
-            | ".code_page"
-            | ""
-            | NULL
+        return ret;
+    }
 
-*/
-int parse_locale(const char *locale, char *lang, char *country, char *code_page)
+    if(type == _DISABLE_PER_THREAD_LOCALE) {
+        if(data->locale) {
+            _free_locale(data->locale);
+            data->locale = NULL;
+        }
+
+        return ret;
+    }
+
+    if(!type)
+        return ret;
+
+    return -1;
+}
+
+/*********************************************************************
+ *             setlocale (MSVCRT.@)
+ */
+char* CDECL setlocale(int category, const char* locale)
 {
-	while ( *locale != 0 && *locale != '.' && *locale != '_' )
-	{
-		*lang = *locale;
-		lang++;
-		locale++;
-	}
-	*lang = 0;
-	if ( *locale == '_' ) {
-		locale++;
-		while ( *locale != 0 && *locale != '.' )
-		{
-			*country = *locale;
-			country++;
-			locale++;
-		}
-	}
-	*country = 0;
+    _locale_t loc, cur;
 
+    cur = get_locale();
 
-	if ( *locale == '.' ) {
-		locale++;
-		while ( *locale != 0 && *locale != '.' )
-		{
-			*code_page = *locale;
-			code_page++;
-			locale++;
-		}
-	}
+    if(category<MSVCRT_LC_MIN || category>MSVCRT_LC_MAX)
+        return NULL;
 
-	*code_page = 0;
-	return 0;
+    if(!locale) {
+        if(category == MSVCRT_LC_ALL)
+            return construct_lc_all(cur);
+
+        return cur->locinfo->lc_category[category].locale;
+    }
+
+    loc = _create_locale(category, locale);
+    if(!loc) {
+        WARN("%d %s failed\n", category, locale);
+        return NULL;
+    }
+
+    LOCK_LOCALE;
+
+    switch(category) {
+        case MSVCRT_LC_ALL:
+            if(!cur)
+                break;
+        case MSVCRT_LC_COLLATE:
+            cur->locinfo->lc_handle[MSVCRT_LC_COLLATE] =
+                loc->locinfo->lc_handle[MSVCRT_LC_COLLATE];
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_COLLATE].locale,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_COLLATE].locale);
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_COLLATE].refcount,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_COLLATE].refcount);
+
+            if(category != MSVCRT_LC_ALL)
+                break;
+        case MSVCRT_LC_CTYPE:
+            cur->locinfo->lc_handle[MSVCRT_LC_CTYPE] =
+                loc->locinfo->lc_handle[MSVCRT_LC_CTYPE];
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_CTYPE].locale,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_CTYPE].locale);
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_CTYPE].refcount,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_CTYPE].refcount);
+
+            cur->locinfo->lc_codepage = loc->locinfo->lc_codepage;
+            cur->locinfo->lc_collate_cp = loc->locinfo->lc_collate_cp;
+            cur->locinfo->lc_clike = loc->locinfo->lc_clike;
+            cur->locinfo->mb_cur_max = loc->locinfo->mb_cur_max;
+
+            swap_pointers((void**)&cur->locinfo->ctype1_refcount,
+                    (void**)&loc->locinfo->ctype1_refcount);
+            swap_pointers((void**)&cur->locinfo->ctype1, (void**)&loc->locinfo->ctype1);
+            swap_pointers((void**)&cur->locinfo->pctype, (void**)&loc->locinfo->pctype);
+            swap_pointers((void**)&cur->locinfo->pclmap, (void**)&loc->locinfo->pclmap);
+            swap_pointers((void**)&cur->locinfo->pcumap, (void**)&loc->locinfo->pcumap);
+
+            memcpy(cur->mbcinfo, loc->mbcinfo, sizeof(threadmbcinfo));
+
+            if(category != MSVCRT_LC_ALL)
+                break;
+        case MSVCRT_LC_MONETARY:
+            cur->locinfo->lc_handle[MSVCRT_LC_MONETARY] =
+                loc->locinfo->lc_handle[MSVCRT_LC_MONETARY];
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_MONETARY].locale,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_MONETARY].locale);
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_MONETARY].refcount,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_MONETARY].refcount);
+
+            swap_pointers((void**)&cur->locinfo->lconv->int_curr_symbol,
+                    (void**)&loc->locinfo->lconv->int_curr_symbol);
+            swap_pointers((void**)&cur->locinfo->lconv->currency_symbol,
+                    (void**)&loc->locinfo->lconv->currency_symbol);
+            swap_pointers((void**)&cur->locinfo->lconv->mon_decimal_point,
+                    (void**)&loc->locinfo->lconv->mon_decimal_point);
+            swap_pointers((void**)&cur->locinfo->lconv->mon_thousands_sep,
+                    (void**)&loc->locinfo->lconv->mon_thousands_sep);
+            swap_pointers((void**)&cur->locinfo->lconv->mon_grouping,
+                    (void**)&loc->locinfo->lconv->mon_grouping);
+            swap_pointers((void**)&cur->locinfo->lconv->positive_sign,
+                    (void**)&loc->locinfo->lconv->positive_sign);
+            swap_pointers((void**)&cur->locinfo->lconv->negative_sign,
+                    (void**)&loc->locinfo->lconv->negative_sign);
+            cur->locinfo->lconv->int_frac_digits = loc->locinfo->lconv->int_frac_digits;
+            cur->locinfo->lconv->frac_digits = loc->locinfo->lconv->frac_digits;
+            cur->locinfo->lconv->p_cs_precedes = loc->locinfo->lconv->p_cs_precedes;
+            cur->locinfo->lconv->p_sep_by_space = loc->locinfo->lconv->p_sep_by_space;
+            cur->locinfo->lconv->n_cs_precedes = loc->locinfo->lconv->n_cs_precedes;
+            cur->locinfo->lconv->n_sep_by_space = loc->locinfo->lconv->n_sep_by_space;
+            cur->locinfo->lconv->p_sign_posn = loc->locinfo->lconv->p_sign_posn;
+            cur->locinfo->lconv->n_sign_posn = loc->locinfo->lconv->n_sign_posn;
+
+            if(category != MSVCRT_LC_ALL)
+                break;
+        case MSVCRT_LC_NUMERIC:
+            cur->locinfo->lc_handle[MSVCRT_LC_NUMERIC] =
+                loc->locinfo->lc_handle[MSVCRT_LC_NUMERIC];
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_NUMERIC].locale,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_NUMERIC].locale);
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_NUMERIC].refcount,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_NUMERIC].refcount);
+
+            swap_pointers((void**)&cur->locinfo->lconv->decimal_point,
+                    (void**)&loc->locinfo->lconv->decimal_point);
+            swap_pointers((void**)&cur->locinfo->lconv->thousands_sep,
+                    (void**)&loc->locinfo->lconv->thousands_sep);
+            swap_pointers((void**)&cur->locinfo->lconv->grouping,
+                    (void**)&loc->locinfo->lconv->grouping);
+
+            if(category != MSVCRT_LC_ALL)
+                break;
+        case MSVCRT_LC_TIME:
+            cur->locinfo->lc_handle[MSVCRT_LC_TIME] =
+                loc->locinfo->lc_handle[MSVCRT_LC_TIME];
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_TIME].locale,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_TIME].locale);
+            swap_pointers((void**)&cur->locinfo->lc_category[MSVCRT_LC_TIME].refcount,
+                    (void**)&loc->locinfo->lc_category[MSVCRT_LC_TIME].refcount);
+
+            if(category != MSVCRT_LC_ALL)
+                break;
+    }
+
+    if(!cur)
+        MSVCRT_locale = cur = loc;
+    else
+        _free_locale(loc);
+
+    UNLOCK_LOCALE;
+
+    if(cur == MSVCRT_locale) {
+        MSVCRT___lc_codepage = cur->locinfo->lc_codepage;
+        MSVCRT___lc_collate_cp = cur->locinfo->lc_collate_cp;
+        __mb_cur_max = cur->locinfo->mb_cur_max;
+        _pctype = cur->locinfo->pctype;
+    }
+
+    if(category == MSVCRT_LC_ALL)
+        return construct_lc_all(cur);
+
+    return cur->locinfo->lc_category[category].locale;
 }
 
-const struct map_lcid2str {
-        short            langid;
-        const char      *langname;
-	const char	*country;
-} languages[]={
-        {0x0409,"English", "United States"},
-        {0x0809,"English", "United Kingdom"},
-        {0x0000,"Unknown", "Unknown"}
+//from mbcs.c
 
+/* It seems that the data about valid trail bytes is not available from kernel32
+ * so we have to store is here. The format is the same as for lead bytes in CPINFO */
+struct cp_extra_info_t
+{
+    int cp;
+    BYTE TrailBytes[MAX_LEADBYTES];
 };
 
-const struct map_cntr {
-	const char *abrev;
-	const char  *country;
-} abrev[] = {
-	{"britain", "united kingdom"},
-	{"england", "united kingdom"},
-	{"gbr", "united kingdom"},
-	{"great britain", "united kingdom"},
-	{"uk", "united kingdom"},
-	{"united kingdom", "united kingdom"},
-	{"united-kingdom", "united kingdom"},
-	{"america", "united states" },
-	{"united states", "united states"},
-	{"united-states", "united states"},
-	{"us", "united states"},
-	{"usa", "united states"}
+static struct cp_extra_info_t g_cpextrainfo[] =
+{
+    {932, {0x40, 0x7e, 0x80, 0xfc, 0, 0}},
+    {936, {0x40, 0xfe, 0, 0}},
+    {949, {0x41, 0xfe, 0, 0}},
+    {950, {0x40, 0x7e, 0xa1, 0xfe, 0, 0}},
+    {1361, {0x31, 0x7e, 0x81, 0xfe, 0, 0}},
+    {20932, {1, 255, 0, 0}},  /* seems to give different results on different systems */
+    {0, {1, 255, 0, 0}}       /* match all with FIXME */
 };
 
+/*********************************************************************
+ *		___setlc_active_func (MSVCRT.@)
+ */
+unsigned int CDECL ___setlc_active_func(void)
+{
+  return __setlc_active;
+}
 
-struct lconv _lconv = {
-".",   // decimal_point
-",",   // thousands_sep
-"",    // grouping;
-"DOL", // int_curr_symbol
-"$",   // currency_symbol
-".",   // mon_decimal_point
-",",   // mon_thousands_sep
-"",    // mon_grouping;
-"+",   // positive_sign
-"-",   // negative_sign
-127,     // int_frac_digits
-127,     // frac_digits
-127,     // p_cs_precedes
-127,     // p_sep_by_space
-127,     // n_cs_precedes
-127,     // n_sep_by_space
-127,     // p_sign_posn;
-127      // n_sign_posn;
-};
+/*********************************************************************
+ *              ___mb_cur_max_func(MSVCRT.@)
+ */
+int* CDECL MSVCRT___mb_cur_max_func()
+{
+  return &get_locale()->locinfo->mb_cur_max;
+}
 
-/*
- * @implemented
+/*********************************************************************
+ *		___unguarded_readlc_active_add_func (MSVCRT.@)
  */
-struct lconv *localeconv(void)
+unsigned int * CDECL ___unguarded_readlc_active_add_func(void)
 {
-  return (struct lconv *) &_lconv;
+    return &__unguarded_readlc_active;
 }
 
 /*********************************************************************
+ *		__lc_collate_cp (MSVCRT.@)
+ *
+ * @unimplemented
+ */
+void __lc_collate_cp(int cp)
+{
+    FIXME("__lc_collate_cp - stub\n");
+    return;
+}
+
+/*********************************************************************
+ *		__lc_codepage (MSVCRT.@)
+ *
+ * @unimplemented
+ */
+void __lc_codepage(void)
+{
+    FIXME("__lc_codepage - stub\n");
+    return;
+}
+
+/*********************************************************************
+ *		__lc_handle (MSVCRT.@)
+ *
+ * @unimplemented
+ */
+void __lc_handle(void)
+{
+    FIXME("__lc_handle - stub\n");
+    return;
+}
+
+int CDECL _getmbcp(void)
+{
+    return MSVCRT___lc_codepage;
+}
+
+/*********************************************************************
  *		_setmbcp (MSVCRT.@)
- * @implemented
  */
 int CDECL _setmbcp(int cp)
 {
+  _locale_t locale = get_locale();
   int newcp;
   CPINFO cpi;
   BYTE *bytes;
@@ -645,7 +1311,6 @@
   int ret;
   int i;
 
-  TRACE("_setmbcp %d\n",cp);
   switch (cp)
   {
     case _MB_CP_ANSI:
@@ -655,7 +1320,7 @@
       newcp = GetOEMCP();
       break;
     case _MB_CP_LOCALE:
-      newcp = MSVCRT___lc_codepage;
+      newcp = locale->locinfo->lc_codepage;
       break;
     case _MB_CP_SBCS:
       newcp = 20127;   /* ASCII */
@@ -667,8 +1332,8 @@
 
   if (!GetCPInfo(newcp, &cpi))
   {
-    ERR("Codepage %d not found\n", newcp);
-    __set_errno(EINVAL);
+    WARN("Codepage %d not found\n", newcp);
+    *_errno() = EINVAL;
     return -1;
   }
 
@@ -694,7 +1359,7 @@
       if (cpextra->cp == 0 || cpextra->cp == newcp)
       {
         if (cpextra->cp == 0)
-          ERR("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp);
+          FIXME("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp);
 
         bytes = cpextra->TrailBytes;
         while (bytes[0] || bytes[1])
@@ -748,156 +1413,8 @@
       _mbctype[i + 1] |= _MS;
   }
 
-  MSVCRT___lc_collate_cp = MSVCRT___lc_codepage = newcp;
-  TRACE("(%d) -> %d\n", cp, MSVCRT___lc_codepage);
+  locale->locinfo->lc_collate_cp = newcp;
+  locale->locinfo->lc_codepage = newcp;
+  TRACE("(%d) -> %d\n", cp, locale->locinfo->lc_codepage);
   return 0;
 }
-
-
-/*********************************************************************
- *		__lc_collate_cp (MSVCRT.@)
- *
- * @unimplemented
- */
-void __lc_collate_cp(int cp)
-{
-FIXME("__lc_collate_cp - stub\n");
-return;
-}
-
-
-/*********************************************************************
- *		__lc_handle (MSVCRT.@)
- *
- * @unimplemented
- */
-void __lc_handle(void)
-{
-FIXME("__lc_handle - stub\n");
-return;
-}
-
-
-/*********************************************************************
- *		__lc_codepage (MSVCRT.@)
- *
- * @unimplemented
- */
-void __lc_codepage(void)
-{
-FIXME("__lc_codepage - stub\n");
-return;
-}
-
-
-/*********************************************************************
- *    _Gettnames (MSVCRT.@)
- */
-void *_Gettnames(void)
-{
-  FIXME("(void), stub!\n");
-  return NULL;
-}
-
-/*********************************************************************
- *    __lconv_init (MSVCRT.@)
- */
-void __lconv_init(void)
-{
-  char Char = (char) UCHAR_MAX;
-
-  TRACE("__lconv_init()\n");
-
-  _lconv.int_frac_digits = Char;
-  _lconv.frac_digits = Char;
-  _lconv.p_sep_by_space = _lconv.n_sep_by_space = Char;
-  _lconv.p_cs_precedes = _lconv.n_cs_precedes = Char;
-  _lconv.p_sign_posn = _lconv.n_sign_posn = Char;
-}
-
-
-/*********************************************************************
- *    _Strftime (MSVCRT.@)
- */
-const char* _Strftime(char *out, unsigned int len, const char *fmt,
-                                     const void *tm, void *foo)
-{
-  /* FIXME: */
-  FIXME("(%p %d %s %p %p) stub\n", out, len, fmt, tm, foo);
-  return "";
-}
-
-
-/*********************************************************************
- *    _Getdays (MSVCRT.@)
- */
-const char* _Getdays(void)
-{
-  static const char *MSVCRT_days = ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:"
-                            "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
-  /* FIXME: Use locale */
-  FIXME("(void) semi-stub\n");
-  return MSVCRT_days;
-}
-
-/*********************************************************************
- *    _Getmonths (MSVCRT.@)
- */
-const char* _Getmonths(void)
-{
-  static const char *MSVCRT_months = ":Jan:January:Feb:February:Mar:March:Apr:"
-                "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:"
-                "October:Nov:November:Dec:December";
-  /* FIXME: Use locale */
-  FIXME("(void) semi-stub\n");
-  return MSVCRT_months;
-}
-
-/*********************************************************************
- *    __crtLCMapStringA (MSVCRT.@)
- */
-int __crtLCMapStringA(
-  LCID lcid, DWORD mapflags, const char* src, int srclen, char* dst,
-  int dstlen, unsigned int codepage, int xflag
-) {
-  TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
-        lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag);
-  /* FIXME: A bit incorrect. But msvcrt itself just converts its
-   * arguments to wide strings and then calls LCMapStringW
-   */
-  return LCMapStringA(lcid,mapflags,src,srclen,dst,dstlen);
-}
-
-/*********************************************************************
- *    __crtLCMapStringW (MSVCRT.@)
- */
-int __crtLCMapStringW(
-  LCID lcid, DWORD mapflags, LPCWSTR src, int srclen, LPWSTR dst,
-  int dstlen, unsigned int codepage, int xflag
-) {
-  TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
-        lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag);
-
-  return LCMapStringW(lcid,mapflags,src,srclen,dst,dstlen);
-}
-
-int CDECL _getmbcp(void)
-{
-    return MSVCRT___lc_codepage;
-}
-
-/*********************************************************************
- *		___unguarded_readlc_active_add_func (MSVCRT.@)
- */
-unsigned int * CDECL ___unguarded_readlc_active_add_func(void)
-{
-  return &__unguarded_readlc_active;
-}
-
-/*********************************************************************
- *		___setlc_active_func (MSVCRT.@)
- */
-unsigned int CDECL ___setlc_active_func(void)
-{
-  return __setlc_active;
-}
Index: crt/math/rand.c
===================================================================
--- crt/math/rand.c	(revision 47065)
+++ crt/math/rand.c	(working copy)
@@ -1,6 +1,6 @@
 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
 #include <precomp.h>
-
+#include <Ntsecapi.h>
 #include <internal/tls.h>
 
 /*
@@ -25,3 +25,18 @@
 
   ThreadData->tnext = (ULONGLONG)seed;
 }
+
+ /*********************************************************************
+  *              rand_s (MSVCRT.@)
+  */
+int CDECL rand_s(unsigned int *pval)
+{
+#if 0
+    if (!pval || !RtlGenRandom(pval, sizeof(*pval)))
+    {
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+#endif
+    return 0;
+}
Index: crt/mbstring/jistojms.c
===================================================================
--- crt/mbstring/jistojms.c	(revision 47065)
+++ crt/mbstring/jistojms.c	(working copy)
@@ -25,6 +25,7 @@
 #include <precomp.h>
 #include <mbstring.h>
 #include <locale.h>
+#include <internal/wine/msvcrt.h>
 
 /*
  * @implemented
@@ -33,7 +34,7 @@
 {
  /* Conversion takes place only when codepage is 932.
      In all other cases, c is returned unchanged */
-  if(MSVCRT___lc_codepage == 932)
+  if(get_locale()->locinfo->lc_codepage == 932)
   {
     if(HIBYTE(c) >= 0x21 && HIBYTE(c) <= 0x7e &&
        LOBYTE(c) >= 0x21 && LOBYTE(c) <= 0x7e)
Index: crt/misc/stubs.c
===================================================================
--- crt/misc/stubs.c	(revision 47065)
+++ crt/misc/stubs.c	(working copy)
@@ -2,7 +2,8 @@
 
 int __STRINGTOLD( long double *value, char **endptr, const char *str, int flags )
 {
-   FIXME("%p %p %s %x stub\n", value, endptr, str, flags );
+   FIXME("%p %p %s %x partial stub\n", value, endptr, str, flags );
+   *value = strtold(str,endptr);
    return 0;
 }
 
@@ -15,11 +16,6 @@
   /* FIXME: This is probably data, not a function */
 }
 
-void __p__amblksiz(void)
-{
-   FIXME("__p__amblksiz stub\n");
-}
-
 void __fileinfo(void)
 {
    FIXME("__fileinfo stub\n");
@@ -30,3 +26,15 @@
    FIXME("stub\n");
 }
 
+/*********************************************************************
+ *              _daylight (MSVCRT.@)
+ */
+int MSVCRT___daylight = 0;
+
+/*********************************************************************
+ *              __p_daylight (MSVCRT.@)
+ */
+int * CDECL MSVCRT___p__daylight(void)
+{
+    return &MSVCRT___daylight;
+}
Index: crt/precomp.h
===================================================================
--- crt/precomp.h	(revision 47065)
+++ crt/precomp.h	(working copy)
@@ -34,6 +34,7 @@
 #endif
 
 #include "wine/unicode.h"
+#include "wine/config.h"
 
 /* kernelmode libcnt should not include Wine-debugging crap */
 #ifndef _LIBCNT_
Index: crt/stdio/file.c
===================================================================
--- crt/stdio/file.c	(revision 47065)
+++ crt/stdio/file.c	(working copy)
@@ -37,7 +37,7 @@
 
 #include <precomp.h>
 #include "wine/unicode.h"
-
+#include <internal/wine/msvcrt.h>
 #include <sys/utime.h>
 #include <direct.h>
 
@@ -123,6 +123,17 @@
   return fd >= 0 && fd < fdend && (fdesc[fd].wxflag & WX_OPEN);
 }
 
+/* INTERNAL: Create a wide string from an ascii string */
+wchar_t *msvcrt_wstrdupa(const char *str)
+{
+  const unsigned int len = strlen(str) + 1 ;
+  wchar_t *wstr = malloc(len* sizeof (wchar_t));
+  if (!wstr)
+    return NULL;
+   MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len,wstr,len);
+  return wstr;
+}
+
 /* INTERNAL: Get the HANDLE for a fd
  * This doesn't lock the table, because a failure will result in
  * INVALID_HANDLE_VALUE being returned, which should be handled correctly.  If
@@ -175,6 +186,7 @@
   if (fd >= MAX_FILES)
   {
     WARN(":files exhausted!\n");
+    *_errno() = ENFILE;
     return -1;
   }
   fdesc[fd].handle = hand;
@@ -341,9 +353,10 @@
   if (!(fdesc[0].wxflag & WX_OPEN) || fdesc[0].handle == INVALID_HANDLE_VALUE)
   {
 #ifndef __REACTOS__
-    DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE),
-                    GetCurrentProcess(), &fdesc[0].handle, 0, TRUE, 
-                    DUPLICATE_SAME_ACCESS);
+      HANDLE std = GetStdHandle(STD_INPUT_HANDLE);
+      if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
+                                                         GetCurrentProcess(), &MSVCRT_fdesc[0].handle,
+                                                         0, TRUE, DUPLICATE_SAME_ACCESS))
 #else
       fdesc[0].handle = GetStdHandle(STD_INPUT_HANDLE);
       if (fdesc[0].handle == NULL)
@@ -354,9 +367,10 @@
   if (!(fdesc[1].wxflag & WX_OPEN) || fdesc[1].handle == INVALID_HANDLE_VALUE)
   {
 #ifndef __REACTOS__
-      DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE),
-                    GetCurrentProcess(), &fdesc[1].handle, 0, TRUE, 
-                    DUPLICATE_SAME_ACCESS);
+      HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
+      if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
+                                                         GetCurrentProcess(), &MSVCRT_fdesc[1].handle,
+                                                         0, TRUE, DUPLICATE_SAME_ACCESS))
 #else
       fdesc[1].handle = GetStdHandle(STD_OUTPUT_HANDLE);
       if (fdesc[1].handle == NULL)
@@ -367,9 +381,10 @@
   if (!(fdesc[2].wxflag & WX_OPEN) || fdesc[2].handle == INVALID_HANDLE_VALUE)
   {
 #ifndef __REACTOS__
-      DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE),
-                    GetCurrentProcess(), &fdesc[2].handle, 0, TRUE, 
-                    DUPLICATE_SAME_ACCESS);
+      HANDLE std = GetStdHandle(STD_ERROR_HANDLE);
+      if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
+                                                         GetCurrentProcess(), &MSVCRT_fdesc[2].handle,
+                                                         0, TRUE, DUPLICATE_SAME_ACCESS))
 #else
       fdesc[2].handle = GetStdHandle(STD_ERROR_HANDLE);
       if (fdesc[2].handle == NULL)
@@ -448,11 +463,11 @@
 }
 
 /*********************************************************************
- *		__p__iob(MSVCRT.@)
+ *		__iob_func(MSVCRT.@)
  */
-FILE * CDECL __p__iob(void)
+FILE * CDECL __iob_func(void)
 {
- return _iob;
+ return &_iob[0];
 }
 
 /*********************************************************************
@@ -986,9 +1001,9 @@
   clearerr(file);
 }
 
-static int get_flags(const char* mode, int *open_flags, int* stream_flags)
+static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
 {
-  int plus = strchr(mode, '+') != NULL;
+  int plus = strchrW(mode, '+') != NULL;
 
   switch(*mode++)
   {
@@ -1005,6 +1020,8 @@
     *stream_flags = plus ? _IORW : _IOWRT;
     break;
   default:
+    _invalid_parameter(NULL, NULL, NULL, 0, 0);
+    *_errno() = EINVAL;
     return -1;
   }
 
@@ -1020,6 +1037,7 @@
       *open_flags &= ~_O_BINARY;
       break;
     case '+':
+    case ' ':
       break;
     default:
       FIXME(":unknown flag %c not supported\n",mode[-1]);
@@ -1032,6 +1050,22 @@
  */
 FILE* CDECL _fdopen(int fd, const char *mode)
 {
+    FILE *ret;
+    wchar_t *modeW = NULL;
+
+    if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL;
+
+    ret = _wfdopen(fd, modeW);
+
+    free(modeW);
+    return ret;
+}
+
+/*********************************************************************
+ *		_wfdopen (MSVCRT.@)
+ */
+FILE* CDECL _wfdopen(int fd, const wchar_t *mode)
+{
   int open_flags, stream_flags;
   FILE* file;
 
@@ -1045,51 +1079,13 @@
     file->_flag = 0;
     file = NULL;
   }
-  else TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,mode,file);
+  else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
   UNLOCK_FILES();
 
   return file;
 }
 
 /*********************************************************************
- *		_wfdopen (MSVCRT.@)
- */
-FILE* CDECL _wfdopen(int fd, const wchar_t *mode)
-{
-  unsigned mlen = strlenW(mode);
-  char *modea = calloc(mlen + 1, 1);
-  FILE* file = NULL;
-  int open_flags, stream_flags;
-
-  if (modea &&
-      WideCharToMultiByte(CP_ACP,0,mode,mlen,modea,mlen,NULL,NULL))
-  {
-      if (get_flags(modea, &open_flags, &stream_flags) == -1)
-      {
-        free(modea);
-        return NULL;
-      }
-      LOCK_FILES();
-      if (!(file = alloc_fp()))
-        file = NULL;
-      else if (init_fp(file, fd, stream_flags) == -1)
-      {
-        file->_flag = 0;
-        file = NULL;
-      }
-      else
-      {
-        if (file)
-          rewind(file); /* FIXME: is this needed ??? */
-        TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,debugstr_w(mode),file);
-      }
-      UNLOCK_FILES();
-  }
-  free(modea);
-  return file;
-}
-
-/*********************************************************************
  *		_filelength (MSVCRT.@)
  */
 LONG CDECL _filelength(int fd)
@@ -1137,41 +1133,6 @@
 }
 
 /*********************************************************************
- *		_futime (MSVCRT.@)
- */
-int CDECL _futime(int fd, struct _utimbuf *t)
-{
-  HANDLE hand = fdtoh(fd);
-  FILETIME at, wt;
-
-  if (hand == INVALID_HANDLE_VALUE)
-    return -1;
-
-  if (!t)
-  {
-    time_t currTime;
-    time(&currTime);
-    RtlSecondsSince1970ToTime(currTime, (LARGE_INTEGER *)&at);
-    wt = at;
-  }
-  else
-  {
-    RtlSecondsSince1970ToTime(t->actime, (LARGE_INTEGER *)&at);
-    if (t->actime == t->modtime)
-      wt = at;
-    else
-      RtlSecondsSince1970ToTime(t->modtime, (LARGE_INTEGER *)&wt);
-  }
-
-  if (!SetFileTime(hand, NULL, &at, &wt))
-  {
-    _dosmaperr(GetLastError());
-    return -1 ;
-  }
-  return 0;
-}
-
-/*********************************************************************
  *		_get_osfhandle (MSVCRT.@)
  */
 intptr_t CDECL _get_osfhandle(int fd)
@@ -1179,7 +1140,7 @@
   HANDLE hand = fdtoh(fd);
   TRACE(":fd (%d) handle (%p)\n",fd,hand);
 
-  return (long)(LONG_PTR)hand;
+  return (intptr_t)hand;
 }
 
 /*********************************************************************
@@ -1444,24 +1405,95 @@
  */
 int CDECL _wsopen( const wchar_t* path, int oflags, int shflags, ... )
 {
-  const unsigned int len = strlenW(path);
-  char *patha = calloc(len + 1,1);
   va_list ap;
   int pmode;
+  DWORD access = 0, creation = 0, attrib;
+  DWORD sharing;
+  int wxflag = 0, fd;
+  HANDLE hand;
+  SECURITY_ATTRIBUTES sa;
 
-  va_start(ap, shflags);
-  pmode = va_arg(ap, int);
-  va_end(ap);
 
-  if (patha && WideCharToMultiByte(CP_ACP,0,path,len,patha,len,NULL,NULL))
+  TRACE(":file (%s) oflags: 0x%04x shflags: 0x%04x\n",
+        debugstr_w(path), oflags, shflags);
+
+  wxflag = split_oflags(oflags);
+  switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR))
   {
-    int retval = _sopen(patha,oflags,shflags,pmode);
-    free(patha);
-    return retval;
+  case _O_RDONLY: access |= GENERIC_READ; break;
+  case _O_WRONLY: access |= GENERIC_WRITE; break;
+  case _O_RDWR:   access |= GENERIC_WRITE | GENERIC_READ; break;
   }
-  _dosmaperr(GetLastError());
-  free(patha);
-  return -1;
+
+  if (oflags & _O_CREAT)
+  {
+    va_start(ap, shflags);
+    pmode = va_arg(ap, int);
+    va_end(ap);
+
+    if(pmode & ~(_S_IREAD | _S_IWRITE))
+      FIXME(": pmode 0x%04x ignored\n", pmode);
+    else
+      WARN(": pmode 0x%04x ignored\n", pmode);
+
+    if (oflags & _O_EXCL)
+      creation = CREATE_NEW;
+    else if (oflags & _O_TRUNC)
+      creation = CREATE_ALWAYS;
+    else
+      creation = OPEN_ALWAYS;
+  }
+  else  /* no MSVCRT__O_CREAT */
+  {
+    if (oflags & _O_TRUNC)
+      creation = TRUNCATE_EXISTING;
+    else
+      creation = OPEN_EXISTING;
+  }
+
+  switch( shflags )
+  {
+    case _SH_DENYRW:
+      sharing = 0L;
+      break;
+    case _SH_DENYWR:
+      sharing = FILE_SHARE_READ;
+      break;
+    case _SH_DENYRD:
+      sharing = FILE_SHARE_WRITE;
+      break;
+    case _SH_DENYNO:
+      sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+      break;
+    default:
+      ERR( "Unhandled shflags 0x%x\n", shflags );
+      return -1;
+  }
+  attrib = FILE_ATTRIBUTE_NORMAL;
+
+  if (oflags & _O_TEMPORARY)
+  {
+      attrib |= FILE_FLAG_DELETE_ON_CLOSE;
+      access |= DELETE;
+      sharing |= FILE_SHARE_DELETE;
+  }
+
+  sa.nLength              = sizeof( SECURITY_ATTRIBUTES );
+  sa.lpSecurityDescriptor = NULL;
+  sa.bInheritHandle       = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
+
+  hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
+
+  if (hand == INVALID_HANDLE_VALUE)  {
+    WARN(":failed-last error (%d)\n",GetLastError());
+    _dosmaperr(GetLastError());
+    return -1;
+  }
+
+  fd = alloc_fd(hand, wxflag);
+
+  TRACE(":fd (%d) handle (%p)\n",fd, hand);
+  return fd;
 }
 
 /*********************************************************************
@@ -1488,24 +1520,18 @@
  */
 int CDECL _wopen(const wchar_t *path,int flags,...)
 {
-  const unsigned int len = strlenW(path);
-  char *patha = calloc(len + 1,1);
   va_list ap;
-  int pmode;
 
-  va_start(ap, flags);
-  pmode = va_arg(ap, int);
-  va_end(ap);
-
-  if (patha && WideCharToMultiByte(CP_ACP,0,path,len,patha,len,NULL,NULL))
+  if (flags & _O_CREAT)
   {
-    int retval = _open(patha,flags,pmode);
-    free(patha);
-    return retval;
+    int pmode;
+    va_start(ap, flags);
+    pmode = va_arg(ap, int);
+    va_end(ap);
+    return _wsopen( path, flags, _SH_DENYNO, pmode );
   }
-  free(patha);
-  _dosmaperr(GetLastError());
-  return -1;
+  else
+    return _wsopen( path, flags, _SH_DENYNO);
 }
 
 /*********************************************************************
@@ -1570,6 +1596,10 @@
 
 /*********************************************************************
  * (internal) read_i
+ *
+ * When reading \r as last character in text mode, read() positions
+ * the file pointer on the \r character while getc() goes on to
+ * the following \n
  */
 static int read_i(int fd, void *buf, unsigned int count)
 {
@@ -1603,7 +1633,7 @@
         }
         else if (fdesc[fd].wxflag & WX_TEXT)
         {
-              DWORD i, j;
+            DWORD i, j;
             if (bufstart[num_read-1] == '\r')
             {
                 if(count == 1)
@@ -1751,38 +1781,6 @@
 }
 
 /*********************************************************************
- *		_utime (MSVCRT.@)
- */
-int CDECL _utime(const char* path, struct _utimbuf *t)
-{
-  int fd = _open(path, _O_WRONLY | _O_BINARY);
-
-  if (fd > 0)
-  {
-    int retVal = _futime(fd, t);
-    _close(fd);
-    return retVal;
-  }
-  return -1;
-}
-
-/*********************************************************************
- *		_wutime (MSVCRT.@)
- */
-int CDECL _wutime(const wchar_t* path, struct _utimbuf *t)
-{
-  int fd = _wopen(path, _O_WRONLY | _O_BINARY);
-
-  if (fd > 0)
-  {
-    int retVal = _futime(fd, t);
-    _close(fd);
-    return retVal;
-  }
-  return -1;
-}
-
-/*********************************************************************
  *		_write (MSVCRT.@)
  */
 int CDECL _write(int fd, const void* buf, unsigned int count)
@@ -2025,7 +2023,8 @@
   if (!(fdesc[file->_file].wxflag & WX_TEXT))
     {
       wchar_t wc;
-      int i,j;
+      unsigned int i;
+      int j;
       char *chp, *wcp;
       wcp = (char *)&wc;
       for(i=0; i<sizeof(wc); i++)
@@ -2052,7 +2051,7 @@
     }
     
   c = fgetc(file);
-  if ((*__p___mb_cur_max() > 1) && isleadbyte(c))
+  if ((get_locale()->locinfo->mb_cur_max > 1) && isleadbyte(c))
     {
       FIXME("Treat Multibyte characters\n");
     }
@@ -2068,7 +2067,8 @@
 int CDECL _getw(FILE* file)
 {
   char *ch;
-  int i, j, k;
+  int i, k;
+  unsigned int j;
   ch = (char *)&i;
   for (j=0; j<sizeof(int); j++) {
     k = fgetc(file);
@@ -2192,26 +2192,26 @@
 }
 
 /*********************************************************************
- *		_fsopen (MSVCRT.@)
+ *		_wfsopen (MSVCRT.@)
  */
-FILE * CDECL _fsopen(const char *path, const char *mode, int share)
+FILE * CDECL _wfsopen(const wchar_t *path, const wchar_t *mode, int share)
 {
   FILE* file;
   int open_flags, stream_flags, fd;
 
-  TRACE("(%s,%s)\n",path,mode);
+  TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode));
 
   /* map mode string to open() flags. "man fopen" for possibilities. */
   if (get_flags(mode, &open_flags, &stream_flags) == -1)
       return NULL;
 
   LOCK_FILES();
-  fd = _sopen(path, open_flags, share, _S_IREAD | _S_IWRITE);
+  fd = _wsopen(path, open_flags, share, _S_IREAD | _S_IWRITE);
   if (fd < 0)
     file = NULL;
   else if ((file = alloc_fp()) && init_fp(file, fd, stream_flags)
    != -1)
-    TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,mode,file);
+    TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
   else if (file)
   {
     file->_flag = 0;
@@ -2226,29 +2226,31 @@
 }
 
 /*********************************************************************
- *		_wfsopen (MSVCRT.@)
+ *		_fsopen (MSVCRT.@)
  */
-FILE * CDECL _wfsopen(const wchar_t *path, const wchar_t *mode, int share)
+FILE * CDECL _fsopen(const char *path, const char *mode, int share)
 {
-  const unsigned int plen = strlenW(path), mlen = strlenW(mode);
-  char *patha = calloc(plen + 1, 1);
-  char *modea = calloc(mlen + 1, 1);
+    FILE *ret;
+    wchar_t *pathW = NULL, *modeW = NULL;
 
-  TRACE("(%s,%s)\n",debugstr_w(path),debugstr_w(mode));
+    if (path && !(pathW = msvcrt_wstrdupa(path))) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return NULL;
+    }
+    if (mode && !(modeW = msvcrt_wstrdupa(mode)))
+    {
+        free(pathW);
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return NULL;
+    }
 
-  if (patha && modea &&
-      WideCharToMultiByte(CP_ACP,0,path,plen,patha,plen,NULL,NULL) &&
-      WideCharToMultiByte(CP_ACP,0,mode,mlen,modea,mlen,NULL,NULL))
-  {
-    FILE *retval = _fsopen(patha,modea,share);
-    free(patha);
-    free(modea);
-    return retval;
-  }
-  free(patha);
-  free(modea);
-  _dosmaperr(GetLastError());
-  return NULL;
+    ret = _wfsopen(pathW, modeW, share);
+
+    free(pathW);
+    free(modeW);
+    return ret;
 }
 
 /*********************************************************************
@@ -2260,6 +2262,25 @@
 }
 
 /*********************************************************************
+ *              fopen_s (MSVCRT.@)
+ */
+int CDECL fopen_s(FILE** pFile,
+        const char *filename, const char *mode)
+{
+    if(!pFile) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+
+    *pFile = fopen(filename, mode);
+
+    if(!*pFile)
+        return *_errno();
+    return 0;
+}
+
+/*********************************************************************
  *		_wfopen (MSVCRT.@)
  */
 FILE * CDECL _wfopen(const wchar_t *path, const wchar_t *mode)
@@ -2267,6 +2288,25 @@
     return _wfsopen( path, mode, _SH_DENYNO );
 }
 
+/*********************************************************************
+ *		_wfopen_s (MSVCRT.@)
+ */
+int CDECL _wfopen_s(FILE** pFile, const wchar_t *filename,
+        const wchar_t *mode)
+{
+    if(!pFile) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+
+    *pFile = _wfopen(filename, mode);
+
+    if(!*pFile)
+        return *_errno();
+    return 0;
+}
+
 /* fputc calls _flsbuf which calls fputc */
 int CDECL _flsbuf(int c, FILE* file);
 
@@ -2310,7 +2350,7 @@
         int res=flush_buffer(file);
     return res?res : fputc(c, file);
   } else {
-    unsigned char cc=c;
+	unsigned char cc=c;
         int len;
         /* set _cnt to 0 for unbuffered FILEs */
         file->_cnt = 0;
@@ -2402,14 +2442,14 @@
 }
 
 /*********************************************************************
- *		freopen (MSVCRT.@)
+ *		_wfreopen (MSVCRT.@)
  *
  */
-FILE* CDECL freopen(const char *path, const char *mode,FILE* file)
+FILE* CDECL _wfreopen(const wchar_t *path, const wchar_t *mode, FILE* file)
 {
   int open_flags, stream_flags, fd;
 
-  TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n",path,mode,file,file->_file);
+  TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file->_file);
 
   LOCK_FILES();
   if (!file || ((fd = file->_file) < 0) || fd > fdend)
@@ -2422,7 +2462,7 @@
       file = NULL;
     else
     {
-      fd = _open(path, open_flags, _S_IREAD | _S_IWRITE);
+      fd = _wopen(path, open_flags, _S_IREAD | _S_IWRITE);
       if (fd < 0)
         file = NULL;
       else if (init_fp(file, fd, stream_flags) == -1)
@@ -2439,40 +2479,26 @@
 }
 
 /*********************************************************************
- *		wfreopen (MSVCRT.@)
+ *      freopen (MSVCRT.@)
  *
  */
-FILE* CDECL _wfreopen(const wchar_t *path, const wchar_t *mode,FILE* file)
+FILE* CDECL freopen(const char *path, const char *mode, FILE* file)
 {
-  int open_flags, stream_flags, fd;
+    FILE *ret;
+    wchar_t *pathW = NULL, *modeW = NULL;
 
-  TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file->_file);
-
-  LOCK_FILES();
-  if (!file || ((fd = file->_file) < 0) || fd > fdend)
-    file = NULL;
-  else
-  {
-    fclose(file);
-    /* map mode string to open() flags. "man fopen" for possibilities. */
-    if (get_flags((char*)mode, &open_flags, &stream_flags) == -1)
-      file = NULL;
-    else
+    if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL;
+    if (mode && !(modeW = msvcrt_wstrdupa(mode)))
     {
-      fd = _wopen(path, open_flags, _S_IREAD | _S_IWRITE);
-      if (fd < 0)
-        file = NULL;
-      else if (init_fp(file, fd, stream_flags) == -1)
-      {
-          file->_flag = 0;
-          WARN(":failed-last error (%d)\n",GetLastError());
-          _dosmaperr(GetLastError());
-          file = NULL;
-      }
+        free(pathW);
+        return NULL;
     }
-  }
-  UNLOCK_FILES();
-  return file;
+
+    ret = _wfreopen(pathW, modeW, file);
+
+    free(pathW);
+    free(modeW);
+    return ret;
 }
 
 /*********************************************************************
@@ -2518,8 +2544,12 @@
                 if (file->_ptr[i] == '\n')
                     off--;
             }
-        }
-    }
+		        /* Black magic when reading CR at buffer boundary*/
+			if(fdesc[file->_file].wxflag & WX_READCR)
+			  off--;
+
+		}
+	}
   }
   return off + pos;
 }
@@ -2534,18 +2564,21 @@
   if(*pos == -1) return -1;
   if(file->_bufsiz)  {
     if( file->_flag & _IOWRT ) {
-        off = file->_ptr - file->_base;
-    } else {
-        off = -file->_cnt;
+		off = file->_ptr - file->_base;
+	} else {
+		off = -file->_cnt;
         if (fdesc[file->_file].wxflag & WX_TEXT) {
-            /* Black magic correction for CR removal */
-            int i;
-            for (i=0; i<file->_cnt; i++) {
-                if (file->_ptr[i] == '\n')
-                    off--;
-            }
-        }
-    }
+			/* Black magic correction for CR removal */
+			int i;
+			for (i=0; i<file->_cnt; i++) {
+				if (file->_ptr[i] == '\n')
+					off--;
+			}
+		        /* Black magic when reading CR at buffer boundary*/
+			if(fdesc[file->_file].wxflag & WX_READCR)
+			  off--;
+		}
+	}
   }
   *pos += off;
   return 0;
@@ -2861,35 +2894,9 @@
     if (!(mem = malloc(resize*sizeof(*mem))))
       return EOF;
   }
-
-  /* Check if outputting to a text-file */
-  if (fdesc[file->_file].wxflag & WX_TEXT)
-  {
-      /* Convert each character and stop at the first invalid character. Behavior verified by tests under WinXP SP2 */
-      char chMultiByte[MB_LEN_MAX];
-      int nReturn;
-      wchar_t *p;
-
-      retval = 0;
-
-      for (p = mem; *p; p++)
-      {
-          nReturn = wctomb(chMultiByte, *p);
-
-          if(nReturn == -1)
-              break;
-
-          retval += fwrite(chMultiByte, 1, nReturn, file);
-      }
-  }
-  else
-  {
-    retval = fwrite(mem, sizeof(*mem), written, file);
-  }
-
+  retval = fwrite(mem, sizeof(*mem), written, file);
   if (mem != buf)
     free (mem);
-
   return retval;
 }
 
Index: crt/stdlib/errno.c
===================================================================
--- crt/stdlib/errno.c	(revision 47065)
+++ crt/stdlib/errno.c	(working copy)
@@ -8,8 +8,11 @@
  */
 #include <precomp.h>
 #include "doserrmap.h"
+#include <errno.h>
 #include <internal/wine/msvcrt.h>
 
+static _invalid_parameter_handler invalid_parameter_handler = NULL;
+
 /*
  * @implemented
  */
@@ -113,4 +116,36 @@
     SetErrorMode( mode );
 }
 
+/******************************************************************************
+ *		_invalid_parameter (MSVCRT.@)
+ */
+void __cdecl _invalid_parameter(const wchar_t *expr, const wchar_t *func,
+                                       const wchar_t *file, unsigned int line, uintptr_t arg)
+{
+    if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg );
+    else
+    {
+        ERR( "%s:%u %s: %s %lx\n", debugstr_w(file), line, debugstr_w(func), debugstr_w(expr), arg );
+        RaiseException( STATUS_INVALID_CRUNTIME_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, NULL );
+    }
+}
+
+/* _get_invalid_parameter_handler - not exported in native msvcrt, added in msvcr80 */
+_invalid_parameter_handler CDECL _get_invalid_parameter_handler(void)
+{
+    TRACE("\n");
+    return invalid_parameter_handler;
+}
+
+/* _set_invalid_parameter_handler - not exproted in native msvcrt, added in msvcr80 */
+_invalid_parameter_handler CDECL _set_invalid_parameter_handler(
+        _invalid_parameter_handler handler)
+{
+    _invalid_parameter_handler old = invalid_parameter_handler;
+
+    TRACE("(%p)\n", handler);
+
+    invalid_parameter_handler = handler;
+    return old;
+}
 /* EOF */
Index: crt/stdlib/malloc.c
===================================================================
--- crt/stdlib/malloc.c	(revision 47065)
+++ crt/stdlib/malloc.c	(working copy)
@@ -1,158 +0,0 @@
-/*
- * msvcrt.dll heap functions
- *
- * Copyright 2000 Jon Griffiths
- *
- * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Note: Win32 heap operations are MT safe. We only lock the new
- *       handler and non atomic heap operations
- */
-
-#include <precomp.h>
-#include <stdlib.h>
-#include <malloc.h>
-
-#define ROUND_DOWN(n, align) \
-    (((ULONG)n) & ~((align) - 1l))
-
-#define ROUND_UP(n, align) \
-    ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
-
-/* round to 16 bytes + alloc at minimum 16 bytes */
-#define ROUND_SIZE(size) (max(16, ROUND_UP(size, 16)))
-
-/*
- * @implemented
- */
-void* malloc(size_t _size)
-{
-   size_t nSize = ROUND_SIZE(_size);
-
-   if (nSize<_size)
-       return NULL;
-
-   return HeapAlloc(GetProcessHeap(), 0, nSize);
-}
-
-/*
- * @implemented
- */
-void free(void* _ptr)
-{
-   HeapFree(GetProcessHeap(),0,_ptr);
-}
-
-/*
- * @implemented
- */
-void* calloc(size_t _nmemb, size_t _size)
-{
-   size_t nSize = _nmemb * _size;
-   size_t cSize = ROUND_SIZE(nSize);
-
-   if ( (_nmemb > ((size_t)-1 / _size))  || (cSize<nSize))
-      return NULL;
-
-   return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cSize );
-}
-
-/*
- * @implemented
- */
-void* realloc(void* _ptr, size_t _size)
-{
-   size_t nSize;
-
-   if (_ptr == NULL)
-      return malloc(_size);
-
-   if (_size == 0)
-   {
-   	   free(_ptr);
-       return NULL;
-   }
-
-   nSize = ROUND_SIZE(_size);
-
-   /* check for integer overflow */
-   if (nSize<_size)
-       return NULL;
-
-   return HeapReAlloc(GetProcessHeap(), 0, _ptr, nSize);
-}
-
-/*
- * @implemented
- */
-void* _expand(void* _ptr, size_t _size)
-{
-   size_t nSize;
-
-   nSize = ROUND_SIZE(_size);
-
-   if (nSize<_size)
-       return NULL;
-
-   return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, _ptr, nSize);
-}
-
-/*
- * @implemented
- */
-size_t _msize(void* _ptr)
-{
-   return HeapSize(GetProcessHeap(), 0, _ptr);
-}
-
-/*
- * @implemented
- */
-int	_heapchk(void)
-{
-	if (!HeapValidate(GetProcessHeap(), 0, NULL))
-		return -1;
-	return 0;
-}
-
-/*
- * @implemented
- */
-int	_heapmin(void)
-{
-	if (!HeapCompact(GetProcessHeap(), 0))
-		return -1;
-	return 0;
-}
-
-/*
- * @implemented
- */
-int	_heapset(unsigned int unFill)
-{
-	if (_heapchk() == -1)
-		return -1;
-	return 0;
-
-}
-
-/*
- * @implemented
- */
-int _heapwalk(struct _heapinfo* entry)
-{
-	return 0;
-}
-
Index: crt/string/atof.c
===================================================================
--- crt/string/atof.c	(revision 47065)
+++ crt/string/atof.c	(working copy)
@@ -1,11 +1,17 @@
 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
 #include <precomp.h>
+#include <stdlib.h>
 
 /*
  * @implemented
  */
-double
-atof(const char *ascii)
+double CDECL
+atof(const char *str)
 {
-  return strtod(ascii, 0);
+  return _strtod_l(str, NULL,NULL);
 }
+
+double CDECL _atof_l( const char *str, _locale_t locale)
+{
+    return _strtod_l(str, NULL, locale);
+}
Index: crt/string/atol.c
===================================================================
--- crt/string/atol.c	(revision 47065)
+++ crt/string/atol.c	(working copy)
@@ -15,5 +15,5 @@
 {
     /* FIXME needs error checking for huge/small values */
    //*value = strtold(str,0);
-   return -1;
+   return 0;
 }
Index: crt/string/lasttok.c
===================================================================
--- crt/string/lasttok.c	(revision 47065)
+++ crt/string/lasttok.c	(working copy)
@@ -1,26 +0,0 @@
-/*
- * COPYRIGHT:   See COPYING in the top level directory
- * PROJECT:     ReactOS system libraries
- * FILE:        lib/crt/??????
- * PURPOSE:     Unknown
- * PROGRAMER:   Unknown
- * UPDATE HISTORY:
- *              25/11/05: Added license header
- */
-#include <precomp.h>
-
-#include <internal/tls.h>
-#include <assert.h>
-
-/*
- * This is an MSVCRT internal function to return the lasttoken
- * bit of data used by strtok. The reason for it's existence is
- * so that CRTDLL can use the strtok source code in the same
- * file.
- */
-char** _lasttoken()
-{
-	PTHREADDATA ptd = GetThreadData();
-	assert(ptd);
-	return &(ptd->lasttoken);
-}
Index: crt/string/scanf.c
===================================================================
--- crt/string/scanf.c	(revision 47065)
+++ crt/string/scanf.c	(working copy)
@@ -25,7 +25,14 @@
 
 #include <precomp.h>
 #include <ctype.h>
+#include <locale.h>
 
+#ifdef _LIBCNT_
+_locale_t get_locale(void){ return NULL; }
+#else
+_locale_t get_locale(void); //defined in locale.c
+#endif 
+
 // HACK for LIBCNT
 #ifndef debugstr_a
 #define debugstr_a
@@ -56,39 +63,74 @@
 }
 
 #ifndef _LIBCNT_
-/* vfscanf */
+/* vfscanf_l */
 #undef WIDE_SCANF
 #undef CONSOLE
 #undef STRING
+#undef SECURE
 #include "scanf.h"
 
-/* vfwscanf */
+/* vfscanf_l */
+#define SECURE 1
+#include "scanf.h"
+
+/* vfwscanf_l */
 #define WIDE_SCANF 1
 #undef CONSOLE
 #undef STRING
+#undef SECURE
 #include "scanf.h"
+
+/* vfwscanf_s_l */
+#define SECURE 1
+#include "scanf.h"
 #endif
 
-/* vsscanf */
+/* vsscanf_l */
 #undef WIDE_SCANF
 #undef CONSOLE
 #define STRING 1
+#undef SECURE
 #include "scanf.h"
 
-/* vswscanf */
+/* vsscanf_s_l */
+#define SECURE 1
+#include "scanf.h"
+
+/* vswscanf_l */
 #define WIDE_SCANF 1
 #undef CONSOLE
 #define STRING 1
+#undef SECURE
 #include "scanf.h"
 
+/* vswscanf_s_l */
+#define SECURE 1
+#include "scanf.h"
+
 #ifndef _LIBCNT_
-/* vcscanf */
+/* vcscanf_l */
 #undef WIDE_SCANF
 #define CONSOLE 1
 #undef STRING
+#undef SECURE
 #include "scanf.h"
 
+/* vcscanf_s_l */
+#define SECURE 1
+#include "scanf.h"
 
+/* vcwscanf_l */
+#define WIDE_SCANF 1
+#define CONSOLE 1
+#undef STRING
+#undef SECURE
+#include "scanf.h"
+
+/* vcwscanf_s_l */
+#define SECURE 1
+#include "scanf.h"
+
 /*********************************************************************
  *		fscanf (MSVCRT.@)
  */
@@ -98,26 +140,112 @@
     int res;
 
     va_start(valist, format);
-    res = vfscanf(file, format, valist);
+    res = vfscanf_l(file, format, NULL, valist);
     va_end(valist);
     return res;
 }
 
 /*********************************************************************
+ *		_fscanf_l (MSVCRT.@)
+ */
+int CDECL _fscanf_l(FILE *file, const char *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vfscanf_l(file, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		fscanf_s (MSVCRT.@)
+ */
+int CDECL fscanf_s(FILE *file, const char *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vfscanf_s_l(file, format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_fscanf_s_l (MSVCRT.@)
+ */
+int CDECL _fscanf_s_l(FILE *file, const char *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vfscanf_s_l(file, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
  *		scanf (MSVCRT.@)
  */
-int scanf(const char *format, ...)
+int CDECL scanf(const char *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vfscanf(stdin, format, valist);
+    res = vfscanf_l(stdin, format, NULL, valist);
     va_end(valist);
     return res;
 }
 
 /*********************************************************************
+ *		_scanf_l (MSVCRT.@)
+ */
+int CDECL _scanf_l(const char *format, _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vfscanf_l(stdin, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		scanf_s (MSVCRT.@)
+ */
+int CDECL scanf_s(const char *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vfscanf_s_l(stdin, format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_scanf_s_l (MSVCRT.@)
+ */
+int CDECL _scanf_s_l(const char *format, _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vfscanf_s_l(stdin, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
  *		fwscanf (MSVCRT.@)
  */
 int fwscanf(FILE *file, const wchar_t *format, ...)
@@ -126,44 +254,174 @@
     int res;
 
     va_start(valist, format);
-    res = vfwscanf(file, format, valist);
+    res = vfwscanf_l(file, format, NULL, valist);
     va_end(valist);
     return res;
 }
 
+/*********************************************************************
+ *		_fwscanf_l (MSVCRT.@)
+ */
+int CDECL _fwscanf_l(FILE *file, const wchar_t *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
 
+    va_start(valist, locale);
+    res = vfwscanf_l(file, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
 /*********************************************************************
+ *		fwscanf_s (MSVCRT.@)
+ */
+int CDECL fwscanf_s(FILE *file, const wchar_t *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vfwscanf_s_l(file, format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_fwscanf_s_l (MSVCRT.@)
+ */
+int CDECL _fwscanf_s_l(FILE *file, const wchar_t *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vfwscanf_s_l(file, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+
+/*********************************************************************
  *		wscanf (MSVCRT.@)
  */
-int wscanf(const wchar_t *format, ...)
+int CDECL wscanf(const wchar_t *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vfwscanf(stdin, format, valist);
+    res = vfwscanf_l(stdin, format, NULL, valist);
     va_end(valist);
     return res;
 }
-#endif
 
+/*********************************************************************
+ *		_wscanf_l (MSVCRT.@)
+ */
+int CDECL _wscanf_l(const wchar_t *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
 
+    va_start(valist, locale);
+    res = vfwscanf_l(stdin, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
 /*********************************************************************
+ *		wscanf_s (MSVCRT.@)
+ */
+int CDECL wscanf_s(const wchar_t *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vfwscanf_s_l(stdin, format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_wscanf_s_l (MSVCRT.@)
+ */
+int CDECL _wscanf_s_l(const wchar_t *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vfwscanf_s_l(stdin, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+#endif
+
+/*********************************************************************
  *		sscanf (MSVCRT.@)
  */
-int sscanf(const char *str, const char *format, ...)
+int CDECL sscanf(const char *str, const char *format, ...)
 {
     va_list valist;
     int res;
 
     va_start(valist, format);
-    res = vsscanf(str, format, valist);
+    res = vsscanf_l(str, format, NULL, valist);
     va_end(valist);
     return res;
 }
 
+/*********************************************************************
+ *		_sscanf_l (MSVCRT.@)
+ */
+int CDECL _sscanf_l(const char *str, const char *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
 
+    va_start(valist, locale);
+    res = vsscanf_l(str, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
 /*********************************************************************
+ *		sscanf_s (MSVCRT.@)
+ */
+int CDECL sscanf_s(const char *str, const char *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vsscanf_s_l(str, format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_sscanf_s_l (MSVCRT.@)
+ */
+int CDECL _sscanf_s_l(const char *str, const char *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vsscanf_s_l(str, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
  *		swscanf (MSVCRT.@)
  */
 int CDECL swscanf(const wchar_t *str, const wchar_t *format, ...)
@@ -172,11 +430,55 @@
     int res;
 
     va_start(valist, format);
-    res = vswscanf(str, format, valist);
+    res = vswscanf_l(str, format, NULL, valist);
     va_end(valist);
     return res;
 }
 
+/*********************************************************************
+ *		_swscanf_l (MSVCRT.@)
+ */
+int CDECL _swscanf_l(const wchar_t *str, const wchar_t *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vswscanf_l(str, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		swscanf_s (MSVCRT.@)
+ */
+int CDECL swscanf_s(const wchar_t *str, const wchar_t *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vswscanf_s_l(str, format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_swscanf_s_l (MSVCRT.@)
+ */
+int CDECL _swscanf_s_l(const wchar_t *str, const wchar_t *format,
+        _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vswscanf_s_l(str, format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
 #ifndef _LIBCNT_
 /*********************************************************************
  *		_cscanf (MSVCRT.@)
@@ -187,8 +489,106 @@
     int res;
 
     va_start(valist, format);
-    res = vcscanf(format, valist);
+    res = vcscanf_l(format, NULL, valist);
     va_end(valist);
     return res;
 }
+
+/*********************************************************************
+ *		_cscanf_l (MSVCRT.@)
+ */
+int CDECL _cscanf_l(const char *format, _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vcscanf_l(format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_cscanf_s (MSVCRT.@)
+ */
+int CDECL _cscanf_s(const char *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vcscanf_s_l(format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_cscanf_s_l (MSVCRT.@)
+ */
+int CDECL _cscanf_s_l(const char *format, _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vcscanf_s_l(format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_cwscanf (MSVCRT.@)
+ */
+int CDECL _cwscanf(const wchar_t *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vcwscanf_l(format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_cwscanf_l (MSVCRT.@)
+ */
+int CDECL _cwscanf_l(const wchar_t *format, _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vcwscanf_l(format, locale, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_cwscanf_s (MSVCRT.@)
+ */
+int CDECL _cwscanf_s(const wchar_t *format, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, format);
+    res = vcwscanf_s_l(format, NULL, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_cwscanf_s_l (MSVCRT.@)
+ */
+int CDECL _cwscanf_s_l(const wchar_t *format, _locale_t locale, ...)
+{
+    va_list valist;
+    int res;
+
+    va_start(valist, locale);
+    res = vcwscanf_s_l(format, locale, valist);
+    va_end(valist);
+    return res;
+}
 #endif
Index: crt/string/scanf.h
===================================================================
--- crt/string/scanf.h	(revision 47065)
+++ crt/string/scanf.h	(working copy)
@@ -48,7 +48,19 @@
 #ifdef CONSOLE
 #define _GETC_(file) (consumed++, _getch())
 #define _UNGETC_(nch, file) do { _ungetch(nch); consumed--; } while(0)
-#define _FUNCTION_ int vcscanf(const char *format, va_list ap)
+#ifdef WIDE_SCANF
+#ifdef SECURE
+#define _FUNCTION_ static int vcwscanf_s_l(const wchar_t *format, _locale_t locale, va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vcwscanf_l(const wchar_t *format, _locale_t locale, va_list ap)
+#endif /* SECURE */
+#else  /* WIDE_SCANF */
+#ifdef SECURE
+#define _FUNCTION_ static int vcscanf_s_l(const char *format, _locale_t locale, va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vcscanf_l(const char *format, _locale_t locale, va_list ap)
+#endif /* SECURE */
+#endif /* WIDE_SCANF */
 #else
 #ifdef STRING
 #undef _EOF_
@@ -56,19 +68,35 @@
 #define _GETC_(file) (consumed++, *file++)
 #define _UNGETC_(nch, file) do { file--; consumed--; } while(0)
 #ifdef WIDE_SCANF
-#define _FUNCTION_ int vswscanf(const wchar_t *file, const wchar_t *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vswscanf_s_l(const wchar_t *file, const wchar_t *format, _locale_t locale, va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vswscanf_l(const wchar_t *file, const wchar_t *format, _locale_t locale, va_list ap)
+#endif /* SECURE */
 #else /* WIDE_SCANF */
-#define _FUNCTION_ int vsscanf(const char *file, const char *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vsscanf_s_l(const char *file, const char *format, _locale_t locale, va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vsscanf_l(const char *file, const char *format, _locale_t locale, va_list ap)
+#endif /* SECURE */
 #endif /* WIDE_SCANF */
 #else /* STRING */
 #ifdef WIDE_SCANF
 #define _GETC_(file) (consumed++, fgetwc(file))
 #define _UNGETC_(nch, file) do { ungetwc(nch, file); consumed--; } while(0)
-#define _FUNCTION_ int vfwscanf(FILE* file, const wchar_t *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vfwscanf_s_l(FILE* file, const wchar_t *format, _locale_t locale, va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vfwscanf_l(FILE* file, const wchar_t *format, _locale_t locale, va_list ap)
+#endif /* SECURE */
 #else /* WIDE_SCANF */
 #define _GETC_(file) (consumed++, fgetc(file))
 #define _UNGETC_(nch, file) do { ungetc(nch, file); consumed--; } while(0)
-#define _FUNCTION_ int vfscanf(FILE* file, const char *format, va_list ap)
+#ifdef SECURE
+#define _FUNCTION_ static int vfscanf_s_l(FILE* file, const char *format, _locale_t locale, va_list ap)
+#else  /* SECURE */
+#define _FUNCTION_ static int vfscanf_l(FILE* file, const char *format, _locale_t locale, va_list ap)
+#endif /* SECURE */
 #endif /* WIDE_SCANF */
 #endif /* STRING */
 #endif /* CONSOLE */
@@ -82,7 +110,7 @@
     TRACE("(%s):\n", debugstr_a(format));
 #else /* CONSOLE */
 #ifdef STRING
-    TRACE("%s (%s)\n", file, debugstr_a(format));
+    TRACE("%s (%s)\n", debugstr_a(file), debugstr_a(format));
 #else /* STRING */
     TRACE("%p (%s)\n", file, debugstr_a(format));
 #endif /* STRING */
@@ -91,6 +119,9 @@
     nch = _GETC_(file);
     if (nch == _EOF_) return _EOF_RET;
 
+    if(!locale)
+        locale = get_locale();
+
     while (*format) {
 	/* a whitespace character in the format string causes scanf to read,
 	 * but not store, all consecutive white-space characters in the input
@@ -250,7 +281,7 @@
                         nch = _GETC_(file);
                     }
 		    /* get first digit. */
-		    if ('.' != nch) {
+		    if (*locale->locinfo->lconv->decimal_point != nch) {
 		      if (!_ISDIGIT_(nch)) break;
 		      cur = (nch - '0');
 		      nch = _GETC_(file);
@@ -262,10 +293,10 @@
 			if (width>0) width--;
 		      }
 		    } else {
-		      cur = 0; /* MaxPayneDemo Fix: .8 -> 0.8 */
+		      cur = 0; /* Fix: .8 -> 0.8 */
 		    }
 		    /* handle decimals */
-                    if (width!=0 && nch == '.') {
+                    if (width!=0 && nch == *locale->locinfo->lconv->decimal_point) {
                         long double dec = 1;
                         nch = _GETC_(file);
 			if (width>0) width--;
@@ -336,12 +367,25 @@
 #endif /* WIDE_SCANF */
 	    charstring: { /* read a word into a char */
 		    char *sptr = suppress ? NULL : va_arg(ap, char*);
+                    char *sptr_beg = sptr;
+#ifdef SECURE
+                    unsigned size = suppress ? UINT_MAX : va_arg(ap, unsigned);
+#else
+                    unsigned size = UINT_MAX;
+#endif
                     /* skip initial whitespace */
                     while ((nch!=_EOF_) && _ISSPACE_(nch))
                         nch = _GETC_(file);
                     /* read until whitespace */
                     while (width!=0 && (nch!=_EOF_) && !_ISSPACE_(nch)) {
-                        if (!suppress) *sptr++ = _CHAR2SUPPORTED_(nch);
+                        if (!suppress) {
+                            *sptr++ = _CHAR2SUPPORTED_(nch);
+                            if(size>1) size--;
+                            else {
+                                *sptr_beg = 0;
+                                return rd;
+                            }
+                        }
 			st++;
                         nch = _GETC_(file);
 			if (width>0) width--;
@@ -352,12 +396,25 @@
                 break;
 	    widecharstring: { /* read a word into a wchar_t* */
 		    wchar_t *sptr = suppress ? NULL : va_arg(ap, wchar_t*);
+                    wchar_t *sptr_beg = sptr;
+#ifdef SECURE
+                    unsigned size = suppress ? UINT_MAX : va_arg(ap, unsigned);
+#else
+                    unsigned size = UINT_MAX;
+#endif
                     /* skip initial whitespace */
                     while ((nch!=_EOF_) && _ISSPACE_(nch))
                         nch = _GETC_(file);
                     /* read until whitespace */
                     while (width!=0 && (nch!=_EOF_) && !_ISSPACE_(nch)) {
-                        if (!suppress) *sptr++ = _WIDE2SUPPORTED_(nch);
+                        if (!suppress) {
+                            *sptr++ = _WIDE2SUPPORTED_(nch);
+                            if(size>1) size--;
+                            else {
+                                *sptr_beg = 0;
+                                return rd;
+                            }
+                        }
 			st++;
                         nch = _GETC_(file);
 			if (width>0) width--;
@@ -386,10 +443,23 @@
 #endif /* WIDE_SCANF */
 	  character: { /* read single character into char */
                     char *str = suppress ? NULL : va_arg(ap, char*);
+                    char *pstr = str;
+#ifdef SECURE
+                    unsigned size = suppress ? UINT_MAX : va_arg(ap, unsigned)/sizeof(char);
+#else
+                    unsigned size = UINT_MAX;
+#endif
                     if (width == -1) width = 1;
-                    while ((width != 0) && (nch != _EOF_))
+                    while (width && (nch != _EOF_))
                     {
-                        if (!suppress) *str++ = _CHAR2SUPPORTED_(nch);
+                        if (!suppress) {
+                            *str++ = _CHAR2SUPPORTED_(nch);
+                            if(size) size--;
+                            else {
+                                *pstr = 0;
+                                return rd;
+                            }
+                        }
                         st++;
                         width--;
                         nch = _GETC_(file);
@@ -398,10 +468,23 @@
 		break;
 	  widecharacter: { /* read single character into a wchar_t */
                     wchar_t *str = suppress ? NULL : va_arg(ap, wchar_t*);
+                    wchar_t *pstr = str;
+#ifdef SECURE
+                    unsigned size = suppress ? UINT_MAX : va_arg(ap, unsigned)/sizeof(wchar_t);
+#else
+                    unsigned size = UINT_MAX;
+#endif
                     if (width == -1) width = 1;
-                    while ((width != 0) && (nch != _EOF_))
+                    while (width && (nch != _EOF_))
                     {
-                        if (!suppress) *str++ = _WIDE2SUPPORTED_(nch);
+                        if (!suppress) {
+                            *str++ = _WIDE2SUPPORTED_(nch);
+                            if(size) size--;
+                            else {
+                                *pstr = 0;
+                                return rd;
+                            }
+                        }
                         st++;
                         width--;
                         nch = _GETC_(file);
@@ -434,14 +517,19 @@
 		    RTL_BITMAP bitMask;
                     ULONG *Mask;
 		    int invert = 0; /* Set if we are NOT to find the chars */
+#ifdef SECURE
+                    unsigned size = suppress ? UINT_MAX : va_arg(ap, unsigned)/sizeof(_CHAR_);
+#else
+                    unsigned size = UINT_MAX;
+#endif
 
-            /* Init our bitmap */
+		    /* Init our bitmap */
 #ifdef _LIBCNT_
-            Mask = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, _BITMAPSIZE_/8);
+		    Mask = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, _BITMAPSIZE_/8);
 #else
-            Mask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _BITMAPSIZE_/8);
+		    Mask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _BITMAPSIZE_/8);
 #endif
-            RtlInitializeBitMap(&bitMask, Mask, _BITMAPSIZE_);
+		    RtlInitializeBitMap(&bitMask, Mask, _BITMAPSIZE_);
 
 		    /* Read the format */
 		    format++;
@@ -482,6 +570,11 @@
                         st++;
                         nch = _GETC_(file);
                         if (width>0) width--;
+                        if(size>1) size--;
+                        else {
+                            *str = 0;
+                            return rd;
+                        }
                     }
                     /* terminate */
                     if (!suppress) *sptr = 0;
Index: crt/string/strcoll.c
===================================================================
--- crt/string/strcoll.c	(revision 47065)
+++ crt/string/strcoll.c	(working copy)
@@ -14,7 +14,7 @@
    greater than zero if the collated form of S1 is lexicographically
    less than, equal to or greater than the collated form of S2.  */
 
-#if 1
+
 /*
  * @unimplemented
  */
@@ -24,22 +24,12 @@
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 int _stricoll(const char* s1, const char* s2)
 {
-    return _stricmp(s1, s2);
+  /* FIXME: handle collates */
+  TRACE("str1 %s str2 %s\n", debugstr_a(s1), debugstr_a(s2));
+  return lstrcmpiA( s1, s2 );
 }
 
-#else
-int strcoll (const char* s1,const char* s2)
-{
-    int ret;
-    ret = CompareStringA(LOCALE_USER_DEFAULT,0,s1,strlen(s1),s2,strlen(s2));
-    if (ret == 0)
-        return 0;
-    else
-        return ret - 2;
-    return 0;
-}
-#endif
Index: crt/string/strdup.c
===================================================================
--- crt/string/strdup.c	(revision 47065)
+++ crt/string/strdup.c	(working copy)
@@ -4,14 +4,14 @@
 /*
  * @implemented
  */
-char *_strdup(const char *_s)
+char *_strdup(const char *str)
 {
-  char *rv;
-  if (_s == 0)
-    return 0;
-  rv = (char *)malloc(strlen(_s) + 1);
-  if (rv == 0)
-    return 0;
-  strcpy(rv, _s);
-  return rv;
+    if(str)
+    {
+      char * ret = malloc(strlen(str)+1);
+      if (ret) strcpy( ret, str );
+      return ret;
+    }
+    else return 0;
 }
+
Index: crt/string/strrev.c
===================================================================
--- crt/string/strrev.c	(revision 47065)
+++ crt/string/strrev.c	(working copy)
@@ -13,20 +13,18 @@
 /*
  * @implemented
  */
-char * _strrev(char *s)
+char* CDECL _strrev(char *str)
 {
-	char a, *b, *e;
-	b=e=s;
-	while (*e)
-		e++;
-	e--; /* start at last char, not NULL char */
-	while ( b < e )
-	{
-		a=*b;
-		*b=*e;
-		*e=a;
-		b++;
-		e--;
-	}
-	return s; /* return ptr to beginning of string */
+  char * p1;
+  char * p2;
+
+  if (str && *str)
+    for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
+    {
+      *p1 ^= *p2;
+      *p2 ^= *p1;
+      *p1 ^= *p2;
+    }
+
+  return str;
 }
Index: crt/string/strset.c
===================================================================
--- crt/string/strset.c	(revision 47065)
+++ crt/string/strset.c	(working copy)
@@ -8,44 +8,27 @@
  *              25/11/05: Added license header
  */
 
-#if defined(__GNUC__)
-#define __int64 long long
-#endif
+#include <precomp.h>
 
-#ifdef _WIN64
-typedef unsigned __int64 size_t;
-#else
-typedef unsigned int size_t;
-#endif
-
 /*
  * @implemented
  */
-char* _strnset(char* szToFill, int szFill, size_t sizeMaxFill)
+char* CDECL _strnset(char* str, int value, size_t len)
 {
-	char *t = szToFill;
-	int i = 0;
-	while (*szToFill != 0 && i < (int) sizeMaxFill)
-	{
-		*szToFill = szFill;
-		szToFill++;
-		i++;
-
-	}
-	return t;
+  if (len > 0 && str)
+    while (*str && len--)
+      *str++ = value;
+  return str;
 }
 
 /*
  * @implemented
  */
-char* _strset(char* szToFill, int szFill)
+char* CDECL _strset(char* str, int value)
 {
-	char *t = szToFill;
-	while (*szToFill != 0)
-	{
-		*szToFill = szFill;
-		szToFill++;
+  char *ptr = str;
+  while (*ptr)
+    *ptr++ = value;
 
-	}
-	return t;
+  return str;
 }
Index: crt/string/strtod.c
===================================================================
--- crt/string/strtod.c	(revision 47065)
+++ crt/string/strtod.c	(working copy)
@@ -1,103 +1,118 @@
-/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
-/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
 
 #include <precomp.h>
+#include <locale.h>
+#include <internal/wine/msvcrt.h>
 
-/*
- * @implemented
+/*********************************************************************
+ *		_strtod_l  (MSVCRT.@)
  */
-double
-strtod(const char *s, char **sret)
+double CDECL _strtod_l( const char *str, char **end, _locale_t locale)
 {
-  long double r;		/* result */
-  int e;			/* exponent */
-  long double d;		/* scale */
-  int sign;			/* +- 1.0 */
-  int esign;
-  int i;
-  int flags=0;
+    unsigned __int64 d=0, hlp;
+    int exp=0, sign=1;
+    const char *p;
+    double ret;
 
-  r = 0.0;
-  sign = 1;
-  e = 0;
-  esign = 1;
+    if(!str) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return 0;
+    }
 
-  if (s == NULL)
-     return r;
+    if(!locale)
+        locale = get_locale();
 
+    /* FIXME: use *_l functions */
+    p = str;
+    while(isspace(*p))
+        p++;
 
-  while ((*s == ' ') || (*s == '\t'))
-    s++;
+    if(*p == '-') {
+        sign = -1;
+        p++;
+    } else  if(*p == '+')
+        p++;
 
-  if (*s == '+')
-    s++;
-  else if (*s == '-')
-  {
-    sign = -1;
-    s++;
-  }
+    while(isdigit(*p)) {
+        hlp = d*10+*(p++)-'0';
+        if(d>UINT64_MAX/10 || hlp<d) {
+            exp++;
+            break;
+        } else
+            d = hlp;
+    }
+    while(isdigit(*p)) {
+        exp++;
+        p++;
+    }
 
-  while ((*s >= '0') && (*s <= '9'))
-  {
-    flags |= 1;
-    r *= 10.0;
-    r += *s - '0';
-    s++;
-  }
+    if(*p == *locale->locinfo->lconv->decimal_point)
+        p++;
 
-  if (*s == '.')
-  {
-    d = 0.1L;
-    s++;
-    while ((*s >= '0') && (*s <= '9'))
-    {
-      flags |= 2;
-      r += d * (*s - '0');
-      s++;
-      d *= 0.1L;
+    while(isdigit(*p)) {
+        hlp = d*10+*(p++)-'0';
+        if(d>UINT64_MAX/10 || hlp<d)
+            break;
+
+        d = hlp;
+        exp--;
     }
-  }
+    while(isdigit(*p))
+        p++;
 
-  if (flags == 0)
-  {
-    if (sret)
-      *sret = (char *)s;
-    return 0;
-  }
-
-  if ((*s == 'e') || (*s == 'E'))
-  {
-    s++;
-    if (*s == '+')
-      s++;
-    else if (*s == '-')
-    {
-      s++;
-      esign = -1;
+    if(p == str) {
+        if(end)
+            *end = (char*)str;
+        return 0.0;
     }
-    if ((*s < '0') || (*s > '9'))
-    {
-      if (sret)
-	*sret = (char *)s;
-      return r;
-    }
 
-    while ((*s >= '0') && (*s <= '9'))
-    {
-      e *= 10;
-      e += *s - '0';
-      s++;
+    if(*p=='e' || *p=='E' || *p=='d' || *p=='D') {
+        int e=0, s=1;
+
+        p++;
+        if(*p == '-') {
+            s = -1;
+            p++;
+        } else if(*p == '+')
+            p++;
+
+        if(isdigit(*p)) {
+            while(isdigit(*p)) {
+                if(e>INT_MAX/10 || (e=e*10+*p-'0')<0)
+                    e = INT_MAX;
+                p++;
+            }
+            e *= s;
+
+            if(exp<0 && e<0 && exp+e>=0) exp = INT_MIN;
+            else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
+            else exp += e;
+        } else {
+            if(*p=='-' || *p=='+')
+                p--;
+            p--;
+        }
     }
-  }
 
-  if (esign < 0)
-    for (i = 1; i <= e; i++)
-      r *= 0.1L;
-  else
-    for (i = 1; i <= e; i++)
-      r *= 10.0;
+    if(exp>0)
+        ret = (double)sign*d*pow(10, exp);
+    else
+        ret = (double)sign*d/pow(10, -exp);
 
-  if (sret)
-    *sret = (char *)s;
-  return r * sign;
+    if((d && ret==0.0) || isinf(ret))
+        *_errno() = ERANGE;
+
+    if(end)
+        *end = (char*)p;
+
+    return ret;
 }
+
+/*
+ * @implemented
+ */
+double
+strtod(const char *str, char **end)
+{
+    return _strtod_l( str, end, NULL );
+}
Index: crt/string/strtoi64.c
===================================================================
--- crt/string/strtoi64.c	(revision 47065)
+++ crt/string/strtoi64.c	(working copy)
@@ -1,12 +1,156 @@
 #include <precomp.h>
 
+/*********************************************************************
+ *  _strtoi64_l (MSVCR90.@)
+ *
+ * FIXME: locale parameter is ignored
+ */
+__int64 CDECL _strtoi64_l(const char *nptr, char **endptr, int base, _locale_t locale)
+{
+    BOOL negative = FALSE;
+    __int64 ret = 0;
 
+    TRACE("(%s %p %d %p)\n", nptr, endptr, base, locale);
+
+    if(!nptr || base<0 || base>36 || base==1) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        return 0;
+    }
+
+    while(isspace(*nptr)) nptr++;
+
+    if(*nptr == '-') {
+        negative = TRUE;
+        nptr++;
+    } else if(*nptr == '+')
+        nptr++;
+
+    if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
+        base = 16;
+        nptr += 2;
+    }
+
+    if(base == 0) {
+        if(*nptr=='0')
+            base = 8;
+        else
+            base = 10;
+    }
+
+    while(*nptr) {
+        char cur = tolower(*nptr);
+        int v;
+
+        if(isdigit(cur)) {
+            if(cur >= '0'+base)
+                break;
+            v = cur-'0';
+        } else {
+            if(cur<'a' || cur>='a'+base-10)
+                break;
+            v = cur-'a'+10;
+        }
+
+        if(negative)
+            v = -v;
+
+        nptr++;
+
+        if(!negative && (ret>INT64_MAX/base || ret*base>INT64_MAX-v)) {
+            ret = INT64_MAX;
+            *_errno() = ERANGE;
+        } else if(negative && (ret<INT64_MIN/base || ret*base<INT64_MIN-v)) {
+            ret = INT64_MIN;
+            *_errno() = ERANGE;
+        } else
+            ret = ret*base + v;
+    }
+
+    if(endptr)
+        *endptr = (char*)nptr;
+
+    return ret;
+}
+
 __int64
 _strtoi64(const char *nptr, char **endptr, int base)
 {
-   TRACE("_strtoi64 is UNIMPLEMENTED\n");
-   return 0;
+   return _strtoi64_l(nptr, endptr, base, NULL);
 }
 
+/*********************************************************************
+ *  _strtoui64_l (MSVCR90.@)
+ *
+ * FIXME: locale parameter is ignored
+ */
+unsigned __int64 CDECL _strtoui64_l(const char *nptr, char **endptr, int base, _locale_t locale)
+{
+    BOOL negative = FALSE;
+    unsigned __int64 ret = 0;
 
+    TRACE("(%s %p %d %p)\n", nptr, endptr, base, locale);
+
+    if(!nptr || base<0 || base>36 || base==1) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        return 0;
+    }
+
+    while(isspace(*nptr)) nptr++;
+
+    if(*nptr == '-') {
+        negative = TRUE;
+        nptr++;
+    } else if(*nptr == '+')
+        nptr++;
+
+    if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
+        base = 16;
+        nptr += 2;
+    }
+
+    if(base == 0) {
+        if(*nptr=='0')
+            base = 8;
+        else
+            base = 10;
+    }
+
+    while(*nptr) {
+        char cur = tolower(*nptr);
+        int v;
+
+        if(isdigit(cur)) {
+            if(cur >= '0'+base)
+                break;
+            v = *nptr-'0';
+        } else {
+            if(cur<'a' || cur>='a'+base-10)
+                break;
+            v = cur-'a'+10;
+        }
+
+        nptr++;
+
+        if(ret>UINT64_MAX/base || ret*base>UINT64_MAX-v) {
+            ret = UINT64_MAX;
+            *_errno() = ERANGE;
+        } else
+            ret = ret*base + v;
+    }
+
+    if(endptr)
+        *endptr = (char*)nptr;
+
+    return negative ? -ret : ret;
+}
+
+/*********************************************************************
+ *  _strtoui64 (MSVCR90.@)
+ */
+unsigned __int64 CDECL _strtoui64(const char *nptr, char **endptr, int base)
+{
+    return _strtoui64_l(nptr, endptr, base, NULL);
+}
+
+
 /* EOF */
Index: crt/string/strtok.c
===================================================================
--- crt/string/strtok.c	(revision 47065)
+++ crt/string/strtok.c	(working copy)
@@ -2,61 +2,53 @@
 #include <precomp.h>
 
 #include <string.h>
+#include <internal/wine/msvcrt.h>
 #include <internal/tls.h>
 
-char** _lasttoken(); /* lasttok.c */
+/*********************************************************************
+ *		strtok  (MSVCRT.@)
+ */
+char* strtok(char* str, const char* delim)
+{
+    MSVCRT_thread_data *data = msvcrt_get_thread_data();
+    char *ret;
 
-/*
- * @implemented
+    if (!str)
+        if (!(str = data->strtok_next)) return NULL;
+
+    while (*str && strchr( delim, *str )) str++;
+    if (!*str) return NULL;
+    ret = str++;
+    while (*str && !strchr( delim, *str )) str++;
+    if (*str) *str++ = 0;
+    data->strtok_next = str;
+    return ret;
+}
+
+/*********************************************************************
+ *		strtok_s  (MSVCRT.@)
  */
-char* strtok(char* s, const char* delim)
+char * CDECL strtok_s(char *str, const char *delim, char **ctx)
 {
-  const char *spanp;
-  int c, sc;
-  char *tok;
-#if 1
-  char ** lasttoken = _lasttoken();
-#else
-  PTHREADDATA ThreadData = GetThreadData();
-  char ** lasttoken = &ThreadData->lasttoken;
-#endif
+    if(!delim || !ctx || (!str && !*ctx)) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return NULL;
+    }
 
-  if (s == NULL && (s = *lasttoken) == NULL)
-    return (NULL);
+    if(!str)
+        str = *ctx;
 
-  /*
-   * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
-   */
- cont:
-  c = *s++;
-  for (spanp = delim; (sc = *spanp++) != 0;) {
-    if (c == sc)
-      goto cont;
-  }
+    while(*str && strchr(delim, *str))
+        str++;
+    if(!*str)
+        return NULL;
 
-  if (c == 0) {			/* no non-delimiter characters */
-    *lasttoken = NULL;
-    return (NULL);
-  }
-  tok = s - 1;
+    *ctx = str+1;
+    while(**ctx && !strchr(delim, **ctx))
+        (*ctx)++;
+    if(**ctx)
+        *(*ctx)++ = 0;
 
-  /*
-   * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
-   * Note that delim must have one NUL; we stop if we see that, too.
-   */
-  for (;;) {
-    c = *s++;
-    spanp = delim;
-    do {
-      if ((sc = *spanp++) == c) {
-	if (c == 0)
-	  s = NULL;
-	else
-	  s[-1] = 0;
-	*lasttoken = s;
-	return (tok);
-      }
-    } while (sc != 0);
-  }
-  /* NOTREACHED */
+    return str;
 }
Index: crt/string/strtold.c
===================================================================
--- crt/string/strtold.c	(revision 47065)
+++ crt/string/strtold.c	(working copy)
@@ -1,6 +1,6 @@
 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
 #include <stdlib.h>
-#include <msvcrt/ctype.h>
+#include <ctype.h>
 
 static double powten[] =
 {
@@ -13,7 +13,7 @@
 };
 
 long double
-_strtold(const char *s, char **sret)
+strtold(const char *s, char **sret)
 {
   double r;		/* result */
   int e, ne;			/* exponent */
Index: crt/string/wcs.c
===================================================================
--- crt/string/wcs.c	(revision 47065)
+++ crt/string/wcs.c	(working copy)
@@ -27,19 +27,18 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
+#define MINGW_HAS_SECURE_API 1
 #include <precomp.h>
 #include <assert.h>
+#include <locale.h>
 
 #ifndef _LIBCNT_
 #include <internal/wine/msvcrt.h>
 #endif
 
 #include "wine/unicode.h"
-//#include "wine/debug.h"
 
 
-//WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
-
 #undef sprintf
 #undef wsprintf
 #undef snprintf
@@ -139,77 +138,209 @@
 }
 
 /*********************************************************************
- *		wcstod (MSVCRT.@)
+ * _wcstod_l - not exported in native msvcrt
  */
-double CDECL wcstod(const wchar_t* lpszStr, wchar_t** end)
+double CDECL _wcstod_l(const wchar_t* str, wchar_t** end,
+        _locale_t locale)
 {
-  const wchar_t* str = lpszStr;
-  int negative = 0;
-  double ret = 0, divisor = 10.0;
+    unsigned __int64 d=0, hlp;
+    int exp=0, sign=1;
+    const wchar_t *p;
+    double ret;
 
-  TRACE("(%s,%p) semi-stub\n", debugstr_w(lpszStr), end);
+    if(!str) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return 0;
+    }
 
-  /* FIXME:
-   * - Should set errno on failure
-   * - Should fail on overflow
-   * - Need to check which input formats are allowed
-   */
-  while (isspaceW(*str))
-    str++;
+    if(!locale)
+        locale = get_locale();
 
-  if (*str == '-')
-  {
-    negative = 1;
-    str++;
-  }
+    p = str;
+    while(isspaceW(*p))
+        p++;
 
-  while (isdigitW(*str))
-  {
-    ret = ret * 10.0 + (*str - '0');
-    str++;
-  }
-  if (*str == '.')
-    str++;
-  while (isdigitW(*str))
-  {
-    ret = ret + (*str - '0') / divisor;
-    divisor *= 10;
-    str++;
-  }
+    if(*p == '-') {
+        sign = -1;
+        p++;
+    } else  if(*p == '+')
+        p++;
 
-  if (*str == 'E' || *str == 'e' || *str == 'D' || *str == 'd')
-  {
-    int negativeExponent = 0;
-    int exponent = 0;
-    if (*(++str) == '-')
-    {
-      negativeExponent = 1;
-      str++;
+    while(isdigitW(*p)) {
+        hlp = d*10+*(p++)-'0';
+        if(d>UINT64_MAX/10 || hlp<d) {
+            exp++;
+            break;
+        } else
+            d = hlp;
     }
-    while (isdigitW(*str))
-    {
-      exponent = exponent * 10 + (*str - '0');
-      str++;
+    while(isdigitW(*p)) {
+        exp++;
+        p++;
     }
-    if (exponent != 0)
-    {
-      if (negativeExponent)
-        ret = ret / pow(10.0, exponent);
-      else
-        ret = ret * pow(10.0, exponent);
+    if(*p == *locale->locinfo->lconv->decimal_point)
+        p++;
+
+    while(isdigitW(*p)) {
+        hlp = d*10+*(p++)-'0';
+        if(d>UINT64_MAX/10 || hlp<d)
+            break;
+
+        d = hlp;
+        exp--;
     }
-  }
+    while(isdigitW(*p))
+        p++;
 
-  if (negative)
-    ret = -ret;
+    if(p == str) {
+        if(end)
+            *end = (wchar_t*)str;
+        return 0.0;
+    }
 
-  if (end)
-    *end = (wchar_t*)str;
+    if(*p=='e' || *p=='E' || *p=='d' || *p=='D') {
+        int e=0, s=1;
 
-  TRACE("returning %g\n", ret);
-  return ret;
+        p++;
+        if(*p == '-') {
+            s = -1;
+            p++;
+        } else if(*p == '+')
+            p++;
+
+        if(isdigitW(*p)) {
+            while(isdigitW(*p)) {
+                if(e>INT_MAX/10 || (e=e*10+*p-'0')<0)
+                    e = INT_MAX;
+                p++;
+            }
+            e *= s;
+
+            if(exp<0 && e<0 && exp+e>=0) exp = INT_MIN;
+            else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
+            else exp += e;
+        } else {
+            if(*p=='-' || *p=='+')
+                p--;
+            p--;
+        }
+    }
+
+    if(exp>0)
+        ret = (double)sign*d*pow(10, exp);
+    else
+        ret = (double)sign*d/pow(10, -exp);
+
+    if((d && ret==0.0) || isinf(ret))
+        *_errno() = ERANGE;
+
+    if(end)
+        *end = (wchar_t*)p;
+
+    return ret;
 }
 
+/*********************************************************************
+ *		_wcstombs_s_l (MSVCRT.@)
+ */
+int CDECL _wcstombs_s_l(size_t *ret, char *mbstr,
+        size_t size, const wchar_t *wcstr,
+        size_t count, _locale_t locale)
+{
+    char default_char = '\0', *p;
+    int hlp, len;
+
+    if(!size)
+        return 0;
+
+    if(!mbstr || !wcstr) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        if(mbstr)
+            *mbstr = '\0';
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+
+    if(!locale)
+        locale = get_locale();
+
+    if(size<=count)
+        len = size;
+    else if(count==_TRUNCATE)
+        len = size-1;
+    else
+        len = count;
+
+    p = mbstr;
+    *ret = 0;
+    while(1) {
+        if(!len)
+            break;
+
+        if(*wcstr == '\0') {
+            *p = '\0';
+            break;
+        }
+
+        hlp = WideCharToMultiByte(locale->locinfo->lc_codepage,
+                WC_NO_BEST_FIT_CHARS, wcstr, 1, p, len, &default_char, NULL);
+        if(!hlp || *p=='\0')
+            break;
+
+        p += hlp;
+        len -= hlp;
+
+        wcstr++;
+        *ret += 1;
+    }
+
+    if(!len && size<=count) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *mbstr = '\0';
+        *_errno() = ERANGE;
+        return ERANGE;
+    }
+
+    if(*wcstr == '\0')
+        *ret += 1;
+    *p = '\0';
+    return 0;
+}
+
+/*********************************************************************
+ *		wcstombs_s (MSVCRT.@)
+ */
+int CDECL wcstombs_s(size_t *ret, char *mbstr,
+        size_t size, const MSVCRT_wchar_t *wcstr, size_t count)
+{
+    return _wcstombs_s_l(ret, mbstr, size, wcstr, count, NULL);
+}
+
+/*********************************************************************
+ *		wcstod (MSVCRT.@)
+ */
+double CDECL wcstod(const wchar_t* lpszStr, wchar_t** end)
+{
+    return _wcstod_l(lpszStr, end, NULL);
+}
+
+/*********************************************************************
+ *		_wtof (MSVCRT.@)
+ */
+double CDECL _wtof(const wchar_t *str)
+{
+    return _wcstod_l(str, NULL, NULL);
+}
+
+/*********************************************************************
+ *		_wtof_l (MSVCRT.@)
+ */
+double CDECL _wtof_l(const wchar_t *str, _locale_t locale)
+{
+    return _wcstod_l(str, NULL, locale);
+}
+
 typedef struct pf_output_t
 {
     int used;
@@ -247,11 +378,11 @@
 
         if( space >= len )
         {
-            memcpy( p, str, len*sizeof(WCHAR) );
+            if (out->buf.W) memcpy( p, str, len*sizeof(WCHAR) );
             out->used += len;
             return len;
         }
-        if( space > 0 )
+        if( space > 0 && out->buf.W )
             memcpy( p, str, space*sizeof(WCHAR) );
         out->used += len;
     }
@@ -262,11 +393,11 @@
 
         if( space >= n )
         {
-            WideCharToMultiByte( CP_ACP, 0, str, len, p, n, NULL, NULL );
+            if (out->buf.A) WideCharToMultiByte( CP_ACP, 0, str, len, p, n, NULL, NULL );
             out->used += n;
             return len;
         }
-        if( space > 0 )
+        if( space > 0 && out->buf.A )
             WideCharToMultiByte( CP_ACP, 0, str, len, p, space, NULL, NULL );
         out->used += n;
     }
@@ -285,11 +416,11 @@
 
         if( space >= len )
         {
-            memcpy( p, str, len );
+            if (out->buf.A) memcpy( p, str, len );
             out->used += len;
             return len;
         }
-        if( space > 0 )
+        if( space > 0 && out->buf.A )
             memcpy( p, str, space );
         out->used += len;
     }
@@ -300,11 +431,11 @@
 
         if( space >= n )
         {
-            MultiByteToWideChar( CP_ACP, 0, str, len, p, n );
+            if (out->buf.W) MultiByteToWideChar( CP_ACP, 0, str, len, p, n );
             out->used += n;
             return len;
         }
-        if( space > 0 )
+        if( space > 0 && out->buf.W )
             MultiByteToWideChar( CP_ACP, 0, str, len, p, space );
         out->used += n;
     }
@@ -459,7 +590,7 @@
 
 /* pf_integer_conv:  prints x to buf, including alternate formats and
    additional precision digits, but not field characters or the sign */
-static void pf_integer_conv( char *buf, unsigned int buf_len, pf_flags *flags,
+static void pf_integer_conv( char *buf, int buf_len, pf_flags *flags,
                              LONGLONG x )
 {
     unsigned int base;
@@ -528,17 +659,60 @@
     return;
 }
 
+/* pf_fixup_exponent: convert a string containing a 2 digit exponent
+   to 3 digits, accounting for padding, in place. Needed to match
+   the native printf's which always use 3 digits. */
+static void pf_fixup_exponent( char *buf )
+{
+    char* tmp = buf;
+
+    while (tmp[0] && toupper(tmp[0]) != 'E')
+        tmp++;
+
+    if (tmp[0] && (tmp[1] == '+' || tmp[1] == '-') &&
+        isdigit(tmp[2]) && isdigit(tmp[3]))
+    {
+        char final;
+
+        if (isdigit(tmp[4]))
+            return; /* Exponent already 3 digits */
+
+        /* We have a 2 digit exponent. Prepend '0' to make it 3 */
+        tmp += 2;
+        final = tmp[2];
+        tmp[2] = tmp[1];
+        tmp[1] = tmp[0];
+        tmp[0] = '0';
+        if (final == '\0')
+        {
+            /* We didn't expand into trailing space, so this string isn't left
+             * justified. Terminate the string and strip a ' ' at the start of
+             * the string if there is one (as there may be if the string is
+             * right justified).
+             */
+            tmp[3] = '\0';
+            if (buf[0] == ' ')
+                memmove(buf, buf + 1, (tmp - buf) + 3);
+        }
+        /* Otherwise, we expanded into trailing space -> nothing to do */
+    }
+}
+
 /*********************************************************************
  *  pf_vsnprintf  (INTERNAL)
  *
  *  implements both A and W vsnprintf functions
  */
-static int pf_vsnprintf( pf_output *out, const WCHAR *format, va_list valist )
+static int pf_vsnprintf( pf_output *out, const WCHAR *format,
+        _locale_t locale, BOOL valid, va_list valist )
 {
     int r;
     LPCWSTR q, p = format;
     pf_flags flags;
 
+    if(!locale)
+        locale = get_locale();
+
     TRACE("format is %s\n",debugstr_w(format));
     while (*p)
     {
@@ -665,6 +839,11 @@
         flags.Format = *p;
         r = 0;
 
+        if (flags.Format == '$')
+        {
+            FIXME("Positional parameters are not supported (%s)\n", wine_dbgstr_w(format));
+            return -1;
+        }
         /* output a string */
         if(  flags.Format == 's' || flags.Format == 'S' )
             r = pf_handle_string_format( out, va_arg(valist, const void*), -1,
@@ -681,13 +860,14 @@
         /* output a pointer */
         else if( flags.Format == 'p' )
         {
-            char pointer[11];
+            char pointer[32];
+            void *ptr = va_arg( valist, void * );
 
             flags.PadZero = 0;
             if( flags.Alternate )
-                lnx_sprintf(pointer, "0X%08lX", va_arg(valist, long));
+                lnx_sprintf(pointer, "0X%0*lX", 2 * (int)sizeof(ptr), (ULONG_PTR)ptr);
             else
-                lnx_sprintf(pointer, "%08lX", va_arg(valist, long));
+                lnx_sprintf(pointer, "%0*lX", 2 * (int)sizeof(ptr), (ULONG_PTR)ptr);
             r = pf_output_format_A( out, pointer, -1, &flags );
         }
 
@@ -708,8 +888,8 @@
                * Includes extra bytes: 1 byte for null, 1 byte for sign,
                  4 bytes for exponent, 2 bytes for alternate formats, 1 byte 
                  for a decimal, and 1 byte for an additional float digit. */
-            unsigned x_len = ((flags.FieldLength > flags.Precision) ? 
-                              flags.FieldLength : flags.Precision) + 10;
+            int x_len = ((flags.FieldLength > flags.Precision) ? 
+                        flags.FieldLength : flags.Precision) + 10;
 
             if( x_len >= sizeof number)
                 x = HeapAlloc( GetProcessHeap(), 0, x_len );
@@ -724,15 +904,15 @@
         /* deal with integers and floats using libc's printf */
         else if( pf_is_valid_format( flags.Format ) )
         {
-            char fmt[20], number[40], *x = number;
+            char fmt[20], number[40], *x = number, *decimal_point;
 
             /* Estimate largest possible required buffer size:
                * Chooses the larger of the field or precision
                * Includes extra bytes: 1 byte for null, 1 byte for sign,
                  4 bytes for exponent, 2 bytes for alternate formats, 1 byte 
                  for a decimal, and 1 byte for an additional float digit. */
-            unsigned x_len = ((flags.FieldLength > flags.Precision) ? 
-                              flags.FieldLength : flags.Precision) + 10;
+            int x_len = ((flags.FieldLength > flags.Precision) ? 
+                        flags.FieldLength : flags.Precision) + 10;
 
             if( x_len >= sizeof number)
                 x = HeapAlloc( GetProcessHeap(), 0, x_len );
@@ -740,16 +920,35 @@
             pf_rebuild_format_string( fmt, &flags );
 
             if( pf_is_double_format( flags.Format ) )
+            {
                 lnx_sprintf( x, fmt, va_arg(valist, double) );
+                if (toupper(flags.Format) == 'E' || toupper(flags.Format) == 'G')
+                    pf_fixup_exponent( x );
+            }
             else
                 lnx_sprintf( x, fmt, va_arg(valist, int) );
 
+            decimal_point = strchr(x, '.');
+            if(decimal_point)
+                *decimal_point = *locale->locinfo->lconv->decimal_point;
+
             r = pf_output_stringA( out, x, -1 );
             if( x != number )
                 HeapFree( GetProcessHeap(), 0, x );
+            if(r < 0)
+                return r;
         }
         else
+        {
+            if( valid )
+            {
+                _invalid_parameter( NULL, NULL, NULL, 0, 0 );
+                *_errno() = EINVAL;
+                return -1;
+            }
+
             continue;
+        }
 
         if( r<0 )
             return r;
@@ -764,10 +963,10 @@
 }
 
 /*********************************************************************
- *		_vsnprintf (MSVCRT.@)
+ * vsnprintf_internal (INTERNAL)
  */
-int CDECL _vsnprintf( char *str, size_t len,
-                            const char *format, va_list valist )
+static inline int vsnprintf_internal( char *str, size_t len, const char *format,
+        _locale_t locale, BOOL valid, __ms_va_list valist )
 {
     DWORD sz;
     LPWSTR formatW = NULL;
@@ -779,14 +978,11 @@
     out.used = 0;
     out.len = len;
 
-    if( format )
-    {
-        sz = MultiByteToWideChar( CP_ACP, 0, format, -1, NULL, 0 );
-        formatW = HeapAlloc( GetProcessHeap(), 0, sz*sizeof(WCHAR) );
-        MultiByteToWideChar( CP_ACP, 0, format, -1, formatW, sz );
-    }
+    sz = MultiByteToWideChar( CP_ACP, 0, format, -1, NULL, 0 );
+    formatW = HeapAlloc( GetProcessHeap(), 0, sz*sizeof(WCHAR) );
+    MultiByteToWideChar( CP_ACP, 0, format, -1, formatW, sz );
 
-    r = pf_vsnprintf( &out, formatW, valist );
+    r = pf_vsnprintf( &out, formatW, locale, valid, valist );
 
     HeapFree( GetProcessHeap(), 0, formatW );
 
@@ -794,6 +990,63 @@
 }
 
 /*********************************************************************
+ *              _vsnprintf (MSVCRT.@)
+ */
+int CDECL _vsnprintf( char *str, size_t len,
+                            const char *format, va_list valist )
+{
+    return vsnprintf_internal(str, len, format, NULL, FALSE, valist);
+}
+
+/*********************************************************************
+*		_vsnprintf_l (MSVCRT.@)
+ */
+int CDECL _vsnprintf_l( char *str, size_t len, const char *format,
+                            _locale_t locale, va_list valist )
+{
+    return vsnprintf_internal(str, len, format, locale, FALSE, valist);
+}
+
+/*********************************************************************
+ *		_vsnprintf_s_l (MSVCRT.@)
+ */
+int CDECL _vsnprintf_s_l( char *str, size_t sizeOfBuffer,
+        size_t count, const char *format,
+        _locale_t locale, va_list valist )
+{
+    int len, ret;
+
+    if(sizeOfBuffer<count+1 || count==-1)
+        len = sizeOfBuffer;
+    else
+        len = count+1;
+
+    ret = vsnprintf_internal(str, len, format, locale, TRUE, valist);
+
+    if(ret<0 || ret==len) {
+        if(count!=_TRUNCATE && count>sizeOfBuffer) {
+            _invalid_parameter( NULL, NULL, NULL, 0, 0 );
+            *_errno() = ERANGE;
+            memset(str, 0, sizeOfBuffer);
+        } else
+            str[len-1] = '\0';
+
+        return -1;
+    }
+
+    return ret;
+}
+
+/*********************************************************************
+ *              _vsnprintf_s (MSVCRT.@)
+ */
+int CDECL _vsnprintf_s( char *str, size_t sizeOfBuffer,
+        size_t count, const char *format, va_list valist )
+{
+    return _vsnprintf_s_l(str,sizeOfBuffer, count, format, NULL, valist);
+}
+
+/*********************************************************************
  *		vsprintf (MSVCRT.@)
  */
 int CDECL vsprintf( char *str, const char *format, va_list valist)
@@ -802,6 +1055,22 @@
 }
 
 /*********************************************************************
+ *		vsprintf_s (MSVCRT.@)
+ */
+int CDECL vsprintf_s( char *str, size_t num, const char *format, va_list valist)
+{
+    return _vsnprintf(str, num, format, valist);
+}
+
+/*********************************************************************
+ *		_vscprintf (MSVCRT.@)
+ */
+int CDECL _vscprintf( const char *format, va_list valist )
+{
+    return _vsnprintf( NULL, INT_MAX, format, valist );
+}
+
+/*********************************************************************
  *		_snprintf (MSVCRT.@)
  */
 int CDECL _snprintf(char *str, size_t len, const char *format, ...)
@@ -815,10 +1084,11 @@
 }
 
 /*********************************************************************
- *		_vsnwsprintf (MSVCRT.@)
+ * vsnwsprintf_internal (INTERNAL)
  */
-int CDECL _vsnwprintf( wchar_t *str, size_t len,
-                             const wchar_t *format, va_list valist )
+static inline int vsnwprintf_internal(wchar_t *str, size_t len,
+        const wchar_t *format, _locale_t locale, BOOL valid,
+        va_list valist)
 {
     pf_output out;
 
@@ -827,10 +1097,68 @@
     out.used = 0;
     out.len = len;
 
-    return pf_vsnprintf( &out, format, valist );
+    return pf_vsnprintf( &out, format, locale, valid, valist );
 }
 
 /*********************************************************************
+ *              _vsnwsprintf (MSVCRT.@)
+ */
+int CDECL _vsnwprintf(wchar_t *str, size_t len,
+        const wchar_t *format, va_list valist)
+{
+    return vsnwprintf_internal(str, len, format, NULL, FALSE, valist);
+}
+
+/*********************************************************************
+ *              _vsnwsprintf_l (MSVCRT.@)
+ */
+int CDECL _vsnwprintf_l(wchar_t *str, size_t len,
+        const wchar_t *format, _locale_t locale,
+        va_list valist)
+{
+        return vsnwprintf_internal(str, len, format, locale, FALSE, valist);
+}
+
+/*********************************************************************
+ *              _vsnwsprintf_s_l (MSVCRT.@)
+ */
+int CDECL _vsnwprintf_s_l( wchar_t *str, size_t sizeOfBuffer,
+        size_t count, const wchar_t *format,
+        _locale_t locale, va_list valist)
+{
+    int len, ret;
+
+    len = sizeOfBuffer/sizeof(wchar_t);
+    if(count!=-1 && len>count+1)
+        len = count+1;
+
+    ret = vsnwprintf_internal(str, len, format, locale, TRUE, valist);
+
+    if(ret<0 || ret==len) {
+        if(count!=_TRUNCATE && count>sizeOfBuffer/sizeof(wchar_t)) {
+            _invalid_parameter( NULL, NULL, NULL, 0, 0 );
+            *_errno() = ERANGE;
+            memset(str, 0, sizeOfBuffer);
+        } else
+            str[len-1] = '\0';
+
+        return -1;
+    }
+
+    return ret;
+}
+
+/*********************************************************************
+ *              _vsnwsprintf_s (MSVCRT.@)
+ */
+int CDECL _vsnwprintf_s(wchar_t *str, size_t sizeOfBuffer,
+        size_t count, const wchar_t *format, va_list valist)
+{
+    return _vsnwprintf_s_l(str, sizeOfBuffer, count,
+            format, NULL, valist);
+}
+
+/*********************************************************************
  *		_snwprintf (MSVCRT.@)
  */
 int CDECL _snwprintf( wchar_t *str, size_t len, const wchar_t *format, ...)
@@ -858,6 +1186,20 @@
 }
 
 /*********************************************************************
+ *		sprintf_s (MSVCRT.@)
+ */
+int CDECL sprintf_s( char *str, size_t num, const char *format, ... )
+{
+    va_list ap;
+    int r;
+
+    va_start( ap, format );
+    r = _vsnprintf( str, num, format, ap );
+    va_end( ap );
+    return r;
+}
+
+/*********************************************************************
  *		swprintf (MSVCRT.@)
  */
 int CDECL swprintf( wchar_t *str, const wchar_t *format, ... )
@@ -872,15 +1214,59 @@
 }
 
 /*********************************************************************
+ *		swprintf_s (MSVCRT.@)
+ */
+int CDECL swprintf_s(wchar_t *str, size_t numberOfElements,
+        const wchar_t *format, ... )
+{
+    va_list ap;
+    int r;
+
+    va_start(ap, format);
+    r = _vsnwprintf_s(str, numberOfElements*sizeof(wchar_t),
+            INT_MAX, format, ap);
+    va_end(ap);
+
+    return r;
+}
+
+/*********************************************************************
  *		vswprintf (MSVCRT.@)
  */
 int CDECL vswprintf( wchar_t* str, const wchar_t* format, va_list args )
 {
     return _vsnwprintf( str, INT_MAX, format, args );
 }
-#endif
 
 /*********************************************************************
+ *		_vscwprintf (MSVCRT.@)
+ */
+int CDECL _vscwprintf( const wchar_t *format, va_list args )
+{
+    return _vsnwprintf( NULL, INT_MAX, format, args );
+}
+
+/*********************************************************************
+ *		vswprintf_s (MSVCRT.@)
+ */
+int CDECL vswprintf_s(wchar_t* str, size_t numberOfElements,
+        const wchar_t* format,va_list args)
+{
+    return _vsnwprintf_s(str, numberOfElements*sizeof(wchar_t),
+            INT_MAX, format, args);
+}
+
+/*********************************************************************
+ *              _vswprintf_s_l (MSVCRT.@)
+ */
+int CDECL _vswprintf_s_l(wchar_t* str, size_t numberOfElements,
+        const wchar_t* format, _locale_t locale, va_list args)
+{
+    return _vsnwprintf_s_l(str, numberOfElements*sizeof(wchar_t),
+            INT_MAX, format, locale, args );
+}
+#endif
+/*********************************************************************
  *		wcscoll (MSVCRT.@)
  */
 int CDECL wcscoll( const wchar_t* str1, const wchar_t* str2 )
@@ -927,222 +1313,18 @@
 /*********************************************************************
  *		wctomb (MSVCRT.@)
  */
-INT CDECL wctomb(char *mbchar, wchar_t wchar)
+INT CDECL wctomb( char *dst, wchar_t ch )
 {
-    BOOL bUsedDefaultChar;
-    char chMultiByte[MB_LEN_MAX];
-    int nBytes;
-
-    /* At least one parameter needs to be given, the length of a null character cannot be queried (verified by tests under WinXP SP2) */
-    if(!mbchar && !wchar)
-        return 0;
-
-    /* Use WideCharToMultiByte for doing the conversion using the codepage currently set with setlocale() */
-    nBytes = WideCharToMultiByte(MSVCRT___lc_codepage, 0, &wchar, 1, chMultiByte, MB_LEN_MAX, NULL, &bUsedDefaultChar);
-
-    /* Only copy the character if an 'mbchar' pointer was given.
-
-       The "C" locale is emulated with codepage 1252 here. This codepage has a default character "?", but the "C" locale doesn't have one.
-       Therefore don't copy the character in this case. */
-    if(mbchar && !(MSVCRT_current_lc_all[0] == 'C' && !MSVCRT_current_lc_all[1] && bUsedDefaultChar))
-        memcpy(mbchar, chMultiByte, nBytes);
-
-    /* If the default character was used, set errno to EILSEQ and return -1. */
-    if(bUsedDefaultChar)
-    {
-        __set_errno(EILSEQ);
-        return -1;
-    }
-
-    /* Otherwise return the number of bytes this character occupies. */
-    return nBytes;
+  return WideCharToMultiByte( CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL );
 }
 
-size_t CDECL wcstombs(char *mbstr, const wchar_t *wcstr, size_t count)
-{
-    BOOL bUsedDefaultChar;
-    char* p = mbstr;
-    int nResult;
-
-    /* Does the caller query for output buffer size? */
-    if(!mbstr)
-    {
-        int nLength;
-
-        /* If we currently use the "C" locale, the length of the input string is returned (verified by tests under WinXP SP2) */
-        if(MSVCRT_current_lc_all[0] == 'C' && !MSVCRT_current_lc_all[1])
-            return wcslen(wcstr);
-
-        /* Otherwise check the length each character needs and build a final return value out of this */
-        count = wcslen(wcstr);
-        nLength = 0;
-
-        while((int)(--count) >= 0 && *wcstr)
-        {
-            /* Get the length of this character */
-            nResult = wctomb(NULL, *wcstr++);
-
-            /* If this character is not convertible in the current locale, the end result will be -1 */
-            if(nResult == -1)
-                return -1;
-
-            nLength += nResult;
-        }
-
-        /* Return the final length */
-        return nLength;
-    }
-
-    /* Convert the string then */
-    bUsedDefaultChar = FALSE;
-
-    for(;;)
-    {
-        char chMultiByte[MB_LEN_MAX];
-        UINT uLength;
-
-        /* Are we at the terminating null character? */
-        if(!*wcstr)
-        {
-            /* Set the null character, but don't increment the pointer as the returned length never includes the terminating null character */
-            *p = 0;
-            break;
-        }
-
-        /* Convert this character into the temporary chMultiByte variable */
-        ZeroMemory(chMultiByte, MB_LEN_MAX);
-        nResult = wctomb(chMultiByte, *wcstr++);
-
-        /* Check if this was an invalid character */
-        if(nResult == -1)
-            bUsedDefaultChar = TRUE;
-
-        /* If we got no character, stop the conversion process here */
-        if(!chMultiByte[0])
-            break;
-
-        /* Determine whether this is a double-byte or a single-byte character */
-        if(chMultiByte[1])
-            uLength = 2;
-        else
-            uLength = 1;
-
-        /* Decrease 'count' by the character length and check if the buffer can still hold the full character */
-        count -= uLength;
-
-        if((int)count < 0)
-            break;
-
-        /* It can, so copy it and move the pointer forward */
-        memcpy(p, chMultiByte, uLength);
-        p += uLength;
-    }
-
-    if(bUsedDefaultChar)
-        return -1;
-
-    /* Return the length in bytes of the copied characters (without the terminating null character) */
-    return p - mbstr;
-}
 #endif
-
-#ifndef __REACTOS__
 /*********************************************************************
- *		iswalnum (MSVCRT.@)
- */
-INT CDECL iswalnum( wchar_t wc )
-{
-    return isalnumW( wc );
-}
-
-/*********************************************************************
- *		iswalpha (MSVCRT.@)
- */
-INT CDECL iswalpha( wchar_t wc )
-{
-    return isalphaW( wc );
-}
-
-/*********************************************************************
- *		iswcntrl (MSVCRT.@)
- */
-INT CDECL iswcntrl( wchar_t wc )
-{
-    return iscntrlW( wc );
-}
-
-/*********************************************************************
- *		iswdigit (MSVCRT.@)
- */
-INT CDECL iswdigit( wchar_t wc )
-{
-    return isdigitW( wc );
-}
-
-/*********************************************************************
- *		iswgraph (MSVCRT.@)
- */
-INT CDECL iswgraph( wchar_t wc )
-{
-    return isgraphW( wc );
-}
-
-/*********************************************************************
- *		iswlower (MSVCRT.@)
- */
-INT CDECL iswlower( wchar_t wc )
-{
-    return islowerW( wc );
-}
-
-/*********************************************************************
- *		iswprint (MSVCRT.@)
- */
-INT CDECL iswprint( wchar_t wc )
-{
-    return isprintW( wc );
-}
-
-/*********************************************************************
- *		iswpunct (MSVCRT.@)
- */
-INT CDECL iswpunct( wchar_t wc )
-{
-    return ispunctW( wc );
-}
-
-/*********************************************************************
- *		iswspace (MSVCRT.@)
- */
-INT CDECL iswspace( wchar_t wc )
-{
-    return isspaceW( wc );
-}
-
-/*********************************************************************
- *		iswupper (MSVCRT.@)
- */
-INT CDECL iswupper( wchar_t wc )
-{
-    return isupperW( wc );
-}
-
-/*********************************************************************
- *		iswxdigit (MSVCRT.@)
- */
-INT CDECL iswxdigit( wchar_t wc )
-{
-    return isxdigitW( wc );
-}
-
-#endif
-
-/*********************************************************************
  *		wcscpy_s (MSVCRT.@)
  */
 INT CDECL wcscpy_s( wchar_t* wcDest, size_t numElement, const  wchar_t *wcSrc)
 {
-    INT size = 0;
+    size_t size = 0;
 
     if(!wcDest || !numElement)
         return EINVAL;
@@ -1197,4 +1379,170 @@
     return 0;
 }
 
+/******************************************************************
+ *		wcscat_s (MSVCRT.@)
+ *
+ */
+INT CDECL wcscat_s(wchar_t* dst, size_t elem, const wchar_t* src)
+{
+    wchar_t* ptr = dst;
 
+    if (!dst || elem == 0) return EINVAL;
+    if (!src)
+    {
+        dst[0] = '\0';
+        return EINVAL;
+    }
+
+    /* seek to end of dst string (or elem if no end of string is found */
+    while (ptr < dst + elem && *ptr != '\0') ptr++;
+    while (ptr < dst + elem)
+    {
+        if ((*ptr++ = *src++) == '\0') return 0;
+    }
+    /* not enough space */
+    dst[0] = '\0';
+    return ERANGE;
+}
+
+#ifndef _LIBCNT_
+/*********************************************************************
+ *  _wctoi64_l (MSVCRT.@)
+ *
+ * FIXME: locale parameter is ignored
+ */
+__int64 CDECL _wcstoi64_l(const wchar_t *nptr,
+        wchar_t **endptr, int base, _locale_t locale)
+{
+    BOOL negative = FALSE;
+    __int64 ret = 0;
+
+    TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
+
+    if(!nptr || base<0 || base>36 || base==1) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        return 0;
+    }
+
+    while(isspaceW(*nptr)) nptr++;
+
+    if(*nptr == '-') {
+        negative = TRUE;
+        nptr++;
+    } else if(*nptr == '+')
+        nptr++;
+
+    if((base==0 || base==16) && *nptr=='0' && tolowerW(*(nptr+1))=='x') {
+        base = 16;
+        nptr += 2;
+    }
+
+    if(base == 0) {
+        if(*nptr=='0')
+            base = 8;
+        else
+            base = 10;
+    }
+
+    while(*nptr) {
+        char cur = tolowerW(*nptr);
+        int v;
+
+        if(isdigitW(cur)) {
+            if(cur >= '0'+base)
+                break;
+            v = cur-'0';
+        } else {
+            if(cur<'a' || cur>='a'+base-10)
+                break;
+            v = cur-'a'+10;
+        }
+
+        if(negative)
+            v = -v;
+
+        nptr++;
+
+        if(!negative && (ret>INT64_MAX/base || ret*base>INT64_MAX-v)) {
+            ret = INT64_MAX;
+            *_errno() = ERANGE;
+        } else if(negative && (ret<INT64_MIN/base || ret*base<INT64_MIN-v)) {
+            ret = INT64_MIN;
+            *_errno() = ERANGE;
+        } else
+            ret = ret*base + v;
+    }
+
+    if(endptr)
+        *endptr = (wchar_t*)nptr;
+
+    return ret;
+}
+
+/*********************************************************************
+ *  _wcstoui64_l (MSVCRT.@)
+ *
+ * FIXME: locale parameter is ignored
+ */
+unsigned __int64 CDECL _wcstoui64_l(const wchar_t *nptr,
+        wchar_t **endptr, int base, _locale_t locale)
+{
+    BOOL negative = FALSE;
+    unsigned __int64 ret = 0;
+
+    TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
+
+    if(!nptr || base<0 || base>36 || base==1) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        return 0;
+    }
+
+    while(isspaceW(*nptr)) nptr++;
+
+    if(*nptr == '-') {
+        negative = TRUE;
+        nptr++;
+    } else if(*nptr == '+')
+        nptr++;
+
+    if((base==0 || base==16) && *nptr=='0' && tolowerW(*(nptr+1))=='x') {
+        base = 16;
+        nptr += 2;
+    }
+
+    if(base == 0) {
+        if(*nptr=='0')
+            base = 8;
+        else
+            base = 10;
+    }
+
+    while(*nptr) {
+        char cur = tolowerW(*nptr);
+        int v;
+
+        if(isdigit(cur)) {
+            if(cur >= '0'+base)
+                break;
+            v = *nptr-'0';
+        } else {
+            if(cur<'a' || cur>='a'+base-10)
+                break;
+            v = cur-'a'+10;
+        }
+
+        nptr++;
+
+        if(ret>UINT64_MAX/base || ret*base>UINT64_MAX-v) {
+            ret = UINT64_MAX;
+            *_errno() = ERANGE;
+        } else
+            ret = ret*base + v;
+    }
+
+    if(endptr)
+        *endptr = (wchar_t*)nptr;
+
+    return negative ? -ret : ret;
+}
+#endif
Index: crt/string/wsplitp.c
===================================================================
--- crt/string/wsplitp.c	(revision 47065)
+++ crt/string/wsplitp.c	(working copy)
@@ -5,3 +5,81 @@
 #include <tchar.h>
 
 #include "splitp.c"
+
+/******************************************************************
+ *		_wsplitpath_s (MSVCRT.@)
+ *
+ * Secure version of _wsplitpath
+ */
+int _wsplitpath_s(const wchar_t* inpath,
+                  wchar_t* drive, size_t sz_drive,
+                  wchar_t* dir, size_t sz_dir,
+                  wchar_t* fname, size_t sz_fname,
+                  wchar_t* ext, size_t sz_ext)
+{
+    const wchar_t *p, *end;
+
+    if (!inpath) return EINVAL;
+    if (!drive && sz_drive) return EINVAL;
+    if (drive && !sz_drive) return EINVAL;
+    if (!dir && sz_dir) return EINVAL;
+    if (dir && !sz_dir) return EINVAL;
+    if (!fname && sz_fname) return EINVAL;
+    if (fname && !sz_fname) return EINVAL;
+    if (!ext && sz_ext) return EINVAL;
+    if (ext && !sz_ext) return EINVAL;
+
+    if (inpath[0] && inpath[1] == ':')
+    {
+        if (drive)
+        {
+            if (sz_drive <= 2) goto do_error;
+            drive[0] = inpath[0];
+            drive[1] = inpath[1];
+            drive[2] = 0;
+        }
+        inpath += 2;
+    }
+    else if (drive) drive[0] = '\0';
+
+    /* look for end of directory part */
+    end = NULL;
+    for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
+
+    if (end)  /* got a directory */
+    {
+        if (dir)
+        {
+            if (sz_dir <= end - inpath) goto do_error;
+            memcpy( dir, inpath, (end - inpath) * sizeof(wchar_t) );
+            dir[end - inpath] = 0;
+        }
+        inpath = end;
+    }
+    else if (dir) dir[0] = 0;
+
+    /* look for extension: what's after the last dot */
+    end = NULL;
+    for (p = inpath; *p; p++) if (*p == '.') end = p;
+
+    if (!end) end = p; /* there's no extension */
+
+    if (fname)
+    {
+        if (sz_fname <= end - inpath) goto do_error;
+        memcpy( fname, inpath, (end - inpath) * sizeof(wchar_t) );
+        fname[end - inpath] = 0;
+    }
+    if (ext)
+    {
+        if (sz_ext <= strlenW(end)) goto do_error;
+        strcpyW( ext, end );
+    }
+    return 0;
+do_error:
+    if (drive)  drive[0] = '\0';
+    if (dir)    dir[0] = '\0';
+    if (fname)  fname[0]= '\0';
+    if (ext)    ext[0]= '\0';
+    return ERANGE;
+}
Index: crt/string/wtoi64.c
===================================================================
--- crt/string/wtoi64.c	(revision 47065)
+++ crt/string/wtoi64.c	(working copy)
@@ -45,26 +45,24 @@
        return value;
 }
 
-
+#ifndef _LIBCNT_
 /*
- * @unimplemented
+ * @implemented
  */
 __int64
 _wcstoi64 (const wchar_t *nptr, wchar_t **endptr, int base)
 {
-   TRACE("_wcstoi64 is UNIMPLEMENTED\n");
-   return 0;
+    return _wcstoi64_l(nptr, endptr, base, NULL);
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 unsigned __int64
 _wcstoui64 (const wchar_t *nptr, wchar_t **endptr, int base)
 {
-   TRACE("_wcstoui64 is UNIMPLEMENTED\n");
-   return 0;
+   return _wcstoui64_l(nptr, endptr, base, NULL);
 }
+#endif
 
-
 /* EOF */
Index: crt/wine/heap.c
===================================================================
--- crt/wine/heap.c	(revision 47065)
+++ crt/wine/heap.c	(working copy)
@@ -15,13 +15,14 @@
  *
  * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Note: Win32 heap operations are MT safe. We only lock the new
  *       handler and non atomic heap operations
  */
 
 #include <precomp.h>
+#include <malloc.h>
 
 /* MT */
 #define LOCK_HEAP   _mlock( _HEAP_LOCK )
@@ -29,47 +30,60 @@
 
 /* _aligned */
 #define SAVED_PTR(x) ((void *)((DWORD_PTR)((char *)x - sizeof(void *)) & \
-                                ~(sizeof(void *) - 1)))
+                               ~(sizeof(void *) - 1)))
 #define ALIGN_PTR(ptr, alignment, offset) ((void *) \
     ((((DWORD_PTR)((char *)ptr + alignment + sizeof(void *) + offset)) & \
       ~(alignment - 1)) - offset))
 
-typedef void (*MSVCRT_new_handler_func)(unsigned long size);
+typedef void (*MSVCRT_new_handler_func)(size_t size);
 
 static MSVCRT_new_handler_func MSVCRT_new_handler;
 static int MSVCRT_new_mode;
 
+/* FIXME - According to documentation it should be 8*1024, at runtime it returns 16 */ 
+static unsigned int MSVCRT_amblksiz = 16;
 /* FIXME - According to documentation it should be 480 bytes, at runtime default is 0 */
 static size_t MSVCRT_sbh_threshold = 0;
 
 /*********************************************************************
  *		??2@YAPAXI@Z (MSVCRT.@)
  */
-void* MSVCRT_operator_new(unsigned long size)
+void* CDECL MSVCRT_operator_new(size_t size)
 {
-  void *retval = malloc(size);
+  void *retval = HeapAlloc(GetProcessHeap(), 0, size);
   TRACE("(%ld) returning %p\n", size, retval);
+  if(retval) return retval;
   LOCK_HEAP;
-  if(!retval && MSVCRT_new_handler)
+  if(MSVCRT_new_handler)
     (*MSVCRT_new_handler)(size);
   UNLOCK_HEAP;
   return retval;
 }
 
+
 /*********************************************************************
+ *		??2@YAPAXIHPBDH@Z (MSVCRT.@)
+ */
+void* CDECL MSVCRT_operator_new_dbg(size_t size, int type, const char *file, int line)
+{
+    return MSVCRT_operator_new( size );
+}
+
+
+/*********************************************************************
  *		??3@YAXPAX@Z (MSVCRT.@)
  */
-void MSVCRT_operator_delete(void *mem)
+void CDECL MSVCRT_operator_delete(void *mem)
 {
   TRACE("(%p)\n", mem);
-  free(mem);
+  HeapFree(GetProcessHeap(), 0, mem);
 }
 
 
 /*********************************************************************
  *		?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@)
  */
-MSVCRT_new_handler_func MSVCRT__query_new_handler(void)
+MSVCRT_new_handler_func CDECL MSVCRT__query_new_handler(void)
 {
   return MSVCRT_new_handler;
 }
@@ -78,7 +92,7 @@
 /*********************************************************************
  *		?_query_new_mode@@YAHXZ (MSVCRT.@)
  */
-int MSVCRT__query_new_mode(void)
+int CDECL MSVCRT__query_new_mode(void)
 {
   return MSVCRT_new_mode;
 }
@@ -86,7 +100,7 @@
 /*********************************************************************
  *		?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@)
  */
-MSVCRT_new_handler_func MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
+MSVCRT_new_handler_func CDECL MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
 {
   MSVCRT_new_handler_func old_handler;
   LOCK_HEAP;
@@ -99,7 +113,7 @@
 /*********************************************************************
  *		?set_new_handler@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
  */
-MSVCRT_new_handler_func MSVCRT_set_new_handler(void *func)
+MSVCRT_new_handler_func CDECL MSVCRT_set_new_handler(void *func)
 {
   TRACE("(%p)\n",func);
   MSVCRT__set_new_handler(NULL);
@@ -109,7 +123,7 @@
 /*********************************************************************
  *		?_set_new_mode@@YAHH@Z (MSVCRT.@)
  */
-int MSVCRT__set_new_mode(int mode)
+int CDECL MSVCRT__set_new_mode(int mode)
 {
   int old_mode;
   LOCK_HEAP;
@@ -119,45 +133,216 @@
   return old_mode;
 }
 
-int CDECL _callnewh(unsigned long size)
+/*********************************************************************
+ *		_callnewh (MSVCRT.@)
+ */
+int CDECL _callnewh(size_t size)
 {
-    if(MSVCRT_new_handler)
-        (*MSVCRT_new_handler)(size);
-    return 0;
+  if(MSVCRT_new_handler)
+    (*MSVCRT_new_handler)(size);
+  return 0;
 }
 
 /*********************************************************************
- *              _get_sbh_threshold (MSVCRT.@)
+ *		_expand (MSVCRT.@)
  */
-size_t CDECL _get_sbh_threshold(void)
+void* CDECL _expand(void* mem, size_t size)
 {
-    return MSVCRT_sbh_threshold;
+  return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, mem, size);
 }
 
 /*********************************************************************
- *              _set_sbh_threshold (MSVCRT.@)
+ *		_heapchk (MSVCRT.@)
  */
-int CDECL _set_sbh_threshold(size_t threshold)
+int CDECL _heapchk(void)
 {
-    if(threshold > 1016)
-        return 0;
-    else
-        MSVCRT_sbh_threshold = threshold;
-    return 1;
+  if (!HeapValidate( GetProcessHeap(), 0, NULL))
+  {
+    __set_errno(GetLastError());
+    return _HEAPBADNODE;
+  }
+  return _HEAPOK;
 }
 
 /*********************************************************************
- *    _heapadd (MSVCRT.@)
+ *		_heapmin (MSVCRT.@)
  */
-int _heapadd(void* mem, size_t size)
+int CDECL _heapmin(void)
 {
-  TRACE("(%p,%d) unsupported in Win32\n", mem,size);
+  if (!HeapCompact( GetProcessHeap(), 0 ))
+  {
+    if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+      __set_errno(GetLastError());
+    return -1;
+  }
+  return 0;
+}
+
+/*********************************************************************
+ *		_heapwalk (MSVCRT.@)
+ */
+int CDECL _heapwalk(_HEAPINFO* next)
+{
+  PROCESS_HEAP_ENTRY phe;
+
+  LOCK_HEAP;
+  phe.lpData = next->_pentry;
+  phe.cbData = next->_size;
+  phe.wFlags = next->_useflag == _USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
+
+  if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
+      !HeapValidate( GetProcessHeap(), 0, phe.lpData ))
+  {
+    UNLOCK_HEAP;
+   __set_errno(GetLastError());
+    return _HEAPBADNODE;
+  }
+
+  do
+  {
+    if (!HeapWalk( GetProcessHeap(), &phe ))
+    {
+      UNLOCK_HEAP;
+      if (GetLastError() == ERROR_NO_MORE_ITEMS)
+         return _HEAPEND;
+      __set_errno(GetLastError());
+      if (!phe.lpData)
+        return _HEAPBADBEGIN;
+      return _HEAPBADNODE;
+    }
+  } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
+
+  UNLOCK_HEAP;
+  next->_pentry = phe.lpData;
+  next->_size = phe.cbData;
+  next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? _USEDENTRY : _FREEENTRY;
+  return _HEAPOK;
+}
+
+/*********************************************************************
+ *		_heapset (MSVCRT.@)
+ */
+int CDECL _heapset(unsigned int value)
+{
+  int retval;
+  _HEAPINFO heap;
+
+  memset( &heap, 0, sizeof(heap) );
+  LOCK_HEAP;
+  while ((retval = _heapwalk(&heap)) == _HEAPOK)
+  {
+    if (heap._useflag == _FREEENTRY)
+      memset(heap._pentry, value, heap._size);
+  }
+  UNLOCK_HEAP;
+  return retval == _HEAPEND? _HEAPOK : retval;
+}
+
+/*********************************************************************
+ *		_heapadd (MSVCRT.@)
+ */
+int CDECL _heapadd(void* mem, size_t size)
+{
+  TRACE("(%p,%ld) unsupported in Win32\n", mem,size);
   *_errno() = ENOSYS;
   return -1;
 }
 
+/*********************************************************************
+ *		_heapadd (MSVCRT.@)
+ */
+intptr_t CDECL _get_heap_handle(void)
+{
+    return (intptr_t)GetProcessHeap();
+}
+
+/*********************************************************************
+ *		_msize (MSVCRT.@)
+ */
+size_t CDECL _msize(void* mem)
+{
+  size_t size = HeapSize(GetProcessHeap(),0,mem);
+  if (size == ~(size_t)0)
+  {
+    WARN(":Probably called with non wine-allocated memory, ret = -1\n");
+    /* At least the Win32 crtdll/msvcrt also return -1 in this case */
+  }
+  return size;
+}
+
+/*********************************************************************
+ *		calloc (MSVCRT.@)
+ */
+void* CDECL calloc(size_t size,size_t count)
+{
+  return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
+}
+
+/*********************************************************************
+ *		free (MSVCRT.@)
+ */
+void CDECL free(void* ptr)
+{
+  HeapFree(GetProcessHeap(),0,ptr);
+}
+
+/*********************************************************************
+ *                  malloc (MSVCRT.@)
+ */
+void* CDECL malloc(size_t size)
+{
+  void *ret = HeapAlloc(GetProcessHeap(),0,size);
+  if (!ret)
+      *_errno() = ENOMEM;
+  return ret;
+}
+
+/*********************************************************************
+ *		realloc (MSVCRT.@)
+ */
+void* CDECL realloc(void* ptr, size_t size)
+{
+  if (!ptr) return malloc(size);
+  if (size) return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
+  free(ptr);
+  return NULL;
+}
+
+/*********************************************************************
+ *		__p__amblksiz (MSVCRT.@)
+ */
+unsigned int* CDECL __p__amblksiz(void)
+{
+  return &MSVCRT_amblksiz;
+}
+
+/*********************************************************************
+ *		_get_sbh_threshold (MSVCRT.@)
+ */
+size_t CDECL _get_sbh_threshold(void)
+{
+  return MSVCRT_sbh_threshold;
+}
+
+/*********************************************************************
+ *		_set_sbh_threshold (MSVCRT.@)
+ */
+int CDECL _set_sbh_threshold(size_t threshold)
+{
+  if(threshold > 1016)
+     return 0;
+  else
+     MSVCRT_sbh_threshold = threshold;
+  return 1;
+}
+
+/*********************************************************************
+ *		_aligned_free (MSVCRT.@)
+ */
 void CDECL _aligned_free(void *memblock)
 {
+    TRACE("(%p)\n", memblock);
+
     if (memblock)
     {
         void **saved = SAVED_PTR(memblock);
@@ -165,9 +350,13 @@
     }
 }
 
+/*********************************************************************
+ *		_aligned_offset_malloc (MSVCRT.@)
+ */
 void * CDECL _aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
 {
     void *memblock, *temp, **saved;
+    TRACE("(%lu, %lu, %lu)\n", size, alignment, offset);
 
     /* alignment must be a power of 2 */
     if ((alignment & (alignment - 1)) != 0)
@@ -204,16 +393,24 @@
     return memblock;
 }
 
+/*********************************************************************
+ *		_aligned_malloc (MSVCRT.@)
+ */
 void * CDECL _aligned_malloc(size_t size, size_t alignment)
 {
+    TRACE("(%lu, %lu)\n", size, alignment);
     return _aligned_offset_malloc(size, alignment, 0);
 }
 
+/*********************************************************************
+ *		_aligned_offset_realloc (MSVCRT.@)
+ */
 void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
                                      size_t alignment, size_t offset)
 {
     void * temp, **saved;
     size_t old_padding, new_padding, old_size;
+    TRACE("(%p, %lu, %lu, %lu)\n", memblock, size, alignment, offset);
 
     if (!memblock)
         return _aligned_offset_malloc(size, alignment, offset);
@@ -244,7 +441,6 @@
 
     /* make sure alignment and offset didn't change */
     saved = SAVED_PTR(memblock);
-
     if (memblock != ALIGN_PTR(*saved, alignment, offset))
     {
         *_errno() = EINVAL;
@@ -255,7 +451,7 @@
 
     /* Get previous size of block */
     old_size = _msize(*saved);
-    if (old_size == (size_t)-1)
+    if (old_size == -1)
     {
         /* It seems this function was called with an invalid pointer. Bail out. */
         return NULL;
@@ -283,47 +479,116 @@
 
     new_padding = (char *)memblock - (char *)temp;
 
-    /*
-    Memory layout of old block is as follows:
-    +-------+---------------------+-+--------------------------+-----------+
-    |  ...  | "old_padding" bytes | | ... "old_size" bytes ... |    ...    |
-    +-------+---------------------+-+--------------------------+-----------+
-    ^                     ^ ^
-    |                     | |
-    *saved               saved memblock
+/*
+   Memory layout of old block is as follows:
+   +-------+---------------------+-+--------------------------+-----------+
+   |  ...  | "old_padding" bytes | | ... "old_size" bytes ... |    ...    |
+   +-------+---------------------+-+--------------------------+-----------+
+           ^                     ^ ^
+           |                     | |
+        *saved               saved memblock
 
+   Memory layout of new block is as follows:
+   +-------+-----------------------------+-+----------------------+-------+
+   |  ...  |    "new_padding" bytes      | | ... "size" bytes ... |  ...  |
+   +-------+-----------------------------+-+----------------------+-------+
+           ^                             ^ ^
+           |                             | |
+          temp                       saved memblock
 
-    Memory layout of new block is as follows:
-    +-------+-----------------------------+-+----------------------+-------+
-    |  ...  |    "new_padding" bytes      | | ... "size" bytes ... |  ...  |
-    +-------+-----------------------------+-+----------------------+-------+
-    ^                             ^ ^
-    |                             | |
-    temp                       saved memblock
+   However, in the new block, actual data is still written as follows
+   (because it was copied by MSVCRT_realloc):
+   +-------+---------------------+--------------------------------+-------+
+   |  ...  | "old_padding" bytes |   ... "old_size" bytes ...     |  ...  |
+   +-------+---------------------+--------------------------------+-------+
+           ^                             ^ ^
+           |                             | |
+          temp                       saved memblock
 
-    However, in the new block, actual data is still written as follows
-    (because it was copied by MSVCRT_realloc):
-    +-------+---------------------+--------------------------------+-------+
-    |  ...  | "old_padding" bytes |   ... "old_size" bytes ...     |  ...  |
-    +-------+---------------------+--------------------------------+-------+
-    ^                             ^ ^
-    |                             | |
-    temp                       saved memblock
-
-    Therefore, min(old_size,size) bytes of actual data have to be moved
-    from the offset they were at in the old block (temp + old_padding),
-    to the offset they have to be in the new block (temp + new_padding == memblock).
-    */
-    
+   Therefore, min(old_size,size) bytes of actual data have to be moved
+   from the offset they were at in the old block (temp + old_padding),
+   to the offset they have to be in the new block (temp + new_padding == memblock).
+*/
     if (new_padding != old_padding)
         memmove((char *)memblock, (char *)temp + old_padding, (old_size < size) ? old_size : size);
 
     *saved = temp;
 
     return memblock;
- }
+}
 
+/*********************************************************************
+ *		_aligned_realloc (MSVCRT.@)
+ */
 void * CDECL _aligned_realloc(void *memblock, size_t size, size_t alignment)
 {
+    TRACE("(%p, %lu, %lu)\n", memblock, size, alignment);
     return _aligned_offset_realloc(memblock, size, alignment, 0);
 }
+
+/*********************************************************************
+ *		memmove_s (MSVCRT.@)
+ */
+int CDECL memmove_s(void *dest, size_t numberOfElements, const void *src, size_t count)
+{
+    TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count);
+
+    if(!count)
+        return 0;
+
+    if(!dest || !src) {
+        if(dest)
+            memset(dest, 0, numberOfElements);
+
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+
+    if(count > numberOfElements) {
+        memset(dest, 0, numberOfElements);
+
+        *_errno() = ERANGE;
+        return ERANGE;
+    }
+
+    memmove(dest, src, count);
+    return 0;
+}
+
+/*********************************************************************
+ *		strncpy_s (MSVCRT.@)
+ */
+int CDECL strncpy_s(char *dest, size_t numberOfElements,
+        const char *src, size_t count)
+{
+    size_t i, end;
+
+    TRACE("(%s %lu %s %lu)\n", dest, numberOfElements, src, count);
+
+    if(!count)
+        return 0;
+
+    if(!dest || !src || !numberOfElements) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+
+    if(count!=_TRUNCATE && count<numberOfElements)
+        end = count;
+    else
+        end = numberOfElements-1;
+
+    for(i=0; i<end && src[i]; i++)
+        dest[i] = src[i];
+
+    if(!src[i] || end==count || count==_TRUNCATE) {
+        dest[i] = '\0';
+        return 0;
+    }
+
+    _invalid_parameter(NULL, NULL, NULL, 0, 0);
+    dest[0] = '\0';
+    *_errno() = EINVAL;
+    return EINVAL;
+}
