[MSVCRT_WINETEST]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 20 Apr 2014 13:10:24 +0000 (13:10 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 20 Apr 2014 13:10:24 +0000 (13:10 +0000)
* Sync with Wine 1.7.17.
CORE-8080

svn path=/trunk/; revision=62836

15 files changed:
rostests/winetests/msvcrt/CMakeLists.txt
rostests/winetests/msvcrt/cpp.c
rostests/winetests/msvcrt/data.c
rostests/winetests/msvcrt/dir.c
rostests/winetests/msvcrt/file.c
rostests/winetests/msvcrt/heap.c
rostests/winetests/msvcrt/locale.c
rostests/winetests/msvcrt/misc.c
rostests/winetests/msvcrt/msvcrt_test.dsp [deleted file]
rostests/winetests/msvcrt/printf.c
rostests/winetests/msvcrt/scanf.c
rostests/winetests/msvcrt/signal.c
rostests/winetests/msvcrt/string.c
rostests/winetests/msvcrt/testlist.c
rostests/winetests/msvcrt/time.c

index 875f485..5e0d848 100644 (file)
@@ -1,8 +1,5 @@
 
-add_definitions(
-    -D__ROS_LONG64__
-    -D_CRT_NONSTDC_NO_DEPRECATE
-    -D__msvcrt_ulong=ULONG)
+add_definitions(-D__msvcrt_ulong=ULONG)
 
 list(APPEND SOURCE
     cpp.c
@@ -23,12 +20,14 @@ list(APPEND SOURCE
 
 add_executable(msvcrt_winetest ${SOURCE})
 
+set_module_type(msvcrt_winetest win32cui)
+add_importlibs(msvcrt_winetest msvcrt kernel32)
+
 if(MSVC)
     target_link_libraries(msvcrt_winetest oldnames)
+    add_importlibs(msvcrt_winetest ntdll)
 else()
     add_target_compile_flags(msvcrt_winetest "-Wno-format")
 endif()
 
-set_module_type(msvcrt_winetest win32cui)
-add_importlibs(msvcrt_winetest msvcrt kernel32 ntdll)
 add_cd_file(TARGET msvcrt_winetest DESTINATION reactos/bin FOR all)
index 8baf9b6..c331db1 100644 (file)
@@ -238,6 +238,55 @@ static BOOL InitFunctionPtrs(void)
     }
     else
     {
+#ifdef __arm__
+        SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
+        SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
+
+        SET(pexception_ctor, "??0exception@std@@QAA@ABQBD@Z");
+        SET(pexception_copy_ctor, "??0exception@std@@QAA@ABV01@@Z");
+        SET(pexception_default_ctor, "??0exception@std@@QAA@XZ");
+        SET(pexception_dtor, "??1exception@std@@UAA@XZ");
+        SET(pexception_opequals, "??4exception@std@@QAAAAV01@ABV01@@Z");
+        SET(pexception_what, "?what@exception@std@@UBAPBDXZ");
+        SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");/**/
+        SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");/**/
+
+        SET(pbad_typeid_ctor, "??0bad_typeid@std@@QAA@PBD@Z");
+        SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@std@@QAAXXZ");
+        SET(pbad_typeid_copy_ctor, "??0bad_typeid@std@@QAA@ABV01@@Z");
+        SET(pbad_typeid_dtor, "??1bad_typeid@std@@UAA@XZ");
+        SET(pbad_typeid_opequals, "??4bad_typeid@std@@QAAAAV01@ABV01@@Z");
+        SET(pbad_typeid_what, "?what@exception@std@@UBAPBDXZ");
+        SET(pbad_typeid_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
+        SET(pbad_typeid_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
+
+        SETNOFAIL(pbad_cast_ctor, "??0bad_cast@@QAE@ABQBD@Z");
+        if (!pbad_cast_ctor)
+            SET(pbad_cast_ctor, "??0bad_cast@std@@AAA@PBQBD@Z");
+        SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@std@@QAA@PBD@Z");
+        SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@std@@QAAXXZ");
+        /* FIXME: No ARM equivalent for "??0bad_cast@@QAE@ABV0@@Z" */
+        SET(pbad_cast_dtor, "??1bad_cast@std@@UAA@XZ");
+        SET(pbad_cast_opequals, "??4bad_cast@std@@QAAAAV01@ABV01@@Z");
+        SET(pbad_cast_what, "?what@exception@std@@UBAPBDXZ");
+        SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
+        SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
+
+        SET(p__non_rtti_object_ctor, "??0__non_rtti_object@std@@QAA@PBD@Z");
+        SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@std@@QAA@ABV01@@Z");
+        SET(p__non_rtti_object_dtor, "??1__non_rtti_object@std@@UAA@XZ");
+        SET(p__non_rtti_object_opequals, "??4__non_rtti_object@std@@QAAAAV01@ABV01@@Z");
+        SET(p__non_rtti_object_what, "?what@exception@std@@UBAPBDXZ");
+        SET(p__non_rtti_object_vector_dtor, "??_E__non_rtti_object@@UAEPAXI@Z");
+        SET(p__non_rtti_object_scalar_dtor, "??_G__non_rtti_object@@UAEPAXI@Z");
+
+        SET(ptype_info_dtor, "??1type_info@@UAA@XZ");
+        SET(ptype_info_raw_name, "?raw_name@type_info@@QBAPBDXZ");
+        SET(ptype_info_name, "?name@type_info@@QBEPBDXZ");
+        SET(ptype_info_before, "?before@type_info@@QBA_NABV1@@Z");
+        SET(ptype_info_opequals_equals, "??8type_info@@QBA_NABV0@@Z");
+        SET(ptype_info_opnot_equals, "??9type_info@@QBA_NABV0@@Z");
+#else
         SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
         SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
 
@@ -285,6 +334,7 @@ static BOOL InitFunctionPtrs(void)
         SET(ptype_info_before, "?before@type_info@@QBEHABV1@@Z");
         SET(ptype_info_opequals_equals, "??8type_info@@QBEHABV0@@Z");
         SET(ptype_info_opnot_equals, "??9type_info@@QBEHABV0@@Z");
+#endif /* __arm__ */
     }
 
     if (!poperator_new)
@@ -901,6 +951,12 @@ static void test_rtti(void)
     { {RTTI_REF(child_class_rtti, base_descriptor[0]), RTTI_REF(child_class_rtti, base_descriptor[1])} },
     {0, 0, 2, RTTI_REF(child_class_rtti, base_array)},
     {1, 0, 0, RTTI_REF(child_class_rtti, type_info[1]), RTTI_REF(child_class_rtti, object_hierarchy), RTTI_REF(child_class_rtti, object_locator)}
+  }, virtual_base_class_rtti = {
+    { {NULL, NULL, "simple_class"}, {NULL, NULL, "child_class"} },
+    { {RTTI_REF(virtual_base_class_rtti, type_info[1]), 0, {0x10, sizeof(void*), sizeof(int)}, 0}, {RTTI_REF(virtual_base_class_rtti, type_info[0]), 0, {8, -1, 0}, 0} },
+    { {RTTI_REF(virtual_base_class_rtti, base_descriptor[0]), RTTI_REF(virtual_base_class_rtti, base_descriptor[1])} },
+    {0, 0, 2, RTTI_REF(virtual_base_class_rtti, base_array)},
+    {1, 0, 0, RTTI_REF(virtual_base_class_rtti, type_info[1]), RTTI_REF(virtual_base_class_rtti, object_hierarchy), RTTI_REF(virtual_base_class_rtti, object_locator)}
   };
   static struct rtti_data simple_class_sig0_rtti, child_class_sig0_rtti;
 
@@ -912,6 +968,9 @@ static void test_rtti(void)
   void *simple_class_sig0 = &simple_class_sig0_vtbl[1];
   void *child_class_sig0_vtbl[2] = {&child_class_sig0_rtti.object_locator};
   void *child_class_sig0 = &child_class_sig0_vtbl[1];
+  void *virtual_base_class_vtbl[2] = {&virtual_base_class_rtti.object_locator};
+  int virtual_base_class_vbtbl[2] = {0, 0x100};
+  void *virtual_base_class[2] = {&virtual_base_class_vtbl[1], virtual_base_class_vbtbl};
 
   static const char* e_name = "name";
   type_info *ti,*bti;
@@ -958,7 +1017,7 @@ static void test_rtti(void)
   call_func1(pexception_dtor, &e);
   call_func1(pbad_typeid_dtor, &b);
 
-  memcpy(&simple_class_sig0_rtti, &simple_class_rtti, sizeof(struct rtti_data));
+  simple_class_sig0_rtti = simple_class_rtti;
   simple_class_sig0_rtti.object_locator.signature = 0;
   simple_class_sig0_rtti.base_descriptor[0].type_descriptor = RTTI_REF_SIG0(simple_class_sig0_rtti, type_info[0], base);
   simple_class_sig0_rtti.base_array.bases[0] = RTTI_REF_SIG0(simple_class_sig0_rtti, base_descriptor[0], base);
@@ -966,7 +1025,7 @@ static void test_rtti(void)
   simple_class_sig0_rtti.object_locator.type_descriptor = RTTI_REF_SIG0(simple_class_sig0_rtti, type_info[0], base);
   simple_class_sig0_rtti.object_locator.type_hierarchy = RTTI_REF_SIG0(simple_class_sig0_rtti, object_hierarchy, base);
 
-  memcpy(&child_class_sig0_rtti, &child_class_rtti, sizeof(struct rtti_data));
+  child_class_sig0_rtti = child_class_rtti;
   child_class_sig0_rtti.object_locator.signature = 0;
   child_class_sig0_rtti.base_descriptor[0].type_descriptor = RTTI_REF_SIG0(child_class_sig0_rtti, type_info[1], base);
   child_class_sig0_rtti.base_descriptor[1].type_descriptor = RTTI_REF_SIG0(child_class_sig0_rtti, type_info[0], base);
@@ -1026,6 +1085,9 @@ static void test_rtti(void)
 
   casted = p__RTDynamicCast(&child_class, 0, &child_class_rtti.type_info[0], &child_class_rtti.type_info[1], 0);
   ok(casted == (char*)&child_class+4, "failed cast to child class (%p %p)\n", casted, &child_class);
+
+  casted = p__RTDynamicCast(&virtual_base_class, 0, &virtual_base_class_rtti.type_info[0], &virtual_base_class_rtti.type_info[1], 0);
+  ok(casted == (char*)&virtual_base_class+0x110+sizeof(void*), "failed cast to child class (%p %p)\n", casted, &virtual_base_class);
 }
 
 struct _demangle {
@@ -1247,7 +1309,20 @@ static void test_demangle(void)
 /* 122 */ {"?_R2@?BN@???$_Fabs@N@std@@YANAEBV?$complex@N@1@PEAH@Z@4NB",
            "double const `double __cdecl std::_Fabs<double>(class std::complex<double> const & __ptr64,int * __ptr64)'::`29'::_R2",
            "?_R2@?BN@???$_Fabs@N@std@@YANAEBV?$complex@N@1@PEAH@Z@4NB"},
-
+/* 123 */ {"?vtordisp_thunk@std@@$4PPPPPPPM@3EAA_NXZ",
+           "[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{4294967292,4}' (void) __ptr64",
+           "[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{-4,4}' (void) __ptr64"},
+/* 124 */ {"??_9CView@@$BBII@AE",
+           "[thunk]: __thiscall CView::`vcall'{392,{flat}}' }'",
+           "[thunk]: __thiscall CView::`vcall'{392,{flat}}' "},
+/* 125 */ {"?_dispatch@_impl_Engine@SalomeApp@@$R4CE@BA@PPPPPPPM@7AE_NAAVomniCallHandle@@@Z",
+           "[thunk]:public: virtual bool __thiscall SalomeApp::_impl_Engine::_dispatch`vtordispex{36,16,4294967292,8}' (class omniCallHandle &)",
+           "?_dispatch@_impl_Engine@SalomeApp@@$R4CE@BA@PPPPPPPM@7AE_NAAVomniCallHandle@@@Z"},
+/* 126 */ {"?_Doraise@bad_cast@std@@MEBAXXZ", "protected: virtual void __cdecl std::bad_cast::_Doraise(void)", NULL, 0x60},
+/* 127 */ {"??Xstd@@YAAEAV?$complex@M@0@AEAV10@AEBV10@@Z", "class std::complex<float> & ptr64 cdecl std::operator*=(class std::complex<float> & ptr64,class std::complex<float> const & ptr64)", NULL, 1},
+/* 128 */ {"??Xstd@@YAAEAV?$complex@M@0@AEAV10@AEBV10@@Z",
+           "class std::complex<float> & std::operator*=(class std::complex<float> &,class std::complex<float> const &)",
+           "??Xstd@@YAAEAV?$complex@M@0@AEAV10@AEBV10@@Z", 2},
     };
     int i, num_test = (sizeof(test)/sizeof(test[0]));
     char* name;
index c20be18..efd7d1a 100644 (file)
 #include <winnls.h>
 #include <process.h>
 #include <errno.h>
+#include <direct.h>
+
+void __cdecl __getmainargs(int *, char ***, char ***, int, int *);
+static int* (__cdecl *p___p___argc)(void);
+static char*** (__cdecl *p___p___argv)(void);
 
 typedef void (__cdecl *_INITTERMFUN)(void);
 static void (__cdecl *p_initterm)(_INITTERMFUN *start, _INITTERMFUN *end);
@@ -71,7 +76,7 @@ static void test_initterm(void)
 
 static void test_initvar( HMODULE hmsvcrt )
 {
-    OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO) };
+    OSVERSIONINFOA osvi = { sizeof(OSVERSIONINFOA) };
     int *pp_winver   = (int*)GetProcAddress(hmsvcrt, "_winver");
     int *pp_winmajor = (int*)GetProcAddress(hmsvcrt, "_winmajor");
     int *pp_winminor = (int*)GetProcAddress(hmsvcrt, "_winminor");
@@ -86,7 +91,7 @@ static void test_initvar( HMODULE hmsvcrt )
     winver = *pp_winver;
     winminor = *pp_winminor;
     winmajor = *pp_winmajor;
-    GetVersionEx( &osvi);
+    GetVersionExA( &osvi);
     ok( winminor == osvi.dwMinorVersion, "Wrong value for _winminor %02x expected %02x\n",
             winminor, osvi.dwMinorVersion);
     ok( winmajor == osvi.dwMajorVersion, "Wrong value for _winmajor %02x expected %02x\n",
@@ -124,9 +129,110 @@ static void test_get_pgmptr(void)
     ok( pgm != NULL, "_get_pgmptr returned a NULL pointer\n" );
 }
 
+static void test___getmainargs(void)
+{
+    int argc, new_argc, mode;
+    char **argv, **new_argv, **envp;
+    char tmppath[MAX_PATH], filepath[MAX_PATH];
+    FILE *f;
+
+    ok(GetTempPathA(MAX_PATH, tmppath) != 0, "GetTempPath failed\n");
+
+    mode = 0;
+    __getmainargs(&argc, &argv, &envp, 0, &mode);
+    ok(argc == 4, "argc = %d\n", argc);
+    ok(!strcmp(argv[1], "data"), "argv[1] = %s\n", argv[1]);
+    sprintf(filepath, "%s*\\*", tmppath);
+    ok(!strcmp(argv[2], filepath), "argv[2] = %s\n", argv[2]);
+    sprintf(filepath, "%swine_test/*", tmppath);
+    ok(!strcmp(argv[3], filepath), "argv[3] = %s\n", argv[3]);
+    ok(!argv[4], "argv[4] != NULL\n");
+
+    if(p___p___argc && p___p___argv) {
+        new_argc = *p___p___argc();
+        new_argv = *p___p___argv();
+        ok(new_argc == 4, "*__p___argc() = %d\n", new_argc);
+        ok(new_argv == argv, "*__p___argv() = %p, epxected %p\n", new_argv, argv);
+    }else {
+        win_skip("__p___argc or __p___argv is not available\n");
+    }
+
+    mode = 0;
+    __getmainargs(&argc, &argv, &envp, 1, &mode);
+    ok(argc == 5, "argc = %d\n", argc);
+    ok(!strcmp(argv[1], "data"), "argv[1] = %s\n", argv[1]);
+    sprintf(filepath, "%s*\\*", tmppath);
+    ok(!strcmp(argv[2], filepath), "argv[2] = %s\n", argv[2]);
+    sprintf(filepath, "%swine_test/a", tmppath);
+    if(argv[3][strlen(argv[3])-1] == 'a') {
+        ok(!strcmp(argv[3], filepath), "argv[3] = %s\n", argv[3]);
+        sprintf(filepath, "%swine_test/test", tmppath);
+        ok(!strcmp(argv[4], filepath), "argv[4] = %s\n", argv[4]);
+    }else {
+        ok(!strcmp(argv[4], filepath), "argv[4] = %s\n", argv[4]);
+        sprintf(filepath, "%swine_test/test", tmppath);
+        ok(!strcmp(argv[3], filepath), "argv[3] = %s\n", argv[3]);
+    }
+    ok(!argv[5], "argv[5] != NULL\n");
+
+    if(p___p___argc && p___p___argv) {
+        new_argc = *p___p___argc();
+        new_argv = *p___p___argv();
+        ok(new_argc == argc, "*__p___argc() = %d, expected %d\n", new_argc, argc);
+        ok(new_argv == argv, "*__p___argv() = %p, epxected %p\n", new_argv, argv);
+    }
+
+    sprintf(filepath, "%swine_test/b", tmppath);
+    f = fopen(filepath, "w");
+    ok(f != NULL, "fopen(%s) failed: %d\n", filepath, errno);
+    fclose(f);
+    mode = 0;
+    __getmainargs(&new_argc, &new_argv, &envp, 1, &mode);
+    ok(new_argc == argc+1, "new_argc = %d, expected %d\n", new_argc, argc+1);
+    _unlink(filepath);
+}
+
+static void test___getmainargs_parent(char *name)
+{
+    char cmdline[3*MAX_PATH];
+    char tmppath[MAX_PATH], filepath[MAX_PATH];
+    STARTUPINFOA startup;
+    PROCESS_INFORMATION proc;
+    FILE *f;
+    int ret;
+
+    ok(GetTempPathA(MAX_PATH, tmppath) != 0, "GetTempPath failed\n");
+    sprintf(cmdline, "%s data %s*\\* %swine_test/*", name, tmppath, tmppath);
+
+    sprintf(filepath, "%swine_test", tmppath);
+    ret = _mkdir(filepath);
+    ok(!ret, "_mkdir failed: %d\n", errno);
+    sprintf(filepath, "%swine_test\\a", tmppath);
+    f = fopen(filepath, "w");
+    ok(f != NULL, "fopen(%s) failed: %d\n", filepath, errno);
+    fclose(f);
+    sprintf(filepath, "%swine_test\\test", tmppath);
+    f = fopen(filepath, "w");
+    ok(f != NULL, "fopen(%s) failed: %d\n", filepath, errno);
+    fclose(f);
+
+    memset(&startup, 0, sizeof(startup));
+    startup.cb = sizeof(startup);
+    CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
+    winetest_wait_child_process(proc.hProcess);
+
+    _unlink(filepath);
+    sprintf(filepath, "%swine_test\\a", tmppath);
+    _unlink(filepath);
+    sprintf(filepath, "%swine_test", tmppath);
+    _rmdir(filepath);
+}
+
 START_TEST(data)
 {
     HMODULE hmsvcrt;
+    int arg_c;
+    char** arg_v;
 
     hmsvcrt = GetModuleHandleA("msvcrt.dll");
     if (!hmsvcrt)
@@ -135,8 +241,18 @@ START_TEST(data)
     {
         p_initterm=(void*)GetProcAddress(hmsvcrt, "_initterm");
         p_get_pgmptr=(void*)GetProcAddress(hmsvcrt, "_get_pgmptr");
+        p___p___argc=(void*)GetProcAddress(hmsvcrt, "__p___argc");
+        p___p___argv=(void*)GetProcAddress(hmsvcrt, "__p___argv");
+    }
+
+    arg_c = winetest_get_mainargs(&arg_v);
+    if(arg_c >= 3) {
+        test___getmainargs();
+        return;
     }
+
     test_initterm();
     test_initvar(hmsvcrt);
     test_get_pgmptr();
+    test___getmainargs_parent(arg_v[0]);
 }
index 83c533b..aa273ea 100644 (file)
@@ -25,6 +25,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <io.h>
+#include <mbctype.h>
 #include <windef.h>
 #include <winbase.h>
 #include <winnls.h>
@@ -345,28 +346,28 @@ static void test_fullpath(void)
     BOOL rc,free1,free2;
 
     free1=free2=TRUE;
-    GetCurrentDirectory(MAX_PATH, prevpath);
-    GetTempPath(MAX_PATH,tmppath);
+    GetCurrentDirectoryA(MAX_PATH, prevpath);
+    GetTempPathA(MAX_PATH,tmppath);
     strcpy(level1,tmppath);
     strcat(level1,"msvcrt-test\\");
 
-    rc = CreateDirectory(level1,NULL);
+    rc = CreateDirectoryA(level1,NULL);
     if (!rc && GetLastError()==ERROR_ALREADY_EXISTS)
         free1=FALSE;
 
     strcpy(level2,level1);
     strcat(level2,"nextlevel\\");
-    rc = CreateDirectory(level2,NULL);
+    rc = CreateDirectoryA(level2,NULL);
     if (!rc && GetLastError()==ERROR_ALREADY_EXISTS)
         free2=FALSE;
-    SetCurrentDirectory(level2);
+    SetCurrentDirectoryA(level2);
 
     ok(_fullpath(full,"test", MAX_PATH)!=NULL,"_fullpath failed\n");
     strcpy(teststring,level2);
     strcat(teststring,"test");
     ok(strcmp(full,teststring)==0,"Invalid Path returned %s\n",full);
     ok(_fullpath(full,"\\test", MAX_PATH)!=NULL,"_fullpath failed\n");
-    strncpy(teststring,level2,3);
+    memcpy(teststring,level2,3);
     teststring[3]=0;
     strcat(teststring,"test");
     ok(strcmp(full,teststring)==0,"Invalid Path returned %s\n",full);
@@ -383,11 +384,36 @@ static void test_fullpath(void)
     ok(strcmp(freeme,teststring)==0,"Invalid Path returned %s\n",freeme);
     free(freeme);
 
-    SetCurrentDirectory(prevpath);
+    SetCurrentDirectoryA(prevpath);
     if (free2)
-        RemoveDirectory(level2);
+        RemoveDirectoryA(level2);
     if (free1)
-        RemoveDirectory(level1);
+        RemoveDirectoryA(level1);
+}
+
+static void test_splitpath(void)
+{
+    const char* path = "c:\\\x83\x5c\x83\x74\x83\x67.bin";
+    char drive[3], dir[MAX_PATH], fname[MAX_PATH], ext[MAX_PATH];
+    int prev_cp = _getmbcp();
+
+    /* SBCS codepage */
+    _setmbcp(1252);
+    _splitpath(path, drive, dir, fname, ext);
+    ok(!strcmp(drive, "c:"), "got %s\n", drive);
+    ok(!strcmp(dir, "\\\x83\x5c"), "got %s\n", dir);
+    ok(!strcmp(fname, "\x83\x74\x83\x67"), "got %s\n", fname);
+    ok(!strcmp(ext, ".bin"), "got %s\n", ext);
+
+    /* MBCS (Japanese) codepage */
+    _setmbcp(932);
+    _splitpath(path, drive, dir, fname, ext);
+    ok(!strcmp(drive, "c:"), "got %s\n", drive);
+    ok(!strcmp(dir, "\\"), "got %s\n", dir);
+    ok(!strcmp(fname, "\x83\x5c\x83\x74\x83\x67"), "got %s\n", fname);
+    ok(!strcmp(ext, ".bin"), "got %s\n", ext);
+
+    _setmbcp(prev_cp);
 }
 
 START_TEST(dir)
@@ -397,4 +423,5 @@ START_TEST(dir)
     test_fullpath();
     test_makepath();
     test_makepath_s();
+    test_splitpath();
 }
index e450b72..f6a1624 100644 (file)
 #include <winnls.h>
 #include <process.h>
 #include <errno.h>
+#include <locale.h>
+
+#define MSVCRT_FD_BLOCK_SIZE 32
+typedef struct {
+    HANDLE              handle;
+    unsigned char       wxflag;
+    char                lookahead[3];
+    int                 exflag;
+    CRITICAL_SECTION    crit;
+} ioinfo;
+static ioinfo **__pioinfo;
 
 static HANDLE proc_handles[2];
 
 static int (__cdecl *p_fopen_s)(FILE**, const char*, const char*);
 static int (__cdecl *p__wfopen_s)(FILE**, const wchar_t*, const wchar_t*);
 
+static const char* get_base_name(const char *path)
+{
+    const char *ret = path+strlen(path)-1;
+
+    while(ret >= path) {
+        if(*ret=='\\' || *ret=='/')
+            break;
+        ret--;
+    }
+    return ret+1;
+}
+
 static void init(void)
 {
     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
 
+    setlocale(LC_CTYPE, "C");
+
     p_fopen_s = (void*)GetProcAddress(hmod, "fopen_s");
     p__wfopen_s = (void*)GetProcAddress(hmod, "_wfopen_s");
+    __pioinfo = (void*)GetProcAddress(hmod, "__pioinfo");
 }
 
 static void test_filbuf( void )
@@ -443,11 +469,11 @@ static void test_filemodeT(void)
     FILE* f;
     size_t bytesWritten;
     size_t bytesRead;
-    WIN32_FIND_DATA findData;
+    WIN32_FIND_DATAA findData;
     HANDLE h;
 
-    GetTempPath (MAX_PATH, temppath);
-    GetTempFileName (temppath, "", 0, tempfile);
+    GetTempPathA(MAX_PATH, temppath);
+    GetTempFileNameA(temppath, "", 0, tempfile);
 
     f = fopen(tempfile, "w+bDT");
     bytesWritten = fwrite(DATA, 1, sizeof(DATA), f);
@@ -458,7 +484,7 @@ static void test_filemodeT(void)
     ok (bytesRead == bytesWritten && bytesRead == sizeof(DATA),
         "fopen file mode 'T' wrongly interpreted as 't'\n" );
 
-    h = FindFirstFile(tempfile, &findData);
+    h = FindFirstFileA(tempfile, &findData);
 
     ok (h == INVALID_HANDLE_VALUE, "file wasn't deleted when closed.\n" );
 
@@ -708,7 +734,7 @@ static void test_fgetwc( void )
   ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
   fgetws(wtextW,LLEN,tempfh);
   l=ftell(tempfh);
-  ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
+  ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlenA(mytext), l);
   mytextW = AtoW (mytext);
   aptr = mytextW;
   wptr = wtextW;
@@ -792,6 +818,190 @@ static void test_fgetwc( void )
   free(tempf);
 }
 
+static void test_fgetwc_locale(const char* text, const char* locale, int codepage)
+{
+    char temppath[MAX_PATH], tempfile[MAX_PATH];
+    FILE *tempfh;
+    static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
+    WCHAR wtextW[BUFSIZ];
+    int ret = 0, i;
+    wint_t ch;
+
+    if (!setlocale(LC_CTYPE, locale))
+    {
+        win_skip("%s locale not available\n", locale);
+        return;
+    }
+
+    GetTempPathA(MAX_PATH, temppath);
+    GetTempFileNameA(temppath, "", 0, tempfile);
+
+    tempfh = fopen(tempfile, "wb");
+    ok(tempfh != NULL, "can't open tempfile\n");
+    fwrite(text, 1, strlen(text), tempfh);
+    fclose(tempfh);
+
+    if (codepage != 0)
+    {
+        /* mbstowcs rejects invalid multibyte sequence,
+           so we use MultiByteToWideChar here. */
+        ret = MultiByteToWideChar(codepage, 0, text, -1,
+                                  wtextW, sizeof(wtextW)/sizeof(wtextW[0]));
+        ok(ret > 0, "MultiByteToWideChar failed\n");
+    }
+    else
+    {
+        /* C locale */
+        const char *p;
+        for (p = text; *p != '\0'; p++)
+            wtextW[ret++] = (unsigned char)*p;
+        wtextW[ret++] = 0;
+    }
+
+    tempfh = fopen(tempfile, "rt");
+    ok(tempfh != NULL, "can't open tempfile\n");
+
+    for (i = 0; i < ret-1; i++)
+    {
+        ch = fgetwc(tempfh);
+        ok(ch == wtextW[i], "got %04hx, expected %04hx (cp%d[%d])\n", ch, wtextW[i], codepage, i);
+    }
+    ch = fgetwc(tempfh);
+    ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
+    fclose(tempfh);
+
+    tempfh = fopen(tempfile, "wb");
+    ok(tempfh != NULL, "can't open tempfile\n");
+    fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
+    fclose(tempfh);
+
+    tempfh = fopen(tempfile, "rb");
+    ok(tempfh != NULL, "can't open tempfile\n");
+    for (i = 0; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
+    {
+        ch = fgetwc(tempfh);
+        ok(ch == wchar_text[i], "got %04hx, expected %04x (cp%d[%d])\n", ch, wchar_text[i], codepage, i);
+    }
+    ch = fgetwc(tempfh);
+    ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
+    fclose(tempfh);
+    unlink(tempfile);
+}
+
+static void test_fgetwc_unicode(void)
+{
+    char temppath[MAX_PATH], tempfile[MAX_PATH];
+    FILE *tempfh;
+    static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
+    char utf8_text[BUFSIZ];
+    int ret, i;
+    wint_t ch;
+
+    GetTempPathA(MAX_PATH, temppath);
+    GetTempFileNameA(temppath, "", 0, tempfile);
+
+    if (!p_fopen_s)
+    {
+        win_skip("fopen_s not available\n");
+        return;
+    }
+
+    tempfh = fopen(tempfile, "wb");
+    ok(tempfh != NULL, "can't open tempfile\n");
+    fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
+    fclose(tempfh);
+
+    tempfh = fopen(tempfile, "rt,ccs=unicode");
+    ok(tempfh != NULL, "can't open tempfile\n");
+    for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
+    {
+        ch = fgetwc(tempfh);
+        ok(ch == wchar_text[i],
+           "got %04hx, expected %04x (unicode[%d])\n", ch, wchar_text[i], i-1);
+    }
+    ch = fgetwc(tempfh);
+    ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch);
+    fclose(tempfh);
+
+    tempfh = fopen(tempfile, "wb");
+    ok(tempfh != NULL, "can't open tempfile\n");
+    ret = WideCharToMultiByte(CP_UTF8, 0, wchar_text, sizeof(wchar_text)/sizeof(wchar_text[0]),
+                              utf8_text, sizeof(utf8_text), NULL, NULL);
+    ok(ret > 0, "utf-8 conversion failed\n");
+    fwrite(utf8_text, sizeof(char), ret, tempfh);
+    fclose(tempfh);
+
+    tempfh = fopen(tempfile, "rt, ccs=UTF-8");
+    ok(tempfh != NULL, "can't open tempfile\n");
+    for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
+    {
+        ch = fgetwc(tempfh);
+        ok(ch == wchar_text[i],
+           "got %04hx, expected %04x (utf8[%d])\n", ch, wchar_text[i], i-1);
+    }
+    ch = fgetwc(tempfh);
+    ok(ch == WEOF, "got %04hx, expected WEOF (utf8)\n", ch);
+    fclose(tempfh);
+    unlink(temppath);
+}
+
+static void test_fputwc(void)
+{
+    char temppath[MAX_PATH];
+    char tempfile[MAX_PATH];
+    FILE *f;
+    char buf[1024];
+    int ret;
+
+    GetTempPathA(MAX_PATH, temppath);
+    GetTempFileNameA(temppath, "", 0, tempfile);
+
+    f = fopen(tempfile, "w");
+    ret = fputwc('a', f);
+    ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
+    ret = fputwc('\n', f);
+    ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
+    fclose(f);
+
+    f = fopen(tempfile, "rb");
+    ret = fread(buf, 1, sizeof(buf), f);
+    ok(ret == 3, "fread returned %d, expected 3\n", ret);
+    ok(!memcmp(buf, "a\r\n", 3), "incorrect file data\n");
+    fclose(f);
+
+    if(p_fopen_s) {
+        f = fopen(tempfile, "w,ccs=unicode");
+        ret = fputwc('a', f);
+        ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
+        ret = fputwc('\n', f);
+        ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
+        fclose(f);
+
+        f = fopen(tempfile, "rb");
+        ret = fread(buf, 1, sizeof(buf), f);
+        ok(ret == 8, "fread returned %d, expected 8\n", ret);
+        ok(!memcmp(buf, "\xff\xfe\x61\x00\r\x00\n\x00", 8), "incorrect file data\n");
+        fclose(f);
+
+        f = fopen(tempfile, "w,ccs=utf-8");
+        ret = fputwc('a', f);
+        ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
+        ret = fputwc('\n', f);
+        ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
+        fclose(f);
+
+        f = fopen(tempfile, "rb");
+        ret = fread(buf, 1, sizeof(buf), f);
+        ok(ret == 6, "fread returned %d, expected 6\n", ret);
+        ok(!memcmp(buf, "\xef\xbb\xbf\x61\r\n", 6), "incorrect file data\n");
+        fclose(f);
+    }else {
+        win_skip("fputwc tests on unicode files\n");
+    }
+
+    _unlink(tempfile);
+}
+
 static void test_ctrlz( void )
 {
   char* tempf;
@@ -956,6 +1166,11 @@ static void test_file_write_read( void )
   _lseek(tempfd, -2, FILE_END);
   ret = _read(tempfd,btext,LLEN);
   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
+  _lseek(tempfd, -2, FILE_END);
+  ret = _read(tempfd,btext,1);
+  ok(ret == 1 && *btext == '\n', "_read returned %d, buf: %d\n", ret, *btext);
+  ret = read(tempfd,btext,1);
+  ok(ret == 0, "_read returned %d, expected 0\n", ret);
   _lseek(tempfd, -3, FILE_END);
   ret = _read(tempfd,btext,1);
   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
@@ -975,7 +1190,7 @@ static void test_file_write_read( void )
   free(tempf);
 
   tempf=_tempnam(".","wne");
-  tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
+  tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR, _S_IWRITE);
   ok( tempfd != -1,
      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
@@ -1011,6 +1226,95 @@ static void test_file_write_read( void )
   ok(i == strlen(mytext)-1, "_read_i %d\n", i);
   _close(tempfd);
 
+  /* test read/write in unicode mode */
+  if(p_fopen_s)
+  {
+      tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_WTEXT, _S_IWRITE);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      ret = _write(tempfd, "a", 1);
+      ok(ret == -1, "_write returned %d, expected -1\n", ret);
+      ret = _write(tempfd, "a\x00\n\x00\xff\xff", 6);
+      ok(ret == 6, "_write returned %d, expected 6\n", ret);
+      _close(tempfd);
+
+      tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      ret = _read(tempfd, btext, sizeof(btext));
+      ok(ret == 10, "_read returned %d, expected 10\n", ret);
+      ok(!memcmp(btext, "\xff\xfe\x61\x00\r\x00\n\x00\xff\xff", 10), "btext is incorrect\n");
+      _close(tempfd);
+
+      tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      errno = 0xdeadbeef;
+      ret = _read(tempfd, btext, 3);
+      ok(ret == -1, "_read returned %d, expected -1\n", ret);
+      ok(errno == 22, "errno = %d\n", errno);
+      ret = _read(tempfd, btext, sizeof(btext));
+      ok(ret == 6, "_read returned %d, expected 6\n", ret);
+      ok(!memcmp(btext, "\x61\x00\n\x00\xff\xff", 6), "btext is incorrect\n");
+      _close(tempfd);
+
+      tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_U8TEXT, _S_IWRITE);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      errno = 0xdeadbeef;
+      ret = _write(tempfd, "a", 1);
+      ok(ret == -1, "_write returned %d, expected -1\n", ret);
+      ok(errno == 22, "errno = %d\n", errno);
+      ret = _write(tempfd, "a\x00\n\x00\x62\x00", 6);
+      ok(ret == 6, "_write returned %d, expected 6\n", ret);
+      _close(tempfd);
+
+      tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      ret = _read(tempfd, btext, sizeof(btext));
+      ok(ret == 7, "_read returned %d, expected 7\n", ret);
+      ok(!memcmp(btext, "\xef\xbb\xbf\x61\r\n\x62", 7), "btext is incorrect\n");
+      _close(tempfd);
+
+      tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      ret = _read(tempfd, btext, sizeof(btext));
+      ok(ret == 6, "_read returned %d, expected 6\n", ret);
+      ok(!memcmp(btext, "\x61\x00\n\x00\x62\x00", 6), "btext is incorrect\n");
+
+      /* when buffer is small read sometimes fails in native implementation */
+      lseek(tempfd, 3 /* skip bom */, SEEK_SET);
+      ret = _read(tempfd, btext, 4);
+      todo_wine ok(ret == -1, "_read returned %d, expected -1\n", ret);
+
+      lseek(tempfd, 6, SEEK_SET);
+      ret = _read(tempfd, btext, 2);
+      ok(ret == 2, "_read returned %d, expected 2\n", ret);
+      ok(!memcmp(btext, "\x62\x00", 2), "btext is incorrect\n");
+      _close(tempfd);
+
+      tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IWRITE);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      ret = _write(tempfd, "\xef\xbb\xbf\x61\xc4\x85\x62\xc5\xbc\r\r\n", 12);
+      ok(ret == 12, "_write returned %d, expected 9\n", ret);
+      _close(tempfd);
+
+      tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
+      ok(tempfd != -1, "_open failed with error: %d\n", errno);
+      ret = _read(tempfd, btext, sizeof(btext));
+      ok(ret == 12, "_read returned %d, expected 12\n", ret);
+      ok(!memcmp(btext, "\x61\x00\x05\x01\x62\x00\x7c\x01\x0d\x00\x0a\x00", 12), "btext is incorrect\n");
+
+      /* test invalid utf8 sequence */
+      lseek(tempfd, 5, SEEK_SET);
+      ret = _read(tempfd, btext, sizeof(btext));
+      todo_wine ok(ret == 10, "_read returned %d, expected 10\n", ret);
+      /* invalid char should be replaced by U+FFFD in MultiByteToWideChar */
+      todo_wine ok(!memcmp(btext, "\xfd\xff", 2), "invalid UTF8 character was not replaced by U+FFFD\n");
+      ok(!memcmp(btext+ret-8, "\x62\x00\x7c\x01\x0d\x00\x0a\x00", 8), "btext is incorrect\n");
+      _close(tempfd);
+  }
+  else
+  {
+      win_skip("unicode mode tests on file\n");
+  }
+
   ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
   ok( ret == 0,
      "Can't chmod '%s' to read-write: %d\n", tempf, errno);
@@ -1042,7 +1346,7 @@ static void test_file_inherit_child_no(const char* fd_s)
        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
 }
 
-static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
+static void create_io_inherit_block( STARTUPINFOA *startup, unsigned int count, const HANDLE *handles )
 {
     static BYTE block[1024];
     BYTE *wxflag_ptr;
@@ -1072,7 +1376,7 @@ static const char *read_file( HANDLE file )
     return buffer;
 }
 
-static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
+static void test_stdout_handle( STARTUPINFOA *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
                                 const char *descr )
 {
     const char *data;
@@ -1112,7 +1416,7 @@ static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstd
     }
 
     CloseHandle( hErrorFile );
-    DeleteFile( "fdopen.err" );
+    DeleteFileA( "fdopen.err" );
 }
 
 static void test_file_inherit( const char* selfname )
@@ -1121,13 +1425,13 @@ static void test_file_inherit( const char* selfname )
     const char*                arg_v[5];
     char               buffer[16];
     char cmdline[MAX_PATH];
-    STARTUPINFO startup;
+    STARTUPINFOA startup;
     SECURITY_ATTRIBUTES sa;
     HANDLE handles[3];
 
     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
     ok(fd != -1, "Couldn't create test file\n");
-    arg_v[0] = selfname;
+    arg_v[0] = get_base_name(selfname);
     arg_v[1] = "tests/file.c";
     arg_v[2] = "inherit";
     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
@@ -1141,7 +1445,6 @@ static void test_file_inherit( const char* selfname )
     
     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
     ok(fd != -1, "Couldn't create test file\n");
-    arg_v[0] = selfname;
     arg_v[1] = "tests/file.c";
     arg_v[2] = "inherit_no";
     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
@@ -1159,7 +1462,7 @@ static void test_file_inherit( const char* selfname )
     sprintf(cmdline, "%s file inherit 1", selfname);
 
     /* init an empty Reserved2, which should not be recognized as inherit-block */
-    ZeroMemory(&startup, sizeof(STARTUPINFO));
+    ZeroMemory(&startup, sizeof(startup));
     startup.cb = sizeof(startup);
     create_io_inherit_block( &startup, 0, NULL );
     test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
@@ -1172,7 +1475,7 @@ static void test_file_inherit( const char* selfname )
     create_io_inherit_block( &startup, 3, handles );
     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
     CloseHandle( handles[1] );
-    DeleteFile("fdopen.tst");
+    DeleteFileA("fdopen.tst");
 
     /* test inherit block starting with unsigned zero */
     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
@@ -1181,7 +1484,7 @@ static void test_file_inherit( const char* selfname )
     *(unsigned int *)startup.lpReserved2 = 0;
     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
     CloseHandle( handles[1] );
-    DeleteFile("fdopen.tst");
+    DeleteFileA("fdopen.tst");
 
     /* test inherit block with smaller size */
     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
@@ -1190,7 +1493,7 @@ static void test_file_inherit( const char* selfname )
     startup.cbReserved2 -= 3;
     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
     CloseHandle( handles[1] );
-    DeleteFile("fdopen.tst");
+    DeleteFileA("fdopen.tst");
 
     /* test inherit block with even smaller size */
     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
@@ -1199,7 +1502,7 @@ static void test_file_inherit( const char* selfname )
     startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
     CloseHandle( handles[1] );
-    DeleteFile("fdopen.tst");
+    DeleteFileA("fdopen.tst");
 
     /* test inherit block with larger size */
     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
@@ -1208,7 +1511,7 @@ static void test_file_inherit( const char* selfname )
     startup.cbReserved2 += 7;
     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
     CloseHandle( handles[1] );
-    DeleteFile("fdopen.tst");
+    DeleteFileA("fdopen.tst");
 }
 
 static void test_tmpnam( void )
@@ -1320,6 +1623,7 @@ static void test_fopen_s( void )
 {
     const char name[] = "empty1";
     char buff[16];
+    unsigned char *ubuff = (unsigned char*)buff;
     FILE *file;
     int ret;
     int len;
@@ -1348,6 +1652,69 @@ static void test_fopen_s( void )
     ret = fclose(file);
     ok(ret != EOF, "File failed to close\n");
 
+    ret = p_fopen_s(&file, name, "w,  ccs=UNIcode");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    ret = fwrite("a", 1, 2, file);
+    ok(ret == 2, "fwrite returned %d\n", ret);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "r");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    len = fread(buff, 1, 2, file);
+    ok(len == 2, "len = %d\n", len);
+    ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
+            ubuff[0], ubuff[1]);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "r,ccs=unicode");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    len = fread(buff, 1, 2, file);
+    ok(len == 2, "len = %d\n", len);
+    ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
+            ubuff[0], ubuff[1]);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "r,ccs=utf-16le");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    len = fread(buff, 1, 2, file);
+    ok(len == 2, "len = %d\n", len);
+    ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
+            ubuff[0], ubuff[1]);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "r,ccs=utf-8");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    len = fread(buff, 1, 2, file);
+    ok(len == 2, "len = %d\n", len);
+    ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
+            ubuff[0], ubuff[1]);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "w,ccs=utf-16le");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "r");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    len = fread(buff, 1, 3, file);
+    ok(len == 2, "len = %d\n", len);
+    ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
+            ubuff[0], ubuff[1]);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "w,ccs=utf-8");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    fclose(file);
+
+    ret = p_fopen_s(&file, name, "r");
+    ok(ret == 0, "fopen_s failed with %d\n", ret);
+    len = fread(buff, 1, 4, file);
+    ok(len == 3, "len = %d\n", len);
+    ok(ubuff[0]==0xef && ubuff[1]==0xbb && ubuff[2]==0xbf,
+            "buff[0]=%02x, buff[1]=%02x, buff[2]=%02x\n",
+            ubuff[0], ubuff[1], ubuff[2]);
+    fclose(file);
+
     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
 }
 
@@ -1392,6 +1759,61 @@ static void test__wfopen_s( void )
     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
 }
 
+static void test_setmode(void)
+{
+    const char name[] = "empty1";
+    int fd, ret;
+
+    if(!p_fopen_s) {
+        win_skip("unicode file modes are not available, skipping setmode tests\n");
+        return;
+    }
+
+    fd = _open(name, _O_CREAT|_O_WRONLY, _S_IWRITE);
+    ok(fd != -1, "failed to open file\n");
+
+    errno = 0xdeadbeef;
+    ret = _setmode(fd, 0xffffffff);
+    ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
+    ok(errno == EINVAL, "errno = %d\n", errno);
+
+    errno = 0xdeadbeef;
+    ret = _setmode(fd, 0);
+    ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
+    ok(errno == EINVAL, "errno = %d\n", errno);
+
+    errno = 0xdeadbeef;
+    ret = _setmode(fd, _O_BINARY|_O_TEXT);
+    ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
+    ok(errno == EINVAL, "errno = %d\n", errno);
+
+    errno = 0xdeadbeef;
+    ret = _setmode(fd, _O_WTEXT|_O_U16TEXT);
+    ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
+    ok(errno == EINVAL, "errno = %d\n", errno);
+
+    ret = _setmode(fd, _O_BINARY);
+    ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
+
+    ret = _setmode(fd, _O_WTEXT);
+    ok(ret == _O_BINARY, "_setmode returned %x, expected _O_BINARY\n", ret);
+
+    ret = _setmode(fd, _O_TEXT);
+    ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
+
+    ret = _setmode(fd, _O_U16TEXT);
+    ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
+
+    ret = _setmode(fd, _O_U8TEXT);
+    ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
+
+    ret = _setmode(fd, _O_TEXT);
+    ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
+
+    _close(fd);
+    _unlink(name);
+}
+
 static void test_get_osfhandle(void)
 {
     int fd;
@@ -1444,6 +1866,11 @@ static void test_stat(void)
         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
 
+        errno = 0xdeadbeef;
+        ret = stat("stat.tst\\", &buf);
+        ok(ret == -1, "stat returned %d\n", ret);
+        ok(errno == ENOENT, "errno = %d\n", errno);
+
         close(fd);
         remove("stat.tst");
     }
@@ -1483,6 +1910,35 @@ static void test_stat(void)
     }
     else
         skip("pipe failed with errno %d\n", errno);
+
+    /* Tests for directory */
+    if(mkdir("stat.tst") == 0)
+    {
+        ret = stat("stat.tst                         ", &buf);
+        ok(!ret, "stat(directory) failed: errno=%d\n", errno);
+        ok((buf.st_mode & _S_IFMT) == _S_IFDIR, "bad format = %06o\n", buf.st_mode);
+        ok((buf.st_mode & 0777) == 0777, "bad st_mode = %06o\n", buf.st_mode);
+        ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
+        ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
+
+        errno = 0xdeadbeef;
+        ret = stat("stat.tst\\ ", &buf);
+        ok(ret == -1, "stat returned %d\n", ret);
+        ok(errno == ENOENT, "errno = %d\n", errno);
+        rmdir( "stat.tst" );
+    }
+    else
+        skip("mkdir failed with errno %d\n", errno);
+
+    errno = 0xdeadbeef;
+    ret = stat("c:", &buf);
+    ok(ret == -1, "stat returned %d\n", ret);
+    ok(errno == ENOENT, "errno = %d\n", errno);
+
+    ret = stat("c:/", &buf);
+    ok(!ret, "stat returned %d\n", ret);
+    ok(buf.st_dev == 2, "st_dev = %d\n", buf.st_dev);
+    ok(buf.st_rdev == 2, "st_rdev = %d\n", buf.st_rdev);
 }
 
 static const char* pipe_string="Hello world";
@@ -1538,7 +1994,7 @@ static void test_pipes(const char* selfname)
         return;
     }
 
-    arg_v[0] = selfname;
+    arg_v[0] = get_base_name(selfname);
     arg_v[1] = "tests/file.c";
     arg_v[2] = "pipes";
     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
@@ -1568,7 +2024,6 @@ static void test_pipes(const char* selfname)
         return;
     }
 
-    arg_v[0] = selfname;
     arg_v[1] = "tests/file.c";
     arg_v[2] = "pipes";
     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
@@ -1601,6 +2056,56 @@ static void test_pipes(const char* selfname)
 
     i=fclose(file);
     ok(!i, "unable to close the pipe: %d\n", errno);
+
+    /* test \r handling when it's the last character read */
+    if (_pipe(pipes, 1024, O_BINARY) < 0)
+    {
+        ok(0, "pipe failed with errno %d\n", errno);
+        return;
+    }
+    r = write(pipes[1], "\r\n\rab\r\n", 7);
+    ok(r == 7, "write returned %d, errno = %d\n", r, errno);
+    setmode(pipes[0], O_TEXT);
+    r = read(pipes[0], buf, 1);
+    ok(r == 1, "read returned %d, expected 1\n", r);
+    ok(buf[0] == '\n', "buf[0] = %x, expected '\\n'\n", buf[0]);
+    r = read(pipes[0], buf, 1);
+    ok(r == 1, "read returned %d, expected 1\n", r);
+    ok(buf[0] == '\r', "buf[0] = %x, expected '\\r'\n", buf[0]);
+    r = read(pipes[0], buf, 1);
+    ok(r == 1, "read returned %d, expected 1\n", r);
+    ok(buf[0] == 'a', "buf[0] = %x, expected 'a'\n", buf[0]);
+    r = read(pipes[0], buf, 2);
+    ok(r == 2, "read returned %d, expected 1\n", r);
+    ok(buf[0] == 'b', "buf[0] = %x, expected 'b'\n", buf[0]);
+    ok(buf[1] == '\n', "buf[1] = %x, expected '\\n'\n", buf[1]);
+
+    if (p_fopen_s)
+    {
+        /* test utf16 read with insufficient data */
+        r = write(pipes[1], "a\0b", 3);
+        ok(r == 3, "write returned %d, errno = %d\n", r, errno);
+        buf[2] = 'z';
+        buf[3] = 'z';
+        setmode(pipes[0], _O_WTEXT);
+        r = read(pipes[0], buf, 4);
+        ok(r == 2, "read returned %d, expected 2\n", r);
+        ok(!memcmp(buf, "a\0bz", 4), "read returned incorrect data\n");
+        r = write(pipes[1], "\0", 1);
+        ok(r == 1, "write returned %d, errno = %d\n", r, errno);
+        buf[0] = 'z';
+        buf[1] = 'z';
+        r = read(pipes[0], buf, 2);
+        ok(r == 0, "read returned %d, expected 0\n", r);
+        ok(!memcmp(buf, "\0z", 2), "read returned incorrect data\n");
+    }
+    else
+    {
+        win_skip("unicode mode tests on pipe\n");
+    }
+
+    close(pipes[1]);
+    close(pipes[0]);
 }
 
 static void test_unlink(void)
@@ -1621,6 +2126,99 @@ static void test_dup2(void)
     ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
 }
 
+static void test_stdin(void)
+{
+    HANDLE stdinh = GetStdHandle(STD_INPUT_HANDLE);
+    int stdin_dup, fd;
+    HANDLE h;
+    DWORD r;
+
+    stdin_dup = _dup(STDIN_FILENO);
+    ok(stdin_dup != -1, "_dup(STDIN_FILENO) failed\n");
+
+    ok(stdinh == (HANDLE)_get_osfhandle(STDIN_FILENO),
+            "GetStdHandle(STD_INPUT_HANDLE) != _get_osfhandle(STDIN_FILENO)\n");
+
+    r = SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
+    ok(r == TRUE, "SetStdHandle returned %x, expected TRUE\n", r);
+    h = GetStdHandle(STD_INPUT_HANDLE);
+    ok(h == INVALID_HANDLE_VALUE, "h = %p\n", h);
+
+    close(STDIN_FILENO);
+    h = GetStdHandle(STD_INPUT_HANDLE);
+    ok(h == NULL, "h != NULL\n");
+
+    fd = open("stdin.tst", O_WRONLY | O_CREAT, _S_IREAD |_S_IWRITE);
+    ok(fd != -1, "open failed\n");
+    ok(fd == STDIN_FILENO, "fd = %d, expected STDIN_FILENO\n", fd);
+    h = GetStdHandle(STD_INPUT_HANDLE);
+    ok(h != NULL, "h == NULL\n");
+    close(fd);
+    unlink("stdin.tst");
+
+    r = _dup2(stdin_dup, STDIN_FILENO);
+    ok(r != -1, "_dup2 failed\n");
+    h = GetStdHandle(STD_INPUT_HANDLE);
+    ok(h != NULL, "h == NULL\n");
+}
+
+static void test_mktemp(void)
+{
+    char buf[16];
+
+    strcpy(buf, "a");
+    ok(!_mktemp(buf), "_mktemp(\"a\") != NULL\n");
+
+    strcpy(buf, "testXXXXX");
+    ok(!_mktemp(buf), "_mktemp(\"testXXXXX\") != NULL\n");
+
+    strcpy(buf, "testXXXXXX");
+    ok(_mktemp(buf) != NULL, "_mktemp(\"testXXXXXX\") == NULL\n");
+
+    strcpy(buf, "testXXXXXXa");
+    ok(!_mktemp(buf), "_mktemp(\"testXXXXXXa\") != NULL\n");
+
+    strcpy(buf, "**XXXXXX");
+    ok(_mktemp(buf) != NULL, "_mktemp(\"**XXXXXX\") == NULL\n");
+}
+
+static void test__open_osfhandle(void)
+{
+    ioinfo *info;
+    HANDLE h, tmp;
+    int fd;
+
+    errno = 0xdeadbeef;
+    fd = _open_osfhandle((intptr_t)INVALID_HANDLE_VALUE, 0);
+    ok(fd == -1, "_open_osfhandle returned %d\n", fd);
+    ok(errno == EBADF, "errno = %d\n", errno);
+
+    h = CreateFileA("open_osfhandle.tst", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+    fd = _open_osfhandle((intptr_t)h, 0);
+    ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
+    info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
+    ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
+    ok(info->wxflag == 1, "info->wxflag = %x, expected 1\n", info->wxflag);
+    close(fd);
+    ok(info->handle == INVALID_HANDLE_VALUE, "info->handle = %p, expected INVALID_HANDLE_VALUE\n", info->handle);
+    ok(info->wxflag == 0, "info->wxflag = %x, expected 0\n", info->wxflag);
+    DeleteFileA("open_osfhandle.tst");
+
+    errno = 0xdeadbeef;
+    fd = _open_osfhandle((intptr_t)h, 0);
+    ok(fd == -1, "_open_osfhandle returned %d\n", fd);
+    ok(errno == EBADF, "errno = %d\n", errno);
+
+    ok(CreatePipe(&h, &tmp, NULL, 0), "CreatePipe failed\n");
+    fd = _open_osfhandle((intptr_t)h, 0);
+    ok(fd > 0, "_open_osfhandle returned %d (%d)\n", fd, errno);
+    info = &__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][fd%MSVCRT_FD_BLOCK_SIZE];
+    ok(info->handle == h, "info->handle = %p, expected %p\n", info->handle, h);
+    ok(info->wxflag == 9, "info->wxflag = %x, expected 9\n", info->wxflag);
+    close(fd);
+    CloseHandle(tmp);
+}
+
 START_TEST(file)
 {
     int arg_c;
@@ -1656,6 +2254,7 @@ START_TEST(file)
     test_fopen_fclose_fcloseall();
     test_fopen_s();
     test__wfopen_s();
+    test_setmode();
     test_fileops();
     test_asciimode();
     test_asciimode2();
@@ -1668,12 +2267,23 @@ START_TEST(file)
     test_flsbuf();
     test_fflush();
     test_fgetwc();
+    /* \x83\xa9 is double byte character, \xe0\x7f is not (undefined). */
+    test_fgetwc_locale("AB\x83\xa9\xe0\x7f", "Japanese_Japan.932", 932);
+    /* \x83 is U+0192 */
+    test_fgetwc_locale("AB\x83\xa9", "English", 1252);
+    /* \x83 is U+0083 */
+    test_fgetwc_locale("AB\x83\xa9", "C", 0);
+    test_fgetwc_unicode();
+    test_fputwc();
     test_ctrlz();
     test_file_put_get();
     test_tmpnam();
     test_get_osfhandle();
     test_setmaxstdio();
     test_pipes(arg_v[0]);
+    test_stdin();
+    test_mktemp();
+    test__open_osfhandle();
 
     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
      * file contains lines in the correct order
index 3587e0e..309e194 100644 (file)
@@ -233,7 +233,7 @@ static void test_aligned_offset_realloc(unsigned int size1, unsigned int size2,
 
 static void test_aligned(void)
 {
-    HMODULE msvcrt = GetModuleHandle("msvcrt.dll");
+    HMODULE msvcrt = GetModuleHandleA("msvcrt.dll");
 
     if (msvcrt == NULL)
         return;
index 6b09cdf..dfb2146 100644 (file)
@@ -49,9 +49,6 @@ static void test_setlocale(void)
     ret = setlocale(20, "C");
     ok(ret == NULL, "ret = %s\n", ret);
 
-    ret = setlocale(LC_ALL, "");
-    ok(ret != NULL, "ret == NULL\n");
-
     ret = setlocale(LC_ALL, "C");
     ok(!strcmp(ret, "C"), "ret = %s\n", ret);
 
@@ -116,12 +113,14 @@ static void test_setlocale(void)
     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
     if(ret)
         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
+        || !strcmp(ret, "Chinese (Simplified)_China.936")
         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
 
     ret = setlocale(LC_ALL, "chinese-simplified");
     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
     if(ret)
         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
+        || !strcmp(ret, "Chinese (Simplified)_China.936")
         || broken(!strcmp(ret, "Chinese_People's Republic of China.936"))
         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
 
@@ -135,6 +134,7 @@ static void test_setlocale(void)
     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
     if(ret)
         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
+        || !strcmp(ret, "Chinese (Simplified)_China.936")
         || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret);
 
     ret = setlocale(LC_ALL, "cht");
@@ -143,6 +143,18 @@ static void test_setlocale(void)
         ok(!strcmp(ret, "Chinese (Traditional)_Taiwan.950")
         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
 
+    ret = setlocale(LC_ALL, "Chinese_China.936");
+todo_wine
+    ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
+    if(ret)
+    {
+todo_wine
+        ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
+        || !strcmp(ret, "Chinese (Simplified)_China.936")
+        || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret);
+        trace("ret is %s\n", ret);
+    }
+
     ret = setlocale(LC_ALL, "csy");
     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
     if(ret)
@@ -575,6 +587,27 @@ static void test_setlocale(void)
     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
     if(ret)
         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
+
+    ret = setlocale(LC_ALL, "English_United States.ACP");
+    ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
+    if(ret) {
+        strcpy(buf, "English_United States.");
+        GetLocaleInfoA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
+                LOCALE_IDEFAULTANSICODEPAGE, buf+strlen(buf), 80);
+        ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf);
+    }
+
+    ret = setlocale(LC_ALL, "English_United States.OCP");
+    ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
+    if(ret) {
+        strcpy(buf, "English_United States.");
+        GetLocaleInfoA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
+                LOCALE_IDEFAULTCODEPAGE, buf+strlen(buf), 80);
+        ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf);
+    }
+
+    ret = setlocale(LC_ALL, "English_United States.UTF8");
+    ok(ret == NULL, "ret != NULL\n");
 }
 
 static void test_crtGetStringTypeW(void)
@@ -632,6 +665,7 @@ static void test__Gettnames(void)
         char data[1];
     } *ret;
     int size;
+    char buf[64];
 
     if(!setlocale(LC_ALL, "english"))
         return;
@@ -688,7 +722,10 @@ static void test__Gettnames(void)
     ok(!strcmp(ret->str[39], "PM"), "ret->str[39] = %s\n", ret->str[39]);
     ok(!strcmp(ret->str[40], "M/d/yyyy") || broken(!strcmp(ret->str[40], "M/d/yy"))/*NT*/,
             "ret->str[40] = %s\n", ret->str[40]);
-    ok(!strcmp(ret->str[41], "dddd, MMMM dd, yyyy"), "ret->str[41] = %s\n", ret->str[41]);
+    size = GetLocaleInfoA(MAKELCID(LANG_ENGLISH, SORT_DEFAULT),
+           LOCALE_SLONGDATE|LOCALE_NOUSEROVERRIDE, buf, sizeof(buf));
+    ok(size, "GetLocaleInfo failed: %x\n", GetLastError());
+    ok(!strcmp(ret->str[41], buf), "ret->str[41] = %s, expected %s\n", ret->str[41], buf);
     free(ret);
 
     if(!setlocale(LC_TIME, "german"))
@@ -745,10 +782,8 @@ static void test__Gettnames(void)
 static void test___mb_cur_max_func(void)
 {
     int mb_cur_max;
-    CPINFO cp;
 
     setlocale(LC_ALL, "C");
-    GetCPInfo(CP_ACP, &cp);
 
     /* for newer Windows */
     if(!p___mb_cur_max_func)
@@ -772,13 +807,7 @@ static void test___mb_cur_max_func(void)
         win_skip("Skipping __p___mb_cur_max tests\n");
     else {
         mb_cur_max = *p__p___mb_cur_max();
-        if (cp.MaxCharSize != 1) {
-            todo_wine ok(mb_cur_max == cp.MaxCharSize, "mb_cur_max = %d, expected %d\n",
-                    mb_cur_max, cp.MaxCharSize);
-        }
-        else {
-            ok(mb_cur_max == 1, "mb_cur_max = %d, expected 1\n", mb_cur_max);
-        }
+        ok(mb_cur_max == 1, "mb_cur_max = %d, expected 1\n", mb_cur_max);
 
         /* some old Windows don't set chinese */
         if (!setlocale(LC_ALL, "chinese"))
index a2bf0cb..26225f3 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "wine/test.h"
 #include <errno.h>
+#include <stdio.h>
 #include "msvcrt.h"
 
 static int (__cdecl *prand_s)(unsigned int *);
@@ -309,10 +310,54 @@ static void test__set_errno(void)
     ok(errno == 0xdeadbeef, "Expected errno to be 0xdeadbeef, got %d\n", errno);
 }
 
+static void test__popen_child(void)
+{
+    /* don't execute any tests here */
+    /* ExitProcess is used to set return code of _pclose */
+    printf("child output\n");
+    ExitProcess(0x37);
+}
+
+static void test__popen(const char *name)
+{
+    FILE *pipe;
+    char buf[1024];
+    int ret;
+
+    sprintf(buf, "%s misc popen", name);
+    pipe = _popen(buf, "r");
+    ok(pipe != NULL, "_popen failed with error: %d\n", errno);
+
+    fgets(buf, sizeof(buf), pipe);
+    ok(!strcmp(buf, "child output\n"), "buf = %s\n", buf);
+
+    ret = _pclose(pipe);
+    ok(ret == 0x37, "_pclose returned %x, expected 0x37\n", ret);
+
+    errno = 0xdeadbeef;
+    ret = _pclose((FILE*)0xdeadbeef);
+    ok(ret == -1, "_pclose returned %x, expected -1\n", ret);
+    if(p_set_errno)
+        ok(errno == EBADF, "errno = %d\n", errno);
+}
+
 START_TEST(misc)
 {
+    int arg_c;
+    char** arg_v;
+
     init();
 
+    arg_c = winetest_get_mainargs(&arg_v);
+    if(arg_c >= 3) {
+        if(!strcmp(arg_v[2], "popen"))
+            test__popen_child();
+        else
+            ok(0, "invalid argument '%s'\n", arg_v[2]);
+
+        return;
+    }
+
     test_rand_s();
     test_I10_OUTPUT();
     test_strerror_s();
@@ -320,4 +365,5 @@ START_TEST(misc)
     test__get_errno();
     test__set_doserrno();
     test__set_errno();
+    test__popen(arg_v[0]);
 }
diff --git a/rostests/winetests/msvcrt/msvcrt_test.dsp b/rostests/winetests/msvcrt/msvcrt_test.dsp
deleted file mode 100644 (file)
index 1e27830..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-# Microsoft Developer Studio Project File - Name="msvcrt_test" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
-\r
-CFG=msvcrt_test - Win32 Wine Headers\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "msvcrt_test.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "msvcrt_test.mak" CFG="msvcrt_test - Win32 Wine Headers"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "msvcrt_test - Win32 MSVC Headers" (based on "Win32 (x86) Console Application")\r
-!MESSAGE "msvcrt_test - Win32 Wine Headers" (based on "Win32 (x86) Console Application")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-!IF  "$(CFG)" == "msvcrt_test - Win32 MSVC Headers"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Output\Win32_MSVC_Headers"\r
-# PROP BASE Intermediate_Dir "Output\Win32_MSVC_Headers"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Output\Win32_MSVC_Headers"\r
-# PROP Intermediate_Dir "Output\Win32_MSVC_Headers"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ  /c\r
-# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ..\..\..\Output\\Win32_MSVC_Headers /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_MSVCRT_TEST_" /D "__WINE_USE_NATIVE_HEADERS" /D __WINETEST_OUTPUT_DIR=\"Output\\Win32_MSVC_Headers\" /D "__i386__" /D "_X86_" /D inline=__inline /FR /FD /GZ /c\r
-# ADD BASE RSC /l 0x41d /d "_DEBUG"\r
-# ADD RSC /l 0x41d /i "..\..\..\Output\\Win32_MSVC_Headers" /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-\r
-!ELSEIF  "$(CFG)" == "msvcrt_test - Win32 Wine Headers"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Output\Win32_Wine_Headers"\r
-# PROP BASE Intermediate_Dir "Output\Win32_Wine_Headers"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Output\Win32_Wine_Headers"\r
-# PROP Intermediate_Dir "Output\Win32_Wine_Headers"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ  /c\r
-# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ..\..\..\Output\\Win32_Wine_Headers /I ..\..\..\include /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_MSVCRT_TEST_" /D __WINETEST_OUTPUT_DIR=\"Output\\Win32_Wine_Headers\" /D "__i386__" /D "_X86_" /D inline=__inline /FR /FD /GZ /c\r
-# ADD BASE RSC /l 0x41d /d "_DEBUG"\r
-# ADD RSC /l 0x41d /i "..\..\..\Output\\Win32_Wine_Headers" /i "..\..\..\include" /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "msvcrt_test - Win32 MSVC Headers"\r
-# Name "msvcrt_test - Win32 Wine Headers"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\cpp.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\\\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\testlist.c\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# End Group\r
-# End Target\r
-# End Project\r
index 1507a01..829b2e0 100644 (file)
@@ -27,6 +27,7 @@
  
 #include <stdio.h>
 #include <errno.h>
+#include <math.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -44,6 +45,7 @@ static int (__cdecl *p__ecvt_s)(char *buffer, size_t length, double number,
 static int (__cdecl *p__fcvt_s)(char *buffer, size_t length, double number,
                                 int ndigits, int *decpt, int *sign);
 static unsigned int (__cdecl *p__get_output_format)(void);
+static unsigned int (__cdecl *p__set_output_format)(unsigned int);
 static int (__cdecl *p__vsprintf_p)(char*, size_t, const char*, __ms_va_list);
 static int (__cdecl *p_vswprintf)(wchar_t *str, const wchar_t *format, __ms_va_list valist);
 static int (__cdecl *p__vswprintf)(wchar_t *str, const wchar_t *format, __ms_va_list valist);
@@ -66,6 +68,7 @@ static void init( void )
     p__ecvt_s = (void *)GetProcAddress(hmod, "_ecvt_s");
     p__fcvt_s = (void *)GetProcAddress(hmod, "_fcvt_s");
     p__get_output_format = (void *)GetProcAddress(hmod, "_get_output_format");
+    p__set_output_format = (void *)GetProcAddress(hmod, "_set_output_format");
     p__vsprintf_p = (void*)GetProcAddress(hmod, "_vsprintf_p");
     p_vswprintf = (void*)GetProcAddress(hmod, "vswprintf");
     p__vswprintf = (void*)GetProcAddress(hmod, "_vswprintf");
@@ -79,7 +82,7 @@ static void test_sprintf( void )
 {
     char buffer[100];
     const char *format;
-    double pnumber=789456123;
+    double pnumber=789456123, inf, nan;
     int x, r;
     WCHAR wide[] = { 'w','i','d','e',0};
 
@@ -326,18 +329,52 @@ static void test_sprintf( void )
     format = "%#012x";
     r = sprintf(buffer,format,1);
     ok(!strcmp(buffer,"0x0000000001"),"Hexadecimal zero-padded \"%s\"\n",buffer);
+    ok( r==12, "return count wrong\n");
+
+    r = sprintf(buffer,format,0);
+    ok(!strcmp(buffer,"000000000000"),"Hexadecimal zero-padded \"%s\"\n",buffer);
+    ok( r==12, "return count wrong\n");
 
     format = "%#04.8x";
     r = sprintf(buffer,format,1);
     ok(!strcmp(buffer,"0x00000001"), "Hexadecimal zero-padded precision \"%s\"\n",buffer);
+    ok( r==10, "return count wrong\n");
+
+    r = sprintf(buffer,format,0);
+    ok(!strcmp(buffer,"00000000"), "Hexadecimal zero-padded precision \"%s\"\n",buffer);
+    ok( r==8, "return count wrong\n");
 
     format = "%#-08.2x";
     r = sprintf(buffer,format,1);
     ok(!strcmp(buffer,"0x01    "), "Hexadecimal zero-padded not left-adjusted \"%s\"\n",buffer);
+    ok( r==8, "return count wrong\n");
+
+    r = sprintf(buffer,format,0);
+    ok(!strcmp(buffer,"00      "), "Hexadecimal zero-padded not left-adjusted \"%s\"\n",buffer);
+    ok( r==8, "return count wrong\n");
+
+    format = "%#.0x";
+    r = sprintf(buffer,format,1);
+    ok(!strcmp(buffer,"0x1"), "Hexadecimal zero-padded zero-precision \"%s\"\n",buffer);
+    ok( r==3, "return count wrong\n");
+
+    r = sprintf(buffer,format,0);
+    ok(!strcmp(buffer,""), "Hexadecimal zero-padded zero-precision \"%s\"\n",buffer);
+    ok( r==0, "return count wrong\n");
 
     format = "%#08o";
     r = sprintf(buffer,format,1);
     ok(!strcmp(buffer,"00000001"), "Octal zero-padded \"%s\"\n",buffer);
+    ok( r==8, "return count wrong\n");
+
+    format = "%#o";
+    r = sprintf(buffer,format,1);
+    ok(!strcmp(buffer,"01"), "Octal zero-padded \"%s\"\n",buffer);
+    ok( r==2, "return count wrong\n");
+
+    r = sprintf(buffer,format,0);
+    ok(!strcmp(buffer,"0"), "Octal zero-padded \"%s\"\n",buffer);
+    ok( r==1, "return count wrong\n");
 
     if (sizeof(void *) == 8)
     {
@@ -515,6 +552,26 @@ static void test_sprintf( void )
     ok(!strcmp(buffer,"8.6000e+000"), "failed\n");
     ok( r==11, "return count wrong\n");
 
+    format = "% 2.4e";
+    r = sprintf(buffer, format,8.6);
+    ok(!strcmp(buffer," 8.6000e+000"), "failed: %s\n", buffer);
+    ok( r==12, "return count wrong\n");
+
+    format = "% 014.4e";
+    r = sprintf(buffer, format,8.6);
+    ok(!strcmp(buffer," 008.6000e+000"), "failed: %s\n", buffer);
+    ok( r==14, "return count wrong\n");
+
+    format = "% 2.4e";
+    r = sprintf(buffer, format,-8.6);
+    ok(!strcmp(buffer,"-8.6000e+000"), "failed: %s\n", buffer);
+    ok( r==12, "return count wrong\n");
+
+    format = "%+2.4e";
+    r = sprintf(buffer, format,8.6);
+    ok(!strcmp(buffer,"+8.6000e+000"), "failed: %s\n", buffer);
+    ok( r==12, "return count wrong\n");
+
     format = "%2.4g";
     r = sprintf(buffer, format,8.6);
     ok(!strcmp(buffer,"8.6"), "failed\n");
@@ -617,6 +674,41 @@ static void test_sprintf( void )
     ok(!strcmp(buffer,"123"), "failed: \"%s\"\n", buffer);
     r = sprintf(buffer, format, 0x12345);
     ok(!strcmp(buffer,"2345"), "failed \"%s\"\n", buffer);
+
+    nan = 0.0;
+    inf = 1.0/nan;
+    nan = sqrt(-1);
+    format = "%lf";
+    r = sprintf(buffer, format, nan);
+    ok(r==9, "r = %d\n", r);
+    ok(!strcmp(buffer, "-1.#IND00"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==8, "r = %d\n", r);
+    ok(!strcmp(buffer, "1.#INF00"), "failed: \"%s\"\n", buffer);
+
+    format = "%le";
+    r = sprintf(buffer, format, nan);
+    ok(r==14, "r = %d\n", r);
+    ok(!strcmp(buffer, "-1.#IND00e+000"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==13, "r = %d\n", r);
+    ok(!strcmp(buffer, "1.#INF00e+000"), "failed: \"%s\"\n", buffer);
+
+    format = "%lg";
+    r = sprintf(buffer, format, nan);
+    ok(r==7, "r = %d\n", r);
+    ok(!strcmp(buffer, "-1.#IND"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==6, "r = %d\n", r);
+    ok(!strcmp(buffer, "1.#INF"), "failed: \"%s\"\n", buffer);
+
+    format = "%010.2lf";
+    r = sprintf(buffer, format, nan);
+    ok(r==10, "r = %d\n", r);
+    ok(!strcmp(buffer, "-000001.#J"), "failed: \"%s\"\n", buffer);
+    r = sprintf(buffer, format, inf);
+    ok(r==10, "r = %d\n", r);
+    ok(!strcmp(buffer, "0000001.#J"), "failed: \"%s\"\n", buffer);
 }
 
 static void test_swprintf( void )
@@ -671,7 +763,9 @@ static void test_snprintf (void)
 
 static void test_fprintf(void)
 {
-    static char file_name[] = "fprintf.tst";
+    static const char file_name[] = "fprintf.tst";
+    static const WCHAR utf16_test[] = {'u','n','i','c','o','d','e','\n',0};
+
     FILE *fp = fopen(file_name, "wb");
     char buf[1024];
     int ret;
@@ -686,6 +780,11 @@ static void test_fprintf(void)
     ret = ftell(fp);
     ok(ret == 26, "ftell returned %d\n", ret);
 
+    ret = fwprintf(fp, utf16_test);
+    ok(ret == 8, "ret = %d\n", ret);
+    ret = ftell(fp);
+    ok(ret == 42, "ftell returned %d\n", ret);
+
     fclose(fp);
 
     fp = fopen(file_name, "rb");
@@ -700,6 +799,51 @@ static void test_fprintf(void)
     ok(ret == 26, "ret = %d\n", ret);
     ok(!memcmp(buf, "contains\0null\n", 14), "buf = %s\n", buf);
 
+    memset(buf, 0, sizeof(buf));
+    fgets(buf, sizeof(buf), fp);
+    ret = ftell(fp);
+    ok(ret == 41, "ret =  %d\n", ret);
+    ok(!memcmp(buf, utf16_test, sizeof(utf16_test)),
+            "buf = %s\n", wine_dbgstr_w((WCHAR*)buf));
+
+    fclose(fp);
+
+    fp = fopen(file_name, "wt");
+
+    ret = fprintf(fp, "simple test\n");
+    ok(ret == 12, "ret = %d\n", ret);
+    ret = ftell(fp);
+    ok(ret == 13, "ftell returned %d\n", ret);
+
+    ret = fprintf(fp, "contains%cnull\n", '\0');
+    ok(ret == 14, "ret = %d\n", ret);
+    ret = ftell(fp);
+    ok(ret == 28, "ftell returned %d\n", ret);
+
+    ret = fwprintf(fp, utf16_test);
+    ok(ret == 8, "ret = %d\n", ret);
+    ret = ftell(fp);
+    ok(ret == 37, "ftell returned %d\n", ret);
+
+    fclose(fp);
+
+    fp = fopen(file_name, "rb");
+    ret = fscanf(fp, "%[^\n] ", buf);
+    ok(ret == 1, "ret = %d\n", ret);
+    ret = ftell(fp);
+    ok(ret == 13, "ftell returned %d\n", ret);
+    ok(!strcmp(buf, "simple test\r"), "buf = %s\n", buf);
+
+    fgets(buf, sizeof(buf), fp);
+    ret = ftell(fp);
+    ok(ret == 28, "ret = %d\n", ret);
+    ok(!memcmp(buf, "contains\0null\r\n", 15), "buf = %s\n", buf);
+
+    fgets(buf, sizeof(buf), fp);
+    ret = ftell(fp);
+    ok(ret == 37, "ret =  %d\n", ret);
+    ok(!strcmp(buf, "unicode\r\n"), "buf = %s\n", buf);
+
     fclose(fp);
     unlink(file_name);
 }
@@ -1244,15 +1388,34 @@ static void test_vsprintf_p(void)
 static void test__get_output_format(void)
 {
     unsigned int ret;
+    char buf[64];
+    int c;
 
-    if (!p__get_output_format)
+    if (!p__get_output_format || !p__set_output_format)
     {
-        win_skip("_get_output_format not available\n");
+        win_skip("_get_output_format or _set_output_format is not available\n");
         return;
     }
 
     ret = p__get_output_format();
     ok(ret == 0, "got %d\n", ret);
+
+    c = sprintf(buf, "%E", 1.23);
+    ok(c == 13, "c = %d\n", c);
+    ok(!strcmp(buf, "1.230000E+000"), "buf = %s\n", buf);
+
+    ret = p__set_output_format(_TWO_DIGIT_EXPONENT);
+    ok(ret == 0, "got %d\n", ret);
+
+    c = sprintf(buf, "%E", 1.23);
+    ok(c == 12, "c = %d\n", c);
+    ok(!strcmp(buf, "1.230000E+00"), "buf = %s\n", buf);
+
+    ret = p__get_output_format();
+    ok(ret == _TWO_DIGIT_EXPONENT, "got %d\n", ret);
+
+    ret = p__set_output_format(_TWO_DIGIT_EXPONENT);
+    ok(ret == _TWO_DIGIT_EXPONENT, "got %d\n", ret);
 }
 
 START_TEST(printf)
index b09e7df..97b8074 100644 (file)
@@ -131,6 +131,13 @@ static void test_sscanf( void )
     ok( ret == 1, "Error with format \"%s\"\n","%*[a-cd-dg-e]%c");
     ok( buffer[0] == 'h', "Error with \"abcefgdh\" \"%c\"\n", buffer[0]);
 
+    buffer1[0] = 'b';
+    ret = sscanf("a","%s%s", buffer, buffer1);
+    ok( ret == 1, "expected 1, got %u\n", ret);
+    ok( buffer[0] == 'a', "buffer[0] = '%c'\n", buffer[0]);
+    ok( buffer[1] == '\0', "buffer[1] = '%c'\n", buffer[1]);
+    ok( buffer1[0] == 'b', "buffer1[0] = '%c'\n", buffer1[0]);
+
     /* check digits */
     ret = sprintf(buffer,"%d:%d:%d",hour,min,sec);
     ok( ret == 8, "expected 8, got %u\n", ret);
index d33498b..ad6ea6e 100644 (file)
@@ -26,6 +26,13 @@ static int test_value = 0;
 
 static void __cdecl sighandler(int signum)
 {
+    void **ret = __pxcptinfoptrs();
+
+    ok(ret != NULL, "ret = NULL\n");
+    if(signum == SIGABRT)
+        ok(*ret == (void*)0xdeadbeef, "*ret = %p\n", *ret);
+    else if(signum == SIGSEGV)
+        ok(*ret == NULL, "*ret = %p\n", *ret);
     ++test_value;
 }
 
@@ -42,7 +49,32 @@ static void test_signal(void)
     ok(test_value == 1, "SIGBREAK handler not invoked\n");
 }
 
+static void test___pxcptinfoptrs(void)
+{
+    void **ret = __pxcptinfoptrs();
+    int res;
+
+    ok(ret != NULL, "ret == NULL\n");
+    ok(*ret == NULL, "*ret != NULL\n");
+
+    test_value = 0;
+
+    *ret = (void*)0xdeadbeef;
+    signal(SIGSEGV, sighandler);
+    res = raise(SIGSEGV);
+    ok(res == 0, "failed to raise SIGSEGV\n");
+    ok(*ret == (void*)0xdeadbeef, "*ret = %p\n", *ret);
+
+    signal(SIGABRT, sighandler);
+    res = raise(SIGABRT);
+    ok(res == 0, "failed to raise SIGBREAK\n");
+    ok(*ret == (void*)0xdeadbeef, "*ret = %p\n", *ret);
+
+    ok(test_value == 2, "test_value = %d\n", test_value);
+}
+
 START_TEST(signal)
 {
     test_signal();
+    test___pxcptinfoptrs();
 }
index d606ebb..7d820e1 100644 (file)
@@ -19,8 +19,6 @@
  */
 
 #include "wine/test.h"
-#include "winbase.h"
-#include "winnls.h"
 #include <string.h>
 #include <mbstring.h>
 #include <wchar.h>
 #include <locale.h>
 #include <errno.h>
 #include <limits.h>
+#include <math.h>
+
+/* make it use a definition from string.h */
+#undef strncpy
+#include "winbase.h"
+#include "winnls.h"
 
 static char *buf_to_string(const unsigned char *bin, int len, int nr)
 {
@@ -70,6 +74,8 @@ static int (__cdecl *p_wcsupr_s)(wchar_t *str, size_t size);
 static size_t (__cdecl *p_strnlen)(const char *, size_t);
 static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
+static __int64 (__cdecl *p_wcstoi64)(const wchar_t *, wchar_t **, int);
+static unsigned __int64 (__cdecl *p_wcstoui64)(const wchar_t *, wchar_t **, int);
 static int (__cdecl *pwcstombs_s)(size_t*,char*,size_t,const wchar_t*,size_t);
 static int (__cdecl *pmbstowcs_s)(size_t*,wchar_t*,size_t,const char*,size_t);
 static size_t (__cdecl *p_mbsrtowcs)(wchar_t*, const char**, size_t, mbstate_t*);
@@ -89,6 +95,7 @@ static size_t (__cdecl *p_wcrtomb)(char*, wchar_t, mbstate_t*);
 static int (__cdecl *p_tolower)(int);
 static size_t (__cdecl *p_mbrlen)(const char*, size_t, mbstate_t*);
 static size_t (__cdecl *p_mbrtowc)(wchar_t*, const char*, size_t, mbstate_t*);
+static int (__cdecl *p__atodbl_l)(_CRT_DOUBLE*,char*,_locale_t);
 
 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
@@ -428,9 +435,7 @@ static void test_mbcp(void)
     expect_eq(_ismbblead(0x84), 1, int, "%d");
     expect_eq(_ismbblead(0xd3), 1, int, "%d");
     expect_eq(_ismbblead(0xd7), 0, int, "%d");
-    todo_wine {
-      expect_eq(_ismbblead(0xd8), 1, int, "%d");
-    }
+    expect_eq(_ismbblead(0xd8), 1, int, "%d");
     expect_eq(_ismbblead(0xd9), 1, int, "%d");
 
     expect_eq(_ismbbtrail(0x30), 0, int, "%d");
@@ -806,23 +811,33 @@ static void test_wcscpy_s(void)
         return;
     }
 
+    if (p_set_invalid_parameter_handler)
+        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
+            "Invalid parameter handler was already set\n");
+
     /* Test NULL Dest */
+    errno = EBADF;
     ret = p_wcscpy_s(NULL, 18, szLongText);
     ok(ret == EINVAL, "p_wcscpy_s expect EINVAL got %d\n", ret);
+    ok(errno == EINVAL, "expected errno EINVAL got %d\n", errno);
 
     /* Test NULL Source */
+    errno = EBADF;
     szDest[0] = 'A';
     ret = p_wcscpy_s(szDest, 18, NULL);
     ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
-    ok(szDest[0] == 0, "szDest[0] not 0\n");
+    ok(errno == EINVAL, "expected errno EINVAL got %d\n", errno);
+    ok(szDest[0] == 0, "szDest[0] not 0, got %c\n", szDest[0]);
 
     /* Test invalid size */
+    errno = EBADF;
     szDest[0] = 'A';
     ret = p_wcscpy_s(szDest, 0, szLongText);
     /* Later versions changed the return value for this case to EINVAL,
      * and don't modify the result if the dest size is 0.
      */
     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
+    ok(errno == ERANGE || errno == EINVAL, "expected errno ERANGE/EINVAL got %d\n", errno);
     ok(szDest[0] == 0 || ret == EINVAL, "szDest[0] not 0\n");
 
     /* Copy same buffer size */
@@ -831,14 +846,20 @@ static void test_wcscpy_s(void)
     ok(lstrcmpW(szDest, szLongText) == 0, "szDest != szLongText\n");
 
     /* Copy smaller buffer size */
+    errno = EBADF;
     szDest[0] = 'A';
     ret = p_wcscpy_s(szDestShort, 8, szLongText);
     ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
+    ok(errno == ERANGE || errno == EINVAL, "expected errno ERANGE/EINVAL got %d\n", errno);
     ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
 
     if(!p_wcsncpy_s)
     {
         win_skip("wcsncpy_s not found\n");
+
+        if (p_set_invalid_parameter_handler)
+            ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
+                    "Cannot reset invalid parameter handler\n");
         return;
     }
 
@@ -884,6 +905,10 @@ static void test_wcscpy_s(void)
     ok(ret == STRUNCATE, "expected ERROR_SUCCESS got %d\n", ret);
     ok(szDestShort[0]=='1' && szDestShort[1]=='1' && szDestShort[2]=='1' && szDestShort[3]=='1',
             "szDestShort = %s\n", wine_dbgstr_w(szDestShort));
+
+    if (p_set_invalid_parameter_handler)
+        ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
+                "Cannot reset invalid parameter handler\n");
 }
 
 static void test__wcsupr_s(void)
@@ -1319,6 +1344,26 @@ static void test_strtol(void)
     ul = strtoul("9223372036854775807L", &e, 0);
     ok(ul==4294967295ul, "wrong value %u\n", ul);
     ok(errno == ERANGE, "wrong errno %d\n", errno);
+
+    errno = 0;
+    ul = strtoul("-2", NULL, 0);
+    ok(ul == -2, "wrong value %u\n", ul);
+    ok(errno == 0, "wrong errno %d\n", errno);
+
+    errno = 0;
+    ul = strtoul("-4294967294", NULL, 0);
+    ok(ul == 2, "wrong value %u\n", ul);
+    ok(errno == 0, "wrong errno %d\n", errno);
+
+    errno = 0;
+    ul = strtoul("-4294967295", NULL, 0);
+    ok(ul==1, "wrong value %u\n", ul);
+    ok(errno == 0, "wrong errno %d\n", errno);
+
+    errno = 0;
+    ul = strtoul("-4294967296", NULL, 0);
+    ok(ul == 1, "wrong value %u\n", ul);
+    ok(errno == ERANGE, "wrong errno %d\n", errno);
 }
 
 static void test_strnlen(void)
@@ -1590,6 +1635,14 @@ static void test_mbstowcs(void)
     wOut[4] = '!'; wOut[5] = '\0';
     mOut[4] = '!'; mOut[5] = '\0';
 
+    if(pmbstowcs_s) {
+        /* crashes on some systems */
+        errno = 0xdeadbeef;
+        ret = mbstowcs(wOut, NULL, 4);
+        ok(ret == -1, "mbstowcs did not return -1\n");
+        ok(errno == EINVAL, "errno = %d\n", errno);
+    }
+
     ret = mbstowcs(NULL, mSimple, 0);
     ok(ret == 4, "mbstowcs did not return 4\n");
 
@@ -1840,6 +1893,11 @@ static void test__itoa_s(void)
     ok(!strcmp(buffer, "-12345678"),
        "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
        buffer);
+
+    itoa(100, buffer, 100);
+    ok(!strcmp(buffer, "10"),
+            "Expected output buffer string to be \"10\", got \"%s\"\n", buffer);
+
     if (p_set_invalid_parameter_handler)
         ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
                 "Cannot reset invalid parameter handler\n");
@@ -2189,6 +2247,24 @@ static void test__mbslwr_s(void)
        buffer);
 }
 
+static void test__mbstok(void)
+{
+    const unsigned char delim[] = "t";
+
+    char str[] = "!.!test";
+    unsigned char *ret;
+
+    strtok(str, "!");
+
+    ret = _mbstok(NULL, delim);
+    /* most versions of msvcrt use the same buffer for strtok and _mbstok */
+    ok(!ret || broken((char*)ret==str+4),
+            "_mbstok(NULL, \"t\") = %p, expected NULL (%p)\n", ret, str);
+
+    ret = _mbstok(NULL, delim);
+    ok(!ret, "_mbstok(NULL, \"t\") = %p, expected NULL\n", ret);
+}
+
 static void test__ultoa_s(void)
 {
     errno_t ret;
@@ -2336,36 +2412,66 @@ static void test_wctomb(void)
 
     ret = p_wcrtomb((char*)dst, 0xffff, NULL);
     ok(ret == -1, "wcrtomb did not return -1\n");
-    ok(dst[0] == 0x3f, "dst[0] = %x, expected 0x20\n", dst[0]);
+    ok(dst[0] == 0x3f, "dst[0] = %x, expected 0x3f\n", dst[0]);
 
     setlocale(LC_ALL, "C");
 }
 
 static void test_tolower(void)
 {
-    int ret;
+    char ch, lch;
+    int ret, len;
 
+    /* test C locale when locale was never changed */
     ret = p_tolower(0x41);
     ok(ret == 0x61, "ret = %x\n", ret);
 
     ret = p_tolower(0xF4);
     ok(ret == 0xF4, "ret = %x\n", ret);
 
+    errno = 0xdeadbeef;
     ret = p_tolower((char)0xF4);
-    ok(ret==0xF4/*Vista+*/ || ret==(char)0xF4, "ret = %x\n", ret);
+    todo_wine ok(ret == (char)0xF4, "ret = %x\n", ret);
+    todo_wine ok(errno == 0xdeadbeef, "errno = %d\n", errno);
 
-    /* is it using different locale (CP_ACP) for negative values?? */
-    /* current implementation matches msvcr90 behaviour */
+    errno = 0xdeadbeef;
     ret = p_tolower((char)0xD0);
-    todo_wine ok(ret==0xF0/*Vista+*/ || ret==(char)0xD0, "ret = %x\n", ret);
-
-    ret = p_tolower(0xD0);
-    ok(ret == 0xD0, "ret = %x\n", ret);
+    todo_wine ok(ret == (char)0xD0, "ret = %x\n", ret);
+    todo_wine ok(errno == 0xdeadbeef, "errno = %d\n", errno);
 
+    /* test C locale after setting locale */
     if(!setlocale(LC_ALL, "us")) {
         win_skip("skipping tolower tests that depends on locale\n");
         return;
     }
+    setlocale(LC_ALL, "C");
+
+    ch = 0xF4;
+    errno = 0xdeadbeef;
+    ret = p_tolower(ch);
+    len = LCMapStringA(0, LCMAP_LOWERCASE, &ch, 1, &lch, 1);
+    if(len)
+        ok(ret==(unsigned char)lch || broken(ret==ch)/*WinXP-*/, "ret = %x\n", ret);
+    else
+        ok(ret == ch, "ret = %x\n", ret);
+    if(!len || ret==(unsigned char)lch)
+        ok(errno == EILSEQ, "errno = %d\n", errno);
+
+    ch = 0xD0;
+    errno = 0xdeadbeef;
+    ret = p_tolower(ch);
+    len = LCMapStringA(0, LCMAP_LOWERCASE, &ch, 1, &lch, 1);
+    if(len)
+        ok(ret==(unsigned char)lch || broken(ret==ch)/*WinXP-*/, "ret = %x\n", ret);
+    else
+        ok(ret == ch, "ret = %x\n", ret);
+    if(!len || ret==(unsigned char)lch)
+        ok(errno == EILSEQ, "errno = %d\n", errno);
+
+    ret = p_tolower(0xD0);
+    ok(ret == 0xD0, "ret = %x\n", ret);
+
+    ok(setlocale(LC_ALL, "us") != NULL, "setlocale failed\n");
 
     ret = p_tolower((char)0xD0);
     ok(ret == 0xF0, "ret = %x\n", ret);
@@ -2376,6 +2482,194 @@ static void test_tolower(void)
     setlocale(LC_ALL, "C");
 }
 
+static void test__atodbl(void)
+{
+    _CRT_DOUBLE d;
+    char num[32];
+    int ret;
+
+    if(!p__atodbl_l) {
+        /* Old versions of msvcrt use different values for _OVERFLOW and _UNDERFLOW
+         * Because of this lets skip _atodbl tests when _atodbl_l is not available */
+        win_skip("_atodbl_l is not available\n");
+        return;
+    }
+
+    num[0] = 0;
+    ret = p__atodbl_l(&d, num, NULL);
+    ok(ret == 0, "_atodbl_l(&d, \"\", NULL) returned %d, expected 0\n", ret);
+    ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
+    ret = _atodbl(&d, num);
+    ok(ret == 0, "_atodbl(&d, \"\") returned %d, expected 0\n", ret);
+    ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
+
+    strcpy(num, "t");
+    ret = p__atodbl_l(&d, num, NULL);
+    ok(ret == 0, "_atodbl_l(&d, \"t\", NULL) returned %d, expected 0\n", ret);
+    ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
+    ret = _atodbl(&d, num);
+    ok(ret == 0, "_atodbl(&d, \"t\") returned %d, expected 0\n", ret);
+    ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
+
+    strcpy(num, "0");
+    ret = p__atodbl_l(&d, num, NULL);
+    ok(ret == 0, "_atodbl_l(&d, \"0\", NULL) returned %d, expected 0\n", ret);
+    ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
+    ret = _atodbl(&d, num);
+    ok(ret == 0, "_atodbl(&d, \"0\") returned %d, expected 0\n", ret);
+    ok(d.x == 0, "d.x = %lf, expected 0\n", d.x);
+
+    strcpy(num, "123");
+    ret = p__atodbl_l(&d, num, NULL);
+    ok(ret == 0, "_atodbl_l(&d, \"123\", NULL) returned %d, expected 0\n", ret);
+    ok(d.x == 123, "d.x = %lf, expected 123\n", d.x);
+    ret = _atodbl(&d, num);
+    ok(ret == 0, "_atodbl(&d, \"123\") returned %d, expected 0\n", ret);
+    ok(d.x == 123, "d.x = %lf, expected 123\n", d.x);
+
+    strcpy(num, "1e-309");
+    ret = p__atodbl_l(&d, num, NULL);
+    ok(ret == _UNDERFLOW, "_atodbl_l(&d, \"1e-309\", NULL) returned %d, expected _UNDERFLOW\n", ret);
+    ok(d.x!=0 && almost_equal(d.x, 0), "d.x = %le, expected 0\n", d.x);
+    ret = _atodbl(&d, num);
+    ok(ret == _UNDERFLOW, "_atodbl(&d, \"1e-309\") returned %d, expected _UNDERFLOW\n", ret);
+    ok(d.x!=0 && almost_equal(d.x, 0), "d.x = %le, expected 0\n", d.x);
+
+    strcpy(num, "1e309");
+    ret = p__atodbl_l(&d, num, NULL);
+    ok(ret == _OVERFLOW, "_atodbl_l(&d, \"1e309\", NULL) returned %d, expected _OVERFLOW\n", ret);
+    ret = _atodbl(&d, num);
+    ok(ret == _OVERFLOW, "_atodbl(&d, \"1e309\") returned %d, expected _OVERFLOW\n", ret);
+}
+
+static void test__stricmp(void)
+{
+    int ret;
+
+    ret = _stricmp("test", "test");
+    ok(ret == 0, "_stricmp returned %d\n", ret);
+    ret = _stricmp("a", "z");
+    ok(ret < 0, "_stricmp returned %d\n", ret);
+    ret = _stricmp("z", "a");
+    ok(ret > 0, "_stricmp returned %d\n", ret);
+    ret = _stricmp("\xa5", "\xb9");
+    ok(ret < 0, "_stricmp returned %d\n", ret);
+
+    if(!setlocale(LC_ALL, "polish")) {
+        win_skip("stricmp tests\n");
+        return;
+    }
+
+    ret = _stricmp("test", "test");
+    ok(ret == 0, "_stricmp returned %d\n", ret);
+    ret = _stricmp("a", "z");
+    ok(ret < 0, "_stricmp returned %d\n", ret);
+    ret = _stricmp("z", "a");
+    ok(ret > 0, "_stricmp returned %d\n", ret);
+    ret = _stricmp("\xa5", "\xb9");
+    ok(ret == 0, "_stricmp returned %d\n", ret);
+
+    setlocale(LC_ALL, "C");
+}
+
+static void test__wcstoi64(void)
+{
+    static const WCHAR digit[] = { '9', 0 };
+    static const WCHAR stock[] = { 0x3231, 0 }; /* PARENTHESIZED IDEOGRAPH STOCK */
+    static const WCHAR tamil[] = { 0x0bef, 0 }; /* TAMIL DIGIT NINE */
+    static const WCHAR thai[]  = { 0x0e59, 0 }; /* THAI DIGIT NINE */
+    static const WCHAR fullwidth[] = { 0xff19, 0 }; /* FULLWIDTH DIGIT NINE */
+    static const WCHAR hex[] = { 0xff19, 'f', 0x0e59, 0xff46, 0 };
+
+    __int64 res;
+    unsigned __int64 ures;
+    WCHAR *endpos;
+
+    if (!p_wcstoi64 || !p_wcstoui64) {
+        win_skip("_wcstoi64 or _wcstoui64 not found\n");
+        return;
+    }
+
+    res = p_wcstoi64(digit, NULL, 10);
+    ok(res == 9, "res != 9\n");
+    res = p_wcstoi64(stock, &endpos, 10);
+    ok(res == 0, "res != 0\n");
+    ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos);
+    res = p_wcstoi64(tamil, &endpos, 10);
+    ok(res == 0, "res != 0\n");
+    ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos);
+    res = p_wcstoi64(thai, NULL, 10);
+    todo_wine ok(res == 9, "res != 9\n");
+    res = p_wcstoi64(fullwidth, NULL, 10);
+    todo_wine ok(res == 9, "res != 9\n");
+    res = p_wcstoi64(hex, NULL, 16);
+    todo_wine ok(res == 0x9f9, "res != 0x9f9\n");
+
+    ures = p_wcstoui64(digit, NULL, 10);
+    ok(ures == 9, "ures != 9\n");
+    ures = p_wcstoui64(stock, &endpos, 10);
+    ok(ures == 0, "ures != 0\n");
+    ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos);
+    ures = p_wcstoui64(tamil, &endpos, 10);
+    ok(ures == 0, "ures != 0\n");
+    ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos);
+    ures = p_wcstoui64(thai, NULL, 10);
+    todo_wine ok(ures == 9, "ures != 9\n");
+    ures = p_wcstoui64(fullwidth, NULL, 10);
+    todo_wine ok(ures == 9, "ures != 9\n");
+    ures = p_wcstoui64(hex, NULL, 16);
+    todo_wine ok(ures == 0x9f9, "ures != 0x9f9\n");
+
+    return;
+}
+
+static void test_atoi(void)
+{
+    int r;
+
+    r = atoi("0");
+    ok(r == 0, "atoi(0) = %d\n", r);
+
+    r = atoi("-1");
+    ok(r == -1, "atoi(-1) = %d\n", r);
+
+    r = atoi("1");
+    ok(r == 1, "atoi(1) = %d\n", r);
+
+    r = atoi("4294967296");
+    ok(r == 0, "atoi(4294967296) = %d\n", r);
+}
+
+static void test_strncpy(void)
+{
+#define TEST_STRNCPY_LEN 10
+    char *ret;
+    char dst[TEST_STRNCPY_LEN + 1];
+    char not_null_terminated[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
+
+    /* strlen(src) > TEST_STRNCPY_LEN */
+    ret = strncpy(dst, "01234567890123456789", TEST_STRNCPY_LEN);
+    ok(ret == dst, "ret != dst\n");
+    ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
+
+    /* without null-terminated */
+    ret = strncpy(dst, not_null_terminated, TEST_STRNCPY_LEN);
+    ok(ret == dst, "ret != dst\n");
+    ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
+
+    /* strlen(src) < TEST_STRNCPY_LEN */
+    strcpy(dst, "0123456789");
+    ret = strncpy(dst, "012345", TEST_STRNCPY_LEN);
+    ok(ret == dst, "ret != dst\n");
+    ok(!strcmp(dst, "012345"), "dst != 012345\n");
+    ok(dst[TEST_STRNCPY_LEN - 1] == '\0', "dst[TEST_STRNCPY_LEN - 1] != 0\n");
+
+    /* strlen(src) == TEST_STRNCPY_LEN */
+    ret = strncpy(dst, "0123456789", TEST_STRNCPY_LEN);
+    ok(ret == dst, "ret != dst\n");
+    ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n");
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -2403,6 +2697,8 @@ START_TEST(string)
     p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" );
     p_strtoi64 = (void *)GetProcAddress(hMsvcrt, "_strtoi64");
     p_strtoui64 = (void *)GetProcAddress(hMsvcrt, "_strtoui64");
+    p_wcstoi64 = (void *)GetProcAddress(hMsvcrt, "_wcstoi64");
+    p_wcstoui64 = (void *)GetProcAddress(hMsvcrt, "_wcstoui64");
     pmbstowcs_s = (void *)GetProcAddress(hMsvcrt, "mbstowcs_s");
     pwcstombs_s = (void *)GetProcAddress(hMsvcrt, "wcstombs_s");
     pwcsrtombs = (void *)GetProcAddress(hMsvcrt, "wcsrtombs");
@@ -2420,6 +2716,7 @@ START_TEST(string)
     p_mbrlen = (void*)GetProcAddress(hMsvcrt, "mbrlen");
     p_mbrtowc = (void*)GetProcAddress(hMsvcrt, "mbrtowc");
     p_mbsrtowcs = (void*)GetProcAddress(hMsvcrt, "mbsrtowcs");
+    p__atodbl_l = (void*)GetProcAddress(hMsvcrt, "_atodbl_l");
 
     /* MSVCRT memcpy behaves like memmove for overlapping moves,
        MFC42 CString::Insert seems to rely on that behaviour */
@@ -2429,15 +2726,12 @@ START_TEST(string)
     ok(pmemcmp(mem+5,xilstring, nLen) == 0,
        "Got result %s\n",mem+5);
 
-    /* Test _swab function */
+    /* run tolower tests first */
+    test_tolower();
     test_swab();
-
-    /* Test ismbblead*/
     test_mbcp();
-   /* test _mbsspn */
     test_mbsspn();
     test_mbsspnp();
-   /* test _strdup */
     test_strdup();
     test_strcpy_s();
     test_memcpy_s();
@@ -2450,6 +2744,7 @@ START_TEST(string)
     test_mbctombb();
     test_ismbclegal();
     test_strtok();
+    test__mbstok();
     test_wcscpy_s();
     test__wcsupr_s();
     test_strtol();
@@ -2468,5 +2763,9 @@ START_TEST(string)
     test__mbslwr_s();
     test_wctob();
     test_wctomb();
-    test_tolower();
+    test__atodbl();
+    test__stricmp();
+    test__wcstoi64();
+    test_atoi();
+    test_strncpy();
 }
index a4d020f..7a62c63 100644 (file)
@@ -1,10 +1,7 @@
 /* Automatically generated file; DO NOT EDIT!! */
 
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
 #define STANDALONE
-#include "wine/test.h"
+#include <wine/test.h>
 
 extern void func_cpp(void);
 extern void func_data(void);
index c6e2a9c..71e58ba 100644 (file)
@@ -46,13 +46,15 @@ static errno_t    (__cdecl *p_localtime32_s)(struct tm*, __time32_t*);
 static errno_t    (__cdecl *p_localtime64_s)(struct tm*, __time64_t*);
 static int*       (__cdecl *p__daylight)(void);
 static int*       (__cdecl *p___p__daylight)(void);
+static long*      (__cdecl *p___p__dstbias)(void);
+static long*      (__cdecl *p___p__timezone)(void);
 static size_t     (__cdecl *p_strftime)(char *, size_t, const char *, const struct tm *);
 static size_t     (__cdecl *p_wcsftime)(wchar_t *, size_t, const wchar_t *, const struct tm *);
 static char*      (__cdecl *p_asctime)(const struct tm *);
 
 static void init(void)
 {
-    HMODULE hmod = LoadLibrary("msvcrt.dll");
+    HMODULE hmod = LoadLibraryA("msvcrt.dll");
 
     p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
     p_gmtime = (void*)GetProcAddress(hmod, "gmtime");
@@ -64,6 +66,8 @@ static void init(void)
     p_localtime64_s = (void*)GetProcAddress(hmod, "_localtime64_s");
     p__daylight = (void*)GetProcAddress(hmod, "__daylight");
     p___p__daylight = (void*)GetProcAddress(hmod, "__p__daylight");
+    p___p__dstbias = (void*)GetProcAddress(hmod, "__p__dstbias");
+    p___p__timezone = (void*)GetProcAddress(hmod, "__p__timezone");
     p_strftime = (void*)GetProcAddress(hmod, "strftime");
     p_wcsftime = (void*)GetProcAddress(hmod, "wcsftime");
     p_asctime = (void*)GetProcAddress(hmod, "asctime");
@@ -105,7 +109,7 @@ static void test_gmtime(void)
 
     gmt = -1;
     gmt_tm = p_gmtime32(&gmt);
-    ok(gmt_tm == NULL, "gmt_tm != NULL\n");
+    ok(gmt_tm==NULL || broken(gmt_tm->tm_year==70 && gmt_tm->tm_sec<0), "gmt_tm != NULL\n");
 
     gmt = valid = 0;
     gmt_tm = p_gmtime32(&gmt);
@@ -177,9 +181,12 @@ static void test_gmtime(void)
     errno = 0;
     gmt = -1;
     err = p_gmtime32_s(&gmt_tm_s, &gmt);
-    ok(err == EINVAL, "err = %d\n", err);
-    ok(errno == EINVAL, "errno = %d\n", errno);
-    ok(gmt_tm_s.tm_year == -1, "tm_year = %d\n", gmt_tm_s.tm_year);
+    ok(gmt_tm_s.tm_year == -1 || broken(gmt_tm_s.tm_year == 70 && gmt_tm_s.tm_sec < 0),
+       "tm_year = %d, tm_sec = %d\n", gmt_tm_s.tm_year, gmt_tm_s.tm_sec);
+    if(gmt_tm_s.tm_year == -1) {
+        ok(err==EINVAL, "err = %d\n", err);
+        ok(errno==EINVAL, "errno = %d\n", errno);
+    }
 }
 
 static void test_mktime(void)
@@ -804,10 +811,68 @@ static void test_asctime(void)
     ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
 }
 
+static void test__tzset(void)
+{
+    char TZ_env[256];
+    int ret;
+
+    if(!p___p__daylight || !p___p__timezone || !p___p__dstbias) {
+        win_skip("__p__daylight, __p__timezone or __p__dstbias is not available\n");
+        return;
+    }
+
+    _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
+
+    ret = *p___p__daylight();
+    ok(ret == 1, "*__p__daylight() = %d\n", ret);
+    ret = *p___p__timezone();
+    ok(ret == 28800, "*__p__timezone() = %d\n", ret);
+    ret = *p___p__dstbias();
+    ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
+
+    _putenv("TZ=xxx+1yyy");
+    _tzset();
+    ret = *p___p__daylight();
+    ok(ret == 121, "*__p__daylight() = %d\n", ret);
+    ret = *p___p__timezone();
+    ok(ret == 3600, "*__p__timezone() = %d\n", ret);
+    ret = *p___p__dstbias();
+    ok(ret == -3600, "*__p__dstbias() = %d\n", ret);
+
+    *p___p__dstbias() = 0;
+    _putenv("TZ=xxx+1:3:5zzz");
+    _tzset();
+    ret = *p___p__daylight();
+    ok(ret == 122, "*__p__daylight() = %d\n", ret);
+    ret = *p___p__timezone();
+    ok(ret == 3785, "*__p__timezone() = %d\n", ret);
+    ret = *p___p__dstbias();
+    ok(ret == 0, "*__p__dstbias() = %d\n", ret);
+
+    _putenv(TZ_env);
+}
+
+static void test_clock(void)
+{
+    static const int THRESH = 50;
+    clock_t s, e;
+    int i;
+
+    for (i = 0; i < 10; i++)
+    {
+        s = clock();
+        Sleep(1000);
+        e = clock();
+
+        ok(abs((e-s) - 1000) < THRESH, "clock off on loop %i: %i\n", i, e-s);
+    }
+}
+
 START_TEST(time)
 {
     init();
 
+    test__tzset();
     test_strftime();
     test_ctime();
     test_gmtime();
@@ -821,4 +886,5 @@ START_TEST(time)
     test_localtime64_s();
     test_daylight();
     test_asctime();
+    test_clock();
 }