Reactos

[UCRTBASE_WINETEST] Import ucrtbase_winetest from wine-10.0

+5202
+244
modules/rostests/winetests/ucrtbase/cpp.c
··· 1 + /* 2 + * Copyright 2016 Daniel Lehman (Esri) 3 + * 4 + * This library is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU Lesser General Public 6 + * License as published by the Free Software Foundation; either 7 + * version 2.1 of the License, or (at your option) any later version. 8 + * 9 + * This library is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * Lesser General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU Lesser General Public 15 + * License along with this library; if not, write to the Free Software 16 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 + */ 18 + 19 + #include <errno.h> 20 + #include <stdarg.h> 21 + #include <stdlib.h> 22 + #include <wchar.h> 23 + #include <stdio.h> 24 + 25 + #include <windef.h> 26 + #include <winbase.h> 27 + #include <verrsrc.h> 28 + #include <dbghelp.h> 29 + #include "wine/test.h" 30 + 31 + typedef unsigned char MSVCRT_bool; 32 + 33 + typedef struct { 34 + const char *what; 35 + MSVCRT_bool dofree; 36 + } __std_exception_data; 37 + 38 + typedef struct 39 + { 40 + char *name; 41 + char mangled[32]; 42 + } type_info140; 43 + 44 + typedef struct _type_info_list 45 + { 46 + SLIST_ENTRY entry; 47 + char name[1]; 48 + } type_info_list; 49 + 50 + static void* (CDECL *p_malloc)(size_t); 51 + static void (CDECL *p___std_exception_copy)(const __std_exception_data*, __std_exception_data*); 52 + static void (CDECL *p___std_exception_destroy)(__std_exception_data*); 53 + static int (CDECL *p___std_type_info_compare)(const type_info140*, const type_info140*); 54 + static const char* (CDECL *p___std_type_info_name)(type_info140*, SLIST_HEADER*); 55 + static void (CDECL *p___std_type_info_destroy_list)(SLIST_HEADER*); 56 + static size_t (CDECL *p___std_type_info_hash)(type_info140*); 57 + static char* (__cdecl *p___unDName)(char*,const char*,int,void*,void*,unsigned short int); 58 + 59 + static BOOL init(void) 60 + { 61 + HMODULE module; 62 + 63 + module = LoadLibraryA("ucrtbase.dll"); 64 + if (!module) 65 + { 66 + win_skip("ucrtbase.dll not installed\n"); 67 + return FALSE; 68 + } 69 + 70 + p_malloc = (void*)GetProcAddress(module, "malloc"); 71 + p___std_exception_copy = (void*)GetProcAddress(module, "__std_exception_copy"); 72 + p___std_exception_destroy = (void*)GetProcAddress(module, "__std_exception_destroy"); 73 + p___std_type_info_compare = (void*)GetProcAddress(module, "__std_type_info_compare"); 74 + p___std_type_info_name = (void*)GetProcAddress(module, "__std_type_info_name"); 75 + p___std_type_info_destroy_list = (void*)GetProcAddress(module, "__std_type_info_destroy_list"); 76 + p___std_type_info_hash = (void*)GetProcAddress(module, "__std_type_info_hash"); 77 + p___unDName = (void*)GetProcAddress(module, "__unDName"); 78 + return TRUE; 79 + } 80 + 81 + static void test___std_exception(void) 82 + { 83 + __std_exception_data src; 84 + __std_exception_data dst; 85 + 86 + if (0) /* crash on Windows */ 87 + { 88 + p___std_exception_copy(NULL, &src); 89 + p___std_exception_copy(&dst, NULL); 90 + 91 + src.what = "invalid free"; 92 + src.dofree = 1; 93 + p___std_exception_destroy(&src); 94 + p___std_exception_destroy(NULL); 95 + } 96 + 97 + src.what = "what"; 98 + src.dofree = 0; 99 + p___std_exception_copy(&src, &dst); 100 + ok(dst.what == src.what, "expected what to be same, got src %p dst %p\n", src.what, dst.what); 101 + ok(!dst.dofree, "expected 0, got %d\n", dst.dofree); 102 + 103 + src.dofree = 0x42; 104 + p___std_exception_copy(&src, &dst); 105 + ok(dst.what != src.what, "expected what to be different, got src %p dst %p\n", src.what, dst.what); 106 + ok(dst.dofree == 1, "expected 1, got %d\n", dst.dofree); 107 + 108 + p___std_exception_destroy(&dst); 109 + ok(!dst.what, "expected NULL, got %p\n", dst.what); 110 + ok(!dst.dofree, "expected 0, got %d\n", dst.dofree); 111 + 112 + src.what = NULL; 113 + src.dofree = 0; 114 + p___std_exception_copy(&src, &dst); 115 + ok(!dst.what, "dst.what != NULL\n"); 116 + ok(!dst.dofree, "dst.dofree != FALSE\n"); 117 + 118 + src.what = NULL; 119 + src.dofree = 1; 120 + p___std_exception_copy(&src, &dst); 121 + ok(!dst.what, "dst.what != NULL\n"); 122 + ok(!dst.dofree, "dst.dofree != FALSE\n"); 123 + } 124 + 125 + static void test___std_type_info(void) 126 + { 127 + type_info140 ti1 = { NULL, ".?AVa@@" }; 128 + type_info140 ti2 = { NULL, ".?AVb@@" }; 129 + type_info140 ti3 = ti1; 130 + SLIST_HEADER header; 131 + type_info_list *elem; 132 + const char *ret; 133 + size_t hash1, hash2; 134 + int eq; 135 + 136 + 137 + InitializeSListHead(&header); 138 + p___std_type_info_destroy_list(&header); 139 + 140 + elem = p_malloc(sizeof(*elem)); 141 + memset(elem, 0, sizeof(*elem)); 142 + InterlockedPushEntrySList(&header, &elem->entry); 143 + p___std_type_info_destroy_list(&header); 144 + ok(!InterlockedPopEntrySList(&header), "list is not empty\n"); 145 + 146 + ret = p___std_type_info_name(&ti1, &header); 147 + ok(!strcmp(ret, "class a"), "__std_type_info_name(&ti1) = %s\n", ret); 148 + ok(ti1.name == ret, "ti1.name = %p, ret = %p\n", ti1.name, ret); 149 + 150 + p___std_type_info_destroy_list(&header); 151 + ok(!InterlockedPopEntrySList(&header), "list is not empty\n"); 152 + ok(ti1.name == ret, "ti1.name = %p, ret = %p\n", ti1.name, ret); 153 + ti1.name = NULL; 154 + 155 + eq = p___std_type_info_compare(&ti1, &ti1); 156 + ok(eq == 0, "__std_type_info_compare(&ti1, &ti1) = %d\n", eq); 157 + 158 + eq = p___std_type_info_compare(&ti1, &ti2); 159 + ok(eq == -1, "__std_type_info_compare(&ti1, &ti2) = %d\n", eq); 160 + 161 + eq = p___std_type_info_compare(&ti1, &ti3); 162 + ok(eq == 0, "__std_type_info_compare(&ti1, &ti3) = %d\n", eq); 163 + 164 + ti1.mangled[0] = 0; 165 + ti1.mangled[1] = 0; 166 + ti1.mangled[2] = 0; 167 + hash1 = p___std_type_info_hash(&ti1); 168 + #ifdef _WIN64 169 + ok(hash1 == 0xcbf29ce44fd0bfc1, "hash = %p\n", (void*)hash1); 170 + #else 171 + ok(hash1 == 0x811c9dc5, "hash = %p\n", (void*)hash1); 172 + #endif 173 + 174 + ti1.mangled[0] = 1; 175 + hash2 = p___std_type_info_hash(&ti1); 176 + ok(hash1 == hash2, "hash1 != hash2 (first char not ignored)\n"); 177 + 178 + ti1.mangled[1] = 1; 179 + hash1 = p___std_type_info_hash(&ti1); 180 + #ifdef _WIN64 181 + ok(hash1 == 0xaf63bc4c29620a60, "hash = %p\n", (void*)hash1); 182 + #else 183 + ok(hash1 == 0x40c5b8c, "hash = %p\n", (void*)hash1); 184 + #endif 185 + ok(hash1 != hash2, "hash1 == hash2 for different strings\n"); 186 + 187 + ti1.mangled[1] = 2; 188 + hash2 = p___std_type_info_hash(&ti1); 189 + ok(hash1 != hash2, "hash1 == hash2 for different strings\n"); 190 + 191 + hash1 = p___std_type_info_hash(&ti2); 192 + ok(hash1 != hash2, "hash1 == hash2 for different strings\n"); 193 + } 194 + 195 + static void test___unDName(void) 196 + { 197 + static struct {const char *in; const char *out; const char *broken; unsigned int flags;} und_tests[] = 198 + { 199 + /* 0 */ {"??4QDnsDomainNameRecord@@QAEAAV0@$$QAV0@@Z", 200 + "public: class QDnsDomainNameRecord & __thiscall QDnsDomainNameRecord::operator=(class QDnsDomainNameRecord &&)"}, 201 + /* 1 */ {"??4QDnsDomainNameRecord@@QAEAAV0@$$QEAV0@@Z", 202 + "public: class QDnsDomainNameRecord & __thiscall QDnsDomainNameRecord::operator=(class QDnsDomainNameRecord && __ptr64)"}, 203 + /* 2 */ {"??__K_l@@YA?AUCC@@I@Z", "struct CC __cdecl operator \"\" _l(unsigned int)", 204 + "??__K_l@@YA?AUCC@@I@Z" /* W10 1507 fails on this :-( */}, 205 + /* 3 */ {"?meth@Q@@QEGBA?AV1@XZ", 206 + "public: class Q __cdecl Q::meth(void)const __ptr64& ", 207 + "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */}, 208 + /* 4 */ {"?meth@Q@@QEHAA?AV1@XZ", 209 + "public: class Q __cdecl Q::meth(void) __ptr64&& ", 210 + "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */}, 211 + /* 5 */ {"?meth@Q@@QEGBA?AV1@XZ", 212 + "public: class Q Q::meth(void)const & ", 213 + "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */, 214 + UNDNAME_NO_MS_KEYWORDS}, 215 + /* 6 */ {"?meth@Q@@QEHAA?AV1@XZ", 216 + "public: class Q Q::meth(void)&& ", 217 + "public: ?? :: ?? ::XZ::V1" /* W10 1507 fails on this :-( */, 218 + UNDNAME_NO_MS_KEYWORDS}, 219 + /* 7 */ {"?AU?$my_iter@H$0A@$$V@@", 220 + "struct my_iter<int,0>", 221 + NULL, 222 + UNDNAME_NO_ARGUMENTS}, 223 + /* 8 */ {"??$foo@J_W$$T@bar@@YAJQB_W$$THQAUgod@@@Z", 224 + "long __cdecl bar::foo<long,wchar_t,std::nullptr_t>(wchar_t const * const,std::nullptr_t,int,struct god * const)"}, 225 + 226 + }; 227 + unsigned i; 228 + for (i = 0; i < ARRAY_SIZE(und_tests); i++) 229 + { 230 + char *name = p___unDName(0, und_tests[i].in, 0, malloc, free, und_tests[i].flags); 231 + ok(!strcmp(name, und_tests[i].out) || 232 + broken(und_tests[i].broken && !strcmp(und_tests[i].broken, name)), 233 + "unDName returned %s for #%u\n", wine_dbgstr_a(name), i); 234 + free(name); 235 + } 236 + } 237 + 238 + START_TEST(cpp) 239 + { 240 + if (!init()) return; 241 + test___std_exception(); 242 + test___std_type_info(); 243 + test___unDName(); 244 + }
+344
modules/rostests/winetests/ucrtbase/environ.c
··· 1 + /* 2 + * Unit tests for C library environment routines 3 + * 4 + * Copyright 2004 Mike Hearn <mh@codeweavers.com> 5 + * 6 + * This library is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU Lesser General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2.1 of the License, or (at your option) any later version. 10 + * 11 + * This library is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * Lesser General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU Lesser General Public 17 + * License along with this library; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 + */ 20 + 21 + #include "wine/test.h" 22 + #include <errno.h> 23 + #include <stdlib.h> 24 + #include <process.h> 25 + #include <winnls.h> 26 + 27 + #define DEFINE_EXPECT(func) \ 28 + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 29 + 30 + #define SET_EXPECT(func) \ 31 + expect_ ## func = TRUE 32 + 33 + #define CHECK_EXPECT2(func) \ 34 + do { \ 35 + ok(expect_ ##func, "unexpected call " #func "\n"); \ 36 + called_ ## func = TRUE; \ 37 + }while(0) 38 + 39 + #define CHECK_EXPECT(func) \ 40 + do { \ 41 + CHECK_EXPECT2(func); \ 42 + expect_ ## func = FALSE; \ 43 + }while(0) 44 + 45 + #define CHECK_CALLED(func) \ 46 + do { \ 47 + ok(called_ ## func, "expected " #func "\n"); \ 48 + expect_ ## func = called_ ## func = FALSE; \ 49 + }while(0) 50 + 51 + DEFINE_EXPECT(invalid_parameter_handler); 52 + 53 + static const char *a_very_long_env_string = 54 + "LIBRARY_PATH=" 55 + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/;" 56 + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/;" 57 + "/mingw/lib/gcc/mingw32/3.4.2/;" 58 + "/usr/lib/gcc/mingw32/3.4.2/;" 59 + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../../mingw32/lib/mingw32/3.4.2/;" 60 + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../../mingw32/lib/;" 61 + "/mingw/mingw32/lib/mingw32/3.4.2/;" 62 + "/mingw/mingw32/lib/;" 63 + "/mingw/lib/mingw32/3.4.2/;" 64 + "/mingw/lib/;" 65 + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../mingw32/3.4.2/;" 66 + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../;" 67 + "/mingw/lib/mingw32/3.4.2/;" 68 + "/mingw/lib/;" 69 + "/lib/mingw32/3.4.2/;" 70 + "/lib/;" 71 + "/usr/lib/mingw32/3.4.2/;" 72 + "/usr/lib/"; 73 + 74 + static char ***(__cdecl *p__p__environ)(void); 75 + static WCHAR ***(__cdecl *p__p__wenviron)(void); 76 + static char** (__cdecl *p_get_initial_narrow_environment)(void); 77 + static wchar_t** (__cdecl *p_get_initial_wide_environment)(void); 78 + static errno_t (__cdecl *p_putenv_s)(const char*, const char*); 79 + static errno_t (__cdecl *p_wputenv_s)(const wchar_t*, const wchar_t*); 80 + static errno_t (__cdecl *p_getenv_s)(size_t*, char*, size_t, const char*); 81 + 82 + static char ***p_environ; 83 + static WCHAR ***p_wenviron; 84 + 85 + static void __cdecl test_invalid_parameter_handler(const wchar_t *expression, 86 + const wchar_t *function, const wchar_t *file, 87 + unsigned line, uintptr_t arg) 88 + { 89 + CHECK_EXPECT(invalid_parameter_handler); 90 + ok(expression == NULL, "expression is not NULL\n"); 91 + ok(function == NULL, "function is not NULL\n"); 92 + ok(file == NULL, "file is not NULL\n"); 93 + ok(line == 0, "line = %u\n", line); 94 + ok(arg == 0, "arg = %Ix\n", arg); 95 + } 96 + 97 + static BOOL init(void) 98 + { 99 + HMODULE hmod = GetModuleHandleA( "ucrtbase.dll" ); 100 + 101 + p__p__environ = (void *)GetProcAddress( hmod, "__p__environ" ); 102 + p__p__wenviron = (void *)GetProcAddress( hmod, "__p__wenviron" ); 103 + p_get_initial_narrow_environment = (void *)GetProcAddress( hmod, "_get_initial_narrow_environment" ); 104 + p_get_initial_wide_environment = (void *)GetProcAddress( hmod, "_get_initial_wide_environment" ); 105 + p_putenv_s = (void *)GetProcAddress( hmod, "_putenv_s" ); 106 + p_wputenv_s = (void *)GetProcAddress( hmod, "_wputenv_s" ); 107 + p_getenv_s = (void *)GetProcAddress( hmod, "getenv_s" ); 108 + 109 + ok(p__p__environ != NULL, "Unexecped NULL pointer to environ\n" ); 110 + ok(p__p__wenviron != NULL, "Unexecped NULL pointer to environ\n" ); 111 + if (!p__p__environ || !p__p__wenviron) 112 + { 113 + skip( "NULL pointers for environment\n" ); 114 + return FALSE; 115 + } 116 + p_environ = p__p__environ(); 117 + p_wenviron = p__p__wenviron(); 118 + return TRUE; 119 + } 120 + 121 + static unsigned env_get_entry_countA( char **env ) 122 + { 123 + unsigned count; 124 + 125 + if (!env) return 0; 126 + for (count = 0; env[count] != NULL; count++) {} 127 + return count; 128 + } 129 + 130 + static void test_initial_environ( void ) 131 + { 132 + ok( p__p__environ() != NULL, "Unexpected NULL _environ[]\n" ); 133 + ok( *p__p__environ() != NULL, "Unexpected empty _environ[]\n" ); 134 + ok( p_get_initial_narrow_environment() != NULL, "Unexpected empty narrow initial environment\n" ); 135 + ok( p_get_initial_narrow_environment() == *p__p__environ(), "Expecting _environ[] to match initial narrow environment\n" ); 136 + 137 + ok( p__p__wenviron() != NULL, "Unexpected NULL _wenviron[]\n" ); 138 + ok( *p__p__wenviron() == NULL, "Unexpected non empty _wenviron[]\n" ); 139 + ok( p_get_initial_wide_environment() != NULL, "Unexpected empty wide initial environment\n" ); 140 + ok( p_get_initial_wide_environment() == *p__p__wenviron(), "Expecting _wenviron[] to match initial wide environment\n" ); 141 + } 142 + 143 + static void test_environment_manipulation(void) 144 + { 145 + char buf[256]; 146 + errno_t ret; 147 + size_t len; 148 + unsigned count; 149 + char* first; 150 + char* second; 151 + 152 + ok( _putenv( "cat=" ) == 0, "_putenv failed on deletion of nonexistent environment variable\n" ); 153 + ok( _putenv( "cat=dog" ) == 0, "failed setting cat=dog\n" ); 154 + ok( strcmp( getenv( "cat" ), "dog" ) == 0, "getenv did not return 'dog'\n" ); 155 + if (p_getenv_s) 156 + { 157 + ret = p_getenv_s( &len, buf, sizeof(buf), "cat" ); 158 + ok( !ret, "getenv_s returned %d\n", ret ); 159 + ok( len == 4, "getenv_s returned length is %Id\n", len); 160 + ok( !strcmp(buf, "dog"), "getenv_s did not return 'dog'\n" ); 161 + } 162 + ok( _putenv("cat=") == 0, "failed deleting cat\n" ); 163 + 164 + ok( _putenv("=") == -1, "should not accept '=' as input\n" ); 165 + ok( _putenv("=dog") == -1, "should not accept '=dog' as input\n" ); 166 + ok( _putenv(a_very_long_env_string) == 0, "_putenv failed for long environment string\n" ); 167 + 168 + ok( getenv("nonexistent") == NULL, "getenv should fail with nonexistent var name\n" ); 169 + 170 + if (p_putenv_s) 171 + { 172 + SET_EXPECT(invalid_parameter_handler); 173 + ret = p_putenv_s( NULL, "dog" ); 174 + CHECK_CALLED(invalid_parameter_handler); 175 + ok( ret == EINVAL, "_putenv_s returned %d\n", ret ); 176 + SET_EXPECT(invalid_parameter_handler); 177 + ret = p_putenv_s( "cat", NULL ); 178 + CHECK_CALLED(invalid_parameter_handler); 179 + ok( ret == EINVAL, "_putenv_s returned %d\n", ret ); 180 + SET_EXPECT(invalid_parameter_handler); 181 + ret = p_putenv_s( "a=b", NULL ); 182 + CHECK_CALLED(invalid_parameter_handler); 183 + ok( ret == EINVAL, "_putenv_s returned %d\n", ret ); 184 + ret = p_putenv_s( "cat", "a=b" ); 185 + ok( !ret, "_putenv_s returned %d\n", ret ); 186 + ret = p_putenv_s( "cat", "" ); 187 + ok( !ret, "_putenv_s returned %d\n", ret ); 188 + } 189 + 190 + if (p_wputenv_s) 191 + { 192 + SET_EXPECT(invalid_parameter_handler); 193 + ret = p_wputenv_s( NULL, L"dog" ); 194 + CHECK_CALLED(invalid_parameter_handler); 195 + ok( ret == EINVAL, "_wputenv_s returned %d\n", ret ); 196 + SET_EXPECT(invalid_parameter_handler); 197 + ret = p_wputenv_s( L"cat", NULL ); 198 + CHECK_CALLED(invalid_parameter_handler); 199 + ok( ret == EINVAL, "_wputenv_s returned %d\n", ret ); 200 + SET_EXPECT(invalid_parameter_handler); 201 + ret = p_wputenv_s( L"a=b", NULL ); 202 + CHECK_CALLED(invalid_parameter_handler); 203 + ok( ret == EINVAL, "_wputenv_s returned %d\n", ret ); 204 + ret = p_wputenv_s( L"cat", L"a=b" ); 205 + ok( !ret, "_wputenv_s returned %d\n", ret ); 206 + ret = p_wputenv_s( L"cat", L"" ); 207 + ok( !ret, "_wputenv_s returned %d\n", ret ); 208 + } 209 + 210 + if (p_getenv_s) 211 + { 212 + buf[0] = 'x'; 213 + len = 1; 214 + errno = 0xdeadbeef; 215 + ret = p_getenv_s( &len, buf, sizeof(buf), "nonexistent" ); 216 + ok( !ret, "_getenv_s returned %d\n", ret ); 217 + ok( !len, "getenv_s returned length is %Id\n", len ); 218 + ok( !buf[0], "buf = %s\n", buf ); 219 + ok( errno == 0xdeadbeef, "errno = %d\n", errno ); 220 + 221 + buf[0] = 'x'; 222 + len = 1; 223 + errno = 0xdeadbeef; 224 + ret = p_getenv_s( &len, buf, sizeof(buf), NULL ); 225 + ok( !ret, "_getenv_s returned %d\n", ret ); 226 + ok( !len, "getenv_s returned length is %Id\n", len ); 227 + ok( !buf[0], "buf = %s\n", buf ); 228 + ok( errno == 0xdeadbeef, "errno = %d\n", errno ); 229 + } 230 + 231 + /* test stability of _environ[] pointers */ 232 + ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env var\n" ); 233 + ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" ); 234 + count = env_get_entry_countA( *p_environ ); 235 + ok( _putenv( "__winetest_cat=mew") == 0, "Couldn't set env var\n" ); 236 + ok( !strcmp( (*p_environ)[count], "__winetest_cat=mew"), "Unexpected env var value\n" ); 237 + first = (*p_environ)[count]; 238 + ok( getenv("__winetest_cat") == strchr( (*p_environ)[count], '=') + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); 239 + ok( _putenv( "__winetest_dog=bark" ) == 0, "Couldn't set env var\n" ); 240 + ok( !strcmp( (*p_environ)[count + 1], "__winetest_dog=bark" ), "Unexpected env var value\n" ); 241 + ok( getenv( "__winetest_dog" ) == strchr( (*p_environ)[count + 1], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); 242 + ok( first == (*p_environ)[count], "Expected stability of _environ[count] pointer\n" ); 243 + second = (*p_environ)[count + 1]; 244 + ok( count + 2 == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); 245 + 246 + ok( _putenv( "__winetest_cat=purr" ) == 0, "Couldn't set env var\n" ); 247 + ok( !strcmp( (*p_environ)[count], "__winetest_cat=purr" ), "Unexpected env var value\n" ); 248 + ok( getenv( "__winetest_cat" ) == strchr( (*p_environ)[count], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); 249 + ok( second == (*p_environ)[count + 1], "Expected stability of _environ[count] pointer\n" ); 250 + ok( !strcmp( (*p_environ)[count + 1], "__winetest_dog=bark" ), "Couldn't get env var value\n" ); 251 + ok( getenv( "__winetest_dog" ) == strchr( (*p_environ)[count + 1], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); 252 + ok( count + 2 == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); 253 + ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env vat\n" ); 254 + ok( second == (*p_environ)[count], "Expected _environ[count] to be second\n" ); 255 + ok( !strcmp( (*p_environ)[count], "__winetest_dog=bark" ), "Unexpected env var value\n" ); 256 + ok( count + 1 == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); 257 + ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" ); 258 + ok( count == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); 259 + 260 + /* in putenv, only changed variable is updated (no other reload of kernel info is done) */ 261 + ret = SetEnvironmentVariableA( "__winetest_cat", "meow" ); 262 + ok( ret, "SetEnvironmentVariableA failed: %lu\n", GetLastError() ); 263 + ok( _putenv( "__winetest_dog=bark" ) == 0, "Couldn't set env var\n" ); 264 + ok( getenv( "__winetest_cat" ) == NULL, "msvcrt env cache shouldn't have been updated\n" ); 265 + ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env var\n" ); 266 + ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" ); 267 + 268 + /* test setting unicode bits */ 269 + count = env_get_entry_countA( *p_environ ); 270 + ret = WideCharToMultiByte( CP_ACP, 0, L"\u263a", -1, buf, ARRAY_SIZE(buf), 0, 0 ); 271 + ok( ret, "WideCharToMultiByte failed: %lu\n", GetLastError() ); 272 + ok( _wputenv( L"__winetest_cat=\u263a" ) == 0, "Couldn't set env var\n" ); 273 + ok( _wgetenv( L"__winetest_cat" ) && !wcscmp( _wgetenv( L"__winetest_cat" ), L"\u263a" ), "Couldn't retrieve env var\n" ); 274 + ok( getenv( "__winetest_cat" ) && !strcmp( getenv( "__winetest_cat" ), buf ), "Couldn't retrieve env var\n" ); 275 + ok( _wputenv( L"__winetest_cat=" ) == 0, "Couldn't reset env var\n" ); 276 + 277 + ret = WideCharToMultiByte( CP_ACP, 0, L"__winetest_\u263a", -1, buf, ARRAY_SIZE(buf), 0, 0 ); 278 + ok( ret, "WideCharToMultiByte failed: %lu\n", GetLastError() ); 279 + ok( _wputenv( L"__winetest_\u263a=bark" ) == 0, "Couldn't set env var\n" ); 280 + ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"bark"), "Couldn't retrieve env var\n" ); 281 + ok( getenv( buf ) && !strcmp( getenv( buf ), "bark"), "Couldn't retrieve env var %s\n", wine_dbgstr_a(buf) ); 282 + ok( _wputenv( L"__winetest_\u263a=" ) == 0, "Couldn't reset env var\n" ); 283 + ok( count == env_get_entry_countA( *p_environ ), "Unexpected modification of _environ[]\n" ); 284 + } 285 + 286 + static void test_child_env(char** argv) 287 + { 288 + STARTUPINFOA si = {sizeof(si)}; 289 + WCHAR *cur_env, *env, *p, *q; 290 + PROCESS_INFORMATION pi; 291 + char tmp[1024]; 292 + BOOL ret; 293 + int len; 294 + 295 + cur_env = GetEnvironmentStringsW(); 296 + ok( cur_env != NULL, "GetEnvironemntStrings failed\n" ); 297 + 298 + p = cur_env; 299 + while (*p) p += wcslen( p ) + 1; 300 + len = p - cur_env; 301 + env = malloc( (len + 1024) * sizeof(*env) ); 302 + memcpy(env, cur_env, len * sizeof(*env) ); 303 + q = env + len; 304 + FreeEnvironmentStringsW( cur_env ); 305 + 306 + wcscpy( q, L"__winetest_dog=bark" ); 307 + q += wcslen( L"__winetest_dog=bark" ) + 1; 308 + wcscpy( q, L"__winetest_\u263a=\u03b2" ); 309 + q += wcslen( L"__winetest_\u263a=\u03b2" ) + 1; 310 + *q = 0; 311 + 312 + snprintf( tmp, sizeof(tmp), "%s %s create", argv[0], argv[1] ); 313 + ret = CreateProcessA( NULL, tmp, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, env, NULL, &si, &pi ); 314 + ok( ret, "Couldn't create child process %s\n", tmp ); 315 + winetest_wait_child_process( pi.hProcess ); 316 + CloseHandle( pi.hProcess ); 317 + CloseHandle( pi.hThread ); 318 + free( env ); 319 + } 320 + 321 + START_TEST(environ) 322 + { 323 + char **argv; 324 + int argc; 325 + 326 + if (!init()) return; 327 + 328 + ok( _set_invalid_parameter_handler( test_invalid_parameter_handler ) == NULL, 329 + "Invalid parameter handler was already set\n" ); 330 + 331 + argc = winetest_get_mainargs( &argv ); 332 + if (argc == 3 && !strcmp( argv[2], "create" )) 333 + { 334 + ok( getenv( "__winetest_dog" ) && !strcmp( getenv( "__winetest_dog" ), "bark" ), 335 + "Couldn't find env var\n" ); 336 + ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"\u03b2" ), 337 + "Couldn't find unicode env var\n" ); 338 + return; 339 + } 340 + 341 + test_initial_environ(); 342 + test_environment_manipulation(); 343 + test_child_env(argv); 344 + }
+472
modules/rostests/winetests/ucrtbase/file.c
··· 1 + /* 2 + * Unit test suite for file functions 3 + * 4 + * Copyright 2024 Eric Pouech for CodeWeavers 5 + * 6 + * This library is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU Lesser General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2.1 of the License, or (at your option) any later version. 10 + * 11 + * This library is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * Lesser General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU Lesser General Public 17 + * License along with this library; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 + */ 20 + 21 + #include <errno.h> 22 + #include <direct.h> 23 + #include <stdarg.h> 24 + #include <locale.h> 25 + #include <process.h> 26 + #include <share.h> 27 + #include <sys/stat.h> 28 + 29 + #include <windef.h> 30 + #include <winbase.h> 31 + #include <winnls.h> 32 + #include "wine/test.h" 33 + 34 + static void test_std_stream_buffering(void) 35 + { 36 + int dup_fd, ret, pos; 37 + FILE *file; 38 + char ch; 39 + 40 + dup_fd = _dup(STDOUT_FILENO); 41 + ok(dup_fd != -1, "_dup failed\n"); 42 + 43 + file = freopen("std_stream_test.tmp", "w", stdout); 44 + ok(file != NULL, "freopen failed\n"); 45 + 46 + ret = fprintf(stdout, "test"); 47 + pos = _telli64(STDOUT_FILENO); 48 + 49 + fflush(stdout); 50 + _dup2(dup_fd, STDOUT_FILENO); 51 + close(dup_fd); 52 + setvbuf(stdout, NULL, _IONBF, 0); 53 + 54 + ok(ret == 4, "fprintf(stdout) returned %d\n", ret); 55 + ok(!pos, "expected stdout to be buffered\n"); 56 + 57 + dup_fd = _dup(STDERR_FILENO); 58 + ok(dup_fd != -1, "_dup failed\n"); 59 + 60 + file = freopen("std_stream_test.tmp", "w", stderr); 61 + ok(file != NULL, "freopen failed\n"); 62 + 63 + ret = fprintf(stderr, "test"); 64 + ok(ret == 4, "fprintf(stderr) returned %d\n", ret); 65 + pos = _telli64(STDERR_FILENO); 66 + if (broken(!GetProcAddress(GetModuleHandleA("ucrtbase"), "__CxxFrameHandler4") && !pos)) 67 + trace("stderr is buffered\n"); 68 + else 69 + ok(pos == 4, "expected stderr to be unbuffered (%d)\n", pos); 70 + 71 + fflush(stderr); 72 + _dup2(dup_fd, STDERR_FILENO); 73 + close(dup_fd); 74 + 75 + dup_fd = _dup(STDIN_FILENO); 76 + ok(dup_fd != -1, "_dup failed\n"); 77 + 78 + file = freopen("std_stream_test.tmp", "r", stdin); 79 + ok(file != NULL, "freopen failed\n"); 80 + 81 + ch = 0; 82 + ret = fscanf(stdin, "%c", &ch); 83 + ok(ret == 1, "fscanf returned %d\n", ret); 84 + ok(ch == 't', "ch = 0x%x\n", (unsigned char)ch); 85 + pos = _telli64(STDIN_FILENO); 86 + ok(pos == 4, "pos = %d\n", pos); 87 + 88 + fflush(stdin); 89 + _dup2(dup_fd, STDIN_FILENO); 90 + close(dup_fd); 91 + 92 + ok(DeleteFileA("std_stream_test.tmp"), "DeleteFile failed\n"); 93 + } 94 + 95 + int CDECL _get_stream_buffer_pointers(FILE*,char***,char***,int**); 96 + static void test_iobuf_layout(void) 97 + { 98 + union 99 + { 100 + FILE *f; 101 + struct 102 + { 103 + char* _ptr; 104 + char* _base; 105 + int _cnt; 106 + int _flag; 107 + int _file; 108 + int _charbuf; 109 + int _bufsiz; 110 + char* _tmpfname; 111 + CRITICAL_SECTION _crit; 112 + } *iobuf; 113 + } fp; 114 + char *tempf, *ptr, **file_ptr, **file_base; 115 + int cnt, r, *file_cnt; 116 + 117 + tempf = _tempnam(".","wne"); 118 + fp.f = fopen(tempf, "wb"); 119 + ok(fp.f != NULL, "fopen failed with error: %d\n", errno); 120 + 121 + ok(!(fp.iobuf->_flag & 0x440), "fp.iobuf->_flag = %x\n", fp.iobuf->_flag); 122 + r = fprintf(fp.f, "%s", "init"); 123 + ok(r == 4, "fprintf returned %d\n", r); 124 + ok(fp.iobuf->_flag & 0x40, "fp.iobuf->_flag = %x\n", fp.iobuf->_flag); 125 + ok(fp.iobuf->_cnt + 4 == fp.iobuf->_bufsiz, "_cnt = %d, _bufsiz = %d\n", 126 + fp.iobuf->_cnt, fp.iobuf->_bufsiz); 127 + 128 + ptr = fp.iobuf->_ptr; 129 + cnt = fp.iobuf->_cnt; 130 + r = fprintf(fp.f, "%s", "hello"); 131 + ok(r == 5, "fprintf returned %d\n", r); 132 + ok(ptr + 5 == fp.iobuf->_ptr, "fp.iobuf->_ptr = %p, expected %p\n", fp.iobuf->_ptr, ptr + 5); 133 + ok(cnt - 5 == fp.iobuf->_cnt, "fp.iobuf->_cnt = %d, expected %d\n", fp.iobuf->_cnt, cnt - 5); 134 + ok(fp.iobuf->_ptr + fp.iobuf->_cnt == fp.iobuf->_base + fp.iobuf->_bufsiz, 135 + "_ptr = %p, _cnt = %d, _base = %p, _bufsiz = %d\n", 136 + fp.iobuf->_ptr, fp.iobuf->_cnt, fp.iobuf->_base, fp.iobuf->_bufsiz); 137 + 138 + _get_stream_buffer_pointers(fp.f, &file_base, &file_ptr, &file_cnt); 139 + ok(file_base == &fp.iobuf->_base, "_base = %p, expected %p\n", file_base, &fp.iobuf->_base); 140 + ok(file_ptr == &fp.iobuf->_ptr, "_ptr = %p, expected %p\n", file_ptr, &fp.iobuf->_ptr); 141 + ok(file_cnt == &fp.iobuf->_cnt, "_cnt = %p, expected %p\n", file_cnt, &fp.iobuf->_cnt); 142 + 143 + r = setvbuf(fp.f, NULL, _IONBF, 0); 144 + ok(!r, "setvbuf returned %d\n", r); 145 + ok(fp.iobuf->_flag & 0x400, "fp.iobuf->_flag = %x\n", fp.iobuf->_flag); 146 + 147 + ok(TryEnterCriticalSection(&fp.iobuf->_crit), "TryEnterCriticalSection section returned FALSE\n"); 148 + LeaveCriticalSection(&fp.iobuf->_crit); 149 + 150 + fclose(fp.f); 151 + unlink(tempf); 152 + } 153 + 154 + static void test_std_stream_open(void) 155 + { 156 + FILE *f; 157 + int fd; 158 + 159 + fd = _dup(STDIN_FILENO); 160 + ok(fd != -1, "_dup failed\n"); 161 + 162 + ok(!fclose(stdin), "fclose failed\n"); 163 + f = fopen("nul", "r"); 164 + ok(f != stdin, "f = %p, stdin = %p\n", f, stdin); 165 + ok(_fileno(f) == STDIN_FILENO, "_fileno(f) = %d\n", _fileno(f)); 166 + ok(!fclose(f), "fclose failed\n"); 167 + 168 + f = freopen("nul", "r", stdin); 169 + ok(f == stdin, "f = %p, expected %p\n", f, stdin); 170 + ok(_fileno(f) == STDIN_FILENO, "_fileno(f) = %d\n", _fileno(f)); 171 + 172 + _dup2(fd, STDIN_FILENO); 173 + close(fd); 174 + } 175 + 176 + static void test_fopen(void) 177 + { 178 + int i; 179 + FILE *f; 180 + wchar_t wpath[MAX_PATH]; 181 + static const struct { 182 + const char *loc; 183 + const char *path; 184 + } tests[] = { 185 + { "German.utf8", "t\xc3\xa4\xc3\x8f\xc3\xb6\xc3\x9f.txt" }, 186 + { "Polish.utf8", "t\xc4\x99\xc5\x9b\xc4\x87.txt" }, 187 + { "Turkish.utf8", "t\xc3\x87\xc4\x9e\xc4\xb1\xc4\xb0\xc5\x9e.txt" }, 188 + { "Arabic.utf8", "t\xd8\xaa\xda\x86.txt" }, 189 + { "Japanese.utf8", "t\xe3\x82\xaf\xe3\x83\xa4.txt" }, 190 + { "Chinese.utf8", "t\xe4\xb8\x82\xe9\xbd\xab.txt" }, 191 + { "Japanese", "t\xb8\xd5.txt" }, 192 + 193 + }; 194 + 195 + for(i=0; i<ARRAY_SIZE(tests); i++) { 196 + if(!setlocale(LC_ALL, tests[i].loc)) { 197 + win_skip("skipping locale %s\n", tests[i].loc); 198 + continue; 199 + } 200 + 201 + if(!MultiByteToWideChar(___lc_codepage_func() == CP_UTF8 ? CP_UTF8 : CP_ACP, 202 + MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, tests[i].path, -1, wpath, MAX_PATH)) 203 + continue; 204 + 205 + f = _fsopen(tests[i].path, "w", SH_DENYNO); 206 + ok(!!f, "failed to create %s with locale %s\n", 207 + debugstr_a(tests[i].path), tests[i].loc); 208 + fclose(f); 209 + 210 + f = _wfsopen(wpath, L"r", SH_DENYNO); 211 + ok(!!f, "failed to open %s with locale %s\n", 212 + debugstr_a(tests[i].path), tests[i].loc); 213 + if(f) fclose(f); 214 + 215 + ok(!unlink(tests[i].path), "failed to unlink %s with locale %s\n", 216 + tests[i].path, tests[i].loc); 217 + } 218 + setlocale(LC_ALL, "C"); 219 + } 220 + 221 + static void test_utf8(const char *argv0) 222 + { 223 + const char file[] = "file\xc4\x99\xc5\x9b\xc4\x87.a"; 224 + const char dir[] = "dir\xc4\x99\xc5\x9b\xc4\x87"; 225 + const WCHAR fileW[] = L"file\x0119\x015b\x0107.a"; 226 + const WCHAR dirW[] = L"dir\x0119\x015b\x0107"; 227 + 228 + char file2[32], buf[256], *p, *q, *env[2]; 229 + struct _finddata64i32_t fdata64i32; 230 + struct _finddata32_t fdata32; 231 + struct _finddata64_t fdata64; 232 + intptr_t hfind, hproc; 233 + WCHAR bufW[256], *pW; 234 + struct _stat64 stat; 235 + FILE *f; 236 + int ret; 237 + 238 + if (!setlocale(LC_ALL, ".utf8")) 239 + { 240 + win_skip("utf-8 tests\n"); 241 + return; 242 + } 243 + 244 + ret = _mkdir(dir); 245 + if (ret == -1 && errno == ENOENT) 246 + { 247 + skip("can't create test environment\n"); 248 + return; 249 + } 250 + ok(!ret, "_mkdir returned %d, error %d\n", ret, errno); 251 + 252 + ret = _chdir(dir); 253 + ok(!ret, "_chdir returned %d, error %d\n", ret, errno); 254 + 255 + p = _getcwd(buf, sizeof(buf)); 256 + ok(p == buf, "_getcwd returned %p, errno %d\n", p, errno); 257 + p = strrchr(p, '\\'); 258 + ok(!!p, "strrchr returned NULL, buf = %s\n", debugstr_a(buf)); 259 + ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf)); 260 + 261 + p = _getdcwd(_getdrive(), buf, sizeof(buf)); 262 + ok(p == buf, "_getdcwd returned %p, errno %d\n", p, errno); 263 + p = strrchr(p, '\\'); 264 + ok(!!p, "strrchr returned NULL, buf = %s\n", debugstr_a(buf)); 265 + ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf)); 266 + 267 + p = _fullpath(buf, NULL, sizeof(buf)); 268 + ok(p == buf, "_fulpath returned %p, errno %d\n", p, errno); 269 + p = strrchr(p, '\\'); 270 + ok(!!p, "strrchr returned NULL, buf = %s\n", debugstr_a(buf)); 271 + ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf)); 272 + 273 + f = fopen(file, "w"); 274 + ok(!!f, "fopen returned %d, error %d\n", ret, errno); 275 + fclose(f); 276 + 277 + ret = access(file, 0); 278 + ok(!ret, "access returned %d, error %d\n", ret, errno); 279 + 280 + ret = _stat64(file, &stat); 281 + ok(!ret, "_stat64 returned %d, error %d\n", ret, errno); 282 + 283 + ret = _chmod(file, _S_IREAD | _S_IWRITE); 284 + ok(!ret, "_chmod returned %d, error %d\n", ret, errno); 285 + 286 + strcpy(file2, file); 287 + strcat(file2, "XXXXXX"); 288 + p = _mktemp(file2); 289 + ok(p == file2, "_mktemp returned %p, file2 %p, errno %d\n", p, file2, errno); 290 + ok(!memcmp(file2, file, sizeof(file) - 1), "file2 = %s\n", debugstr_a(file2)); 291 + ok(p[ARRAY_SIZE(file) - 1] == 'a', "p = %s\n", debugstr_a(p)); 292 + f = fopen(p, "w"); 293 + ok(!!f, "fopen returned %d, error %d\n", ret, errno); 294 + fclose(f); 295 + 296 + strcpy(buf, file); 297 + strcat(buf, "XXXXXX"); 298 + p = _mktemp(buf); 299 + ok(p == buf, "_mktemp returned %p, buf %p, errno %d\n", p, buf, errno); 300 + ok(!memcmp(buf, file, sizeof(file) - 1), "buf = %s\n", debugstr_a(buf)); 301 + ok(p[ARRAY_SIZE(file) - 1] == 'b', "p = %s\n", debugstr_a(p)); 302 + 303 + strcpy(buf, file); 304 + strcat(buf, "XXXXXX"); 305 + ret = _mktemp_s(buf, sizeof(buf)); 306 + ok(!memcmp(buf, file, sizeof(file) - 1), "buf = %s\n", debugstr_a(buf)); 307 + ok(buf[ARRAY_SIZE(file) - 1] == 'b', "buf = %s\n", debugstr_a(buf)); 308 + 309 + strcpy(buf, file); 310 + strcat(buf, "*"); 311 + fdata32.name[0] = 'x'; 312 + hfind = _findfirst32(buf, &fdata32); 313 + ok(hfind != -1, "_findfirst32 returned %Id, errno %d\n", hfind, errno); 314 + ok(!memcmp(file, fdata32.name, sizeof(file) - 1), "fdata32.name = %s\n", debugstr_a(fdata32.name)); 315 + 316 + fdata32.name[0] = 'x'; 317 + ret = _findnext32(hfind, &fdata32); 318 + ok(!ret, "_findnext32 returned %d, errno %d\n", ret, errno); 319 + ok(!memcmp(file, fdata32.name, sizeof(file) - 1), "fdata32.name = %s\n", debugstr_a(fdata32.name)); 320 + ret = _findclose(hfind); 321 + ok(!ret, "_findclose returned %d, errno %d\n", ret, errno); 322 + 323 + 324 + strcpy(buf, file); 325 + strcat(buf, "*"); 326 + fdata64.name[0] = 'x'; 327 + hfind = _findfirst64(buf, &fdata64); 328 + ok(hfind != -1, "_findfirst64 returned %Id, errno %d\n", hfind, errno); 329 + ok(!memcmp(file, fdata64.name, sizeof(file) - 1), "fdata64.name = %s\n", debugstr_a(fdata64.name)); 330 + 331 + fdata64.name[0] = 'x'; 332 + ret = _findnext64(hfind, &fdata64); 333 + ok(!ret, "_findnext64 returned %d, errno %d\n", ret, errno); 334 + ok(!memcmp(file, fdata64.name, sizeof(file) - 1), "fdata64.name = %s\n", debugstr_a(fdata64.name)); 335 + ret = _findclose(hfind); 336 + ok(!ret, "_findclose returned %d, errno %d\n", ret, errno); 337 + 338 + strcpy(buf, file); 339 + strcat(buf, "*"); 340 + fdata64i32.name[0] = 'x'; 341 + hfind = _findfirst64i32(buf, &fdata64i32); 342 + ok(hfind != -1, "_findfirst64i32 returned %Id, errno %d\n", hfind, errno); 343 + ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); 344 + 345 + fdata64i32.name[0] = 'x'; 346 + ret = _findnext64i32(hfind, &fdata64i32); 347 + ok(!ret, "_findnext64i32 returned %d, errno %d\n", ret, errno); 348 + ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); 349 + ret = _findclose(hfind); 350 + ok(!ret, "_findclose returned %d, errno %d\n", ret, errno); 351 + 352 + ret = remove(file2); 353 + ok(!ret, "remove returned %d, errno %d\n", ret, errno); 354 + 355 + buf[0] = 'x'; 356 + _searchenv(file, "env", buf); 357 + p = strrchr(buf, '\\'); 358 + ok(!!p, "buf = %s\n", debugstr_a(buf)); 359 + ok(!strcmp(p + 1, file), "buf = %s\n", debugstr_a(buf)); 360 + 361 + ret = _wunlink(fileW); 362 + ok(!ret, "_wunlink returned %d, errno %d\n", ret, errno); 363 + 364 + ret = _chdir(".."); 365 + ok(!ret, "_chdir returned %d, error %d\n", ret, errno); 366 + 367 + ret = _wrmdir(dirW); 368 + ok(!ret, "_wrmdir returned %d, errno %d\n", ret, errno); 369 + 370 + p = _tempnam(NULL, file); 371 + ok(!!p, "_tempnam returned NULL, error %d\n", errno); 372 + q = strrchr(p, '\\'); 373 + ok(!!q, "_tempnam returned %s\n", debugstr_a(p)); 374 + todo_wine ok(!memcmp(q + 1, file, ARRAY_SIZE(file) - 1), 375 + "incorrect file prefix: %s\n", debugstr_a(p)); 376 + free(p); 377 + 378 + /* native implementation mixes CP_UTF8 and CP_ACP */ 379 + if (GetACP() != CP_UTF8) 380 + { 381 + /* make sure wide environment is initialized (works around bug in native) */ 382 + ret = _putenv("__wine_env_test=test"); 383 + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); 384 + _wgetenv(L"__wine_env_test"); 385 + 386 + strcpy(buf, file); 387 + strcat(buf, "=test"); 388 + ret = _putenv(buf); 389 + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); 390 + /* bug in native _wgetenv/_putenv implementation */ 391 + pW = _wgetenv(fileW); 392 + ok(!pW, "environment variable name was converted\n"); 393 + bufW[0] = 0; 394 + ret = GetEnvironmentVariableW(fileW, bufW, ARRAY_SIZE(bufW)); 395 + todo_wine ok(ret, "GetEnvironmentVariableW returned error %lu\n", GetLastError()); 396 + todo_wine ok(!wcscmp(bufW, L"test"), "bufW = %s\n", debugstr_w(bufW)); 397 + strcpy(buf, file); 398 + strcat(buf, "="); 399 + ret = _putenv(buf); 400 + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); 401 + 402 + strcpy(buf, "__wine_env_test="); 403 + strcat(buf, file); 404 + ret = _putenv(buf); 405 + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); 406 + /* bug in native _wgetenv/_putenv implementation */ 407 + pW = _wgetenv(L"__wine_env_test"); 408 + ok(wcscmp(pW, fileW), "pW = %s\n", debugstr_w(pW)); 409 + ret = GetEnvironmentVariableW(L"__wine_env_test", bufW, ARRAY_SIZE(bufW)); 410 + ok(ret, "GetEnvironmentVariableW returned error %lu\n", GetLastError()); 411 + todo_wine ok(!wcscmp(bufW, fileW), "bufW = %s\n", debugstr_w(bufW)); 412 + 413 + wcscpy(bufW, L"__wine_env_test="); 414 + wcscat(bufW, fileW); 415 + ret = _wputenv(bufW); 416 + ok(!ret, "_wputenv returned %d, errno %d\n", ret, errno); 417 + p = getenv("__wine_env_test"); 418 + ok(strcmp(p, file), "environment variable was converted\n"); 419 + strcpy(buf, "__wine_env_test="); 420 + ret = _putenv(buf); 421 + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); 422 + } 423 + 424 + strcpy(buf, "__wine_env_test="); 425 + strcat(buf, file); 426 + env[0] = buf; 427 + env[1] = NULL; 428 + hproc = _spawnle(_P_NOWAIT, argv0, argv0, "file", "utf8", file, NULL, env); 429 + ok(hproc != -1, "_spawnl returned %Id, errno %d\n", hproc, errno); 430 + wait_child_process((HANDLE)hproc); 431 + CloseHandle((HANDLE)hproc); 432 + 433 + setlocale(LC_ALL, "C"); 434 + } 435 + 436 + static void test_utf8_argument(void) 437 + { 438 + static const WCHAR nameW[] = L"file\x0119\x015b\x0107.a"; 439 + const WCHAR *cmdline = GetCommandLineW(), *p; 440 + WCHAR buf[256]; 441 + DWORD ret; 442 + 443 + p = wcsrchr(cmdline, ' '); 444 + ok(!!p, "cmdline = %s\n", debugstr_w(cmdline)); 445 + ok(!wcscmp(p + 1, nameW), "cmdline = %s\n", debugstr_w(cmdline)); 446 + 447 + ret = GetEnvironmentVariableW(L"__wine_env_test", buf, ARRAY_SIZE(buf)); 448 + ok(ret, "GetEnvironmentVariableW returned error %lu\n", GetLastError()); 449 + if (GetACP() == CP_UTF8) 450 + ok(!wcscmp(buf, nameW), "__wine_env_test = %s\n", debugstr_w(buf)); 451 + else 452 + ok(wcscmp(buf, nameW), "environment was converted\n"); 453 + } 454 + 455 + START_TEST(file) 456 + { 457 + int arg_c; 458 + char** arg_v; 459 + 460 + arg_c = winetest_get_mainargs(&arg_v); 461 + if(arg_c == 4 && !strcmp(arg_v[2], "utf8")) 462 + { 463 + test_utf8_argument(); 464 + return; 465 + } 466 + 467 + test_std_stream_buffering(); 468 + test_iobuf_layout(); 469 + test_std_stream_open(); 470 + test_fopen(); 471 + test_utf8(arg_v[0]); 472 + }
+1761
modules/rostests/winetests/ucrtbase/misc.c
··· 1 + /* 2 + * Copyright 2016 Nikolay Sivov for CodeWeavers 3 + * 4 + * This library is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU Lesser General Public 6 + * License as published by the Free Software Foundation; either 7 + * version 2.1 of the License, or (at your option) any later version. 8 + * 9 + * This library is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * Lesser General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU Lesser General Public 15 + * License along with this library; if not, write to the Free Software 16 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 + */ 18 + 19 + #include <errno.h> 20 + #include <stdarg.h> 21 + #include <stdlib.h> 22 + #include <wchar.h> 23 + #include <stdio.h> 24 + #include <math.h> 25 + #include <float.h> 26 + #include <io.h> 27 + #include <sys/stat.h> 28 + #include <share.h> 29 + #include <fcntl.h> 30 + #include <time.h> 31 + #include <direct.h> 32 + #include <locale.h> 33 + #include <process.h> 34 + #include <fenv.h> 35 + #include <malloc.h> 36 + 37 + #include <windef.h> 38 + #include <winbase.h> 39 + #include "wine/test.h" 40 + 41 + #define DEFINE_EXPECT(func) \ 42 + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 43 + 44 + #define SET_EXPECT(func) \ 45 + expect_ ## func = TRUE 46 + 47 + #define CHECK_EXPECT2(func) \ 48 + do { \ 49 + ok(expect_ ##func, "unexpected call " #func "\n"); \ 50 + called_ ## func = TRUE; \ 51 + }while(0) 52 + 53 + #define CHECK_EXPECT(func) \ 54 + do { \ 55 + CHECK_EXPECT2(func); \ 56 + expect_ ## func = FALSE; \ 57 + }while(0) 58 + 59 + #define CHECK_CALLED(func) \ 60 + do { \ 61 + ok(called_ ## func, "expected " #func "\n"); \ 62 + expect_ ## func = called_ ## func = FALSE; \ 63 + }while(0) 64 + 65 + static inline double __port_min_pos_double(void) 66 + { 67 + static const UINT64 __min_pos_double = 0x10000000000000; 68 + return *(const double *)&__min_pos_double; 69 + } 70 + 71 + static inline double __port_max_double(void) 72 + { 73 + static const UINT64 __max_double = 0x7FEFFFFFFFFFFFFF; 74 + return *(const double *)&__max_double; 75 + } 76 + 77 + DEFINE_EXPECT(global_invalid_parameter_handler); 78 + DEFINE_EXPECT(thread_invalid_parameter_handler); 79 + 80 + typedef struct { 81 + const char *short_wday[7]; 82 + const char *wday[7]; 83 + const char *short_mon[12]; 84 + const char *mon[12]; 85 + const char *am; 86 + const char *pm; 87 + const char *short_date; 88 + const char *date; 89 + const char *time; 90 + int unk; 91 + int refcount; 92 + const wchar_t *short_wdayW[7]; 93 + const wchar_t *wdayW[7]; 94 + const wchar_t *short_monW[12]; 95 + const wchar_t *monW[12]; 96 + const wchar_t *amW; 97 + const wchar_t *pmW; 98 + const wchar_t *short_dateW; 99 + const wchar_t *dateW; 100 + const wchar_t *timeW; 101 + const wchar_t *locnameW; 102 + } __lc_time_data; 103 + 104 + typedef void (__cdecl *_se_translator_function)(unsigned int code, struct _EXCEPTION_POINTERS *info); 105 + 106 + static LONGLONG crt_init_end; 107 + 108 + _ACRTIMP int __cdecl _o__initialize_onexit_table(_onexit_table_t *table); 109 + _ACRTIMP int __cdecl _o__register_onexit_function(_onexit_table_t *table, _onexit_t func); 110 + _ACRTIMP int __cdecl _o__execute_onexit_table(_onexit_table_t *table); 111 + _ACRTIMP void *__cdecl _o_malloc(size_t); 112 + _se_translator_function __cdecl _set_se_translator(_se_translator_function func); 113 + void** __cdecl __current_exception(void); 114 + int* __cdecl __processing_throw(void); 115 + 116 + #define _MAX__TIME64_T (((__time64_t)0x00000007 << 32) | 0x93406FFF) 117 + 118 + static void test__initialize_onexit_table(void) 119 + { 120 + _onexit_table_t table, table2; 121 + int ret; 122 + 123 + ret = _initialize_onexit_table(NULL); 124 + ok(ret == -1, "got %d\n", ret); 125 + 126 + memset(&table, 0, sizeof(table)); 127 + ret = _initialize_onexit_table(&table); 128 + ok(ret == 0, "got %d\n", ret); 129 + ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 130 + table._first, table._last, table._end); 131 + 132 + memset(&table2, 0, sizeof(table2)); 133 + ret = _initialize_onexit_table(&table2); 134 + ok(ret == 0, "got %d\n", ret); 135 + ok(table2._first == table._first, "got %p, %p\n", table2._first, table._first); 136 + ok(table2._last == table._last, "got %p, %p\n", table2._last, table._last); 137 + ok(table2._end == table._end, "got %p, %p\n", table2._end, table._end); 138 + 139 + memset(&table2, 0, sizeof(table2)); 140 + ret = _o__initialize_onexit_table(&table2); 141 + ok(ret == 0, "got %d\n", ret); 142 + ok(table2._first == table._first, "got %p, %p\n", table2._first, table._first); 143 + ok(table2._last == table._last, "got %p, %p\n", table2._last, table._last); 144 + ok(table2._end == table._end, "got %p, %p\n", table2._end, table._end); 145 + 146 + /* uninitialized table */ 147 + table._first = table._last = table._end = (void*)0x123; 148 + ret = _initialize_onexit_table(&table); 149 + ok(ret == 0, "got %d\n", ret); 150 + ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 151 + table._first, table._last, table._end); 152 + ok(table._first != (void*)0x123, "got %p\n", table._first); 153 + 154 + table._first = (void*)0x123; 155 + table._last = (void*)0x456; 156 + table._end = (void*)0x123; 157 + ret = _initialize_onexit_table(&table); 158 + ok(ret == 0, "got %d\n", ret); 159 + ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 160 + table._first, table._last, table._end); 161 + ok(table._first != (void*)0x123, "got %p\n", table._first); 162 + 163 + table._first = (void*)0x123; 164 + table._last = (void*)0x456; 165 + table._end = (void*)0x789; 166 + ret = _initialize_onexit_table(&table); 167 + ok(ret == 0, "got %d\n", ret); 168 + ok(table._first == (void*)0x123, "got %p\n", table._first); 169 + ok(table._last == (void*)0x456, "got %p\n", table._last); 170 + ok(table._end == (void*)0x789, "got %p\n", table._end); 171 + 172 + table._first = NULL; 173 + table._last = (void*)0x456; 174 + table._end = NULL; 175 + ret = _initialize_onexit_table(&table); 176 + ok(ret == 0, "got %d\n", ret); 177 + ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 178 + table._first, table._last, table._end); 179 + } 180 + 181 + static int g_onexit_called; 182 + static int CDECL onexit_func(void) 183 + { 184 + g_onexit_called++; 185 + return 0; 186 + } 187 + 188 + static int CDECL onexit_func2(void) 189 + { 190 + ok(g_onexit_called == 0, "got %d\n", g_onexit_called); 191 + g_onexit_called++; 192 + return 0; 193 + } 194 + 195 + static void test__register_onexit_function(void) 196 + { 197 + _onexit_table_t table; 198 + _PVFV *f; 199 + int ret; 200 + 201 + memset(&table, 0, sizeof(table)); 202 + ret = _initialize_onexit_table(&table); 203 + ok(ret == 0, "got %d\n", ret); 204 + 205 + ret = _register_onexit_function(NULL, NULL); 206 + ok(ret == -1, "got %d\n", ret); 207 + 208 + ret = _register_onexit_function(NULL, onexit_func); 209 + ok(ret == -1, "got %d\n", ret); 210 + 211 + f = table._last; 212 + ret = _register_onexit_function(&table, NULL); 213 + ok(ret == 0, "got %d\n", ret); 214 + ok(f != table._last, "got %p, initial %p\n", table._last, f); 215 + 216 + ret = _register_onexit_function(&table, onexit_func); 217 + ok(ret == 0, "got %d\n", ret); 218 + 219 + f = table._last; 220 + ret = _register_onexit_function(&table, onexit_func); 221 + ok(ret == 0, "got %d\n", ret); 222 + ok(f != table._last, "got %p, initial %p\n", table._last, f); 223 + 224 + f = table._last; 225 + ret = _o__register_onexit_function(&table, NULL); 226 + ok(ret == 0, "got %d\n", ret); 227 + ok(f != table._last, "got %p, initial %p\n", table._last, f); 228 + 229 + f = table._last; 230 + ret = _o__register_onexit_function(&table, onexit_func); 231 + ok(ret == 0, "got %d\n", ret); 232 + ok(f != table._last, "got %p, initial %p\n", table._last, f); 233 + 234 + ret = _execute_onexit_table(&table); 235 + ok(ret == 0, "got %d\n", ret); 236 + } 237 + 238 + static void test__execute_onexit_table(void) 239 + { 240 + _onexit_table_t table; 241 + int ret; 242 + 243 + ret = _execute_onexit_table(NULL); 244 + ok(ret == -1, "got %d\n", ret); 245 + 246 + memset(&table, 0, sizeof(table)); 247 + ret = _initialize_onexit_table(&table); 248 + ok(ret == 0, "got %d\n", ret); 249 + 250 + /* execute empty table */ 251 + ret = _execute_onexit_table(&table); 252 + ok(ret == 0, "got %d\n", ret); 253 + 254 + /* same function registered multiple times */ 255 + ret = _register_onexit_function(&table, onexit_func); 256 + ok(ret == 0, "got %d\n", ret); 257 + 258 + ret = _register_onexit_function(&table, NULL); 259 + ok(ret == 0, "got %d\n", ret); 260 + 261 + ret = _register_onexit_function(&table, onexit_func); 262 + ok(ret == 0, "got %d\n", ret); 263 + 264 + ret = _o__register_onexit_function(&table, onexit_func); 265 + ok(ret == 0, "got %d\n", ret); 266 + 267 + ok(table._first != table._end, "got %p, %p\n", table._first, table._end); 268 + g_onexit_called = 0; 269 + ret = _execute_onexit_table(&table); 270 + ok(ret == 0, "got %d\n", ret); 271 + ok(g_onexit_called == 3, "got %d\n", g_onexit_called); 272 + ok(table._first == table._end, "got %p, %p\n", table._first, table._end); 273 + 274 + ret = _register_onexit_function(&table, onexit_func); 275 + ok(ret == 0, "got %d\n", ret); 276 + 277 + ret = _register_onexit_function(&table, NULL); 278 + ok(ret == 0, "got %d\n", ret); 279 + 280 + ret = _register_onexit_function(&table, onexit_func); 281 + ok(ret == 0, "got %d\n", ret); 282 + 283 + ret = _o__register_onexit_function(&table, onexit_func); 284 + ok(ret == 0, "got %d\n", ret); 285 + 286 + ok(table._first != table._end, "got %p, %p\n", table._first, table._end); 287 + g_onexit_called = 0; 288 + ret = _o__execute_onexit_table(&table); 289 + ok(ret == 0, "got %d\n", ret); 290 + ok(g_onexit_called == 3, "got %d\n", g_onexit_called); 291 + ok(table._first == table._end, "got %p, %p\n", table._first, table._end); 292 + 293 + /* execute again, table is already empty */ 294 + g_onexit_called = 0; 295 + ret = _execute_onexit_table(&table); 296 + ok(ret == 0, "got %d\n", ret); 297 + ok(g_onexit_called == 0, "got %d\n", g_onexit_called); 298 + 299 + /* check call order */ 300 + memset(&table, 0, sizeof(table)); 301 + ret = _initialize_onexit_table(&table); 302 + ok(ret == 0, "got %d\n", ret); 303 + 304 + ret = _register_onexit_function(&table, onexit_func); 305 + ok(ret == 0, "got %d\n", ret); 306 + 307 + ret = _register_onexit_function(&table, onexit_func2); 308 + ok(ret == 0, "got %d\n", ret); 309 + 310 + g_onexit_called = 0; 311 + ret = _execute_onexit_table(&table); 312 + ok(ret == 0, "got %d\n", ret); 313 + ok(g_onexit_called == 2, "got %d\n", g_onexit_called); 314 + } 315 + 316 + static void test___fpe_flt_rounds(void) 317 + { 318 + unsigned int cfp = _controlfp(0, 0); 319 + int ret; 320 + 321 + if(!cfp) { 322 + skip("_controlfp not supported\n"); 323 + return; 324 + } 325 + 326 + ok((_controlfp(_RC_NEAR, _RC_CHOP) & _RC_CHOP) == _RC_NEAR, "_controlfp(_RC_NEAR, _RC_CHOP) failed\n"); 327 + ret = __fpe_flt_rounds(); 328 + ok(ret == 1, "__fpe_flt_rounds returned %d\n", ret); 329 + 330 + ok((_controlfp(_RC_UP, _RC_CHOP) & _RC_CHOP) == _RC_UP, "_controlfp(_RC_UP, _RC_CHOP) failed\n"); 331 + ret = __fpe_flt_rounds(); 332 + ok(ret == 2 || broken(ret == 3) /* w1064v1507 */, "__fpe_flt_rounds returned %d\n", ret); 333 + 334 + ok((_controlfp(_RC_DOWN, _RC_CHOP) & _RC_CHOP) == _RC_DOWN, "_controlfp(_RC_DOWN, _RC_CHOP) failed\n"); 335 + ret = __fpe_flt_rounds(); 336 + ok(ret == 3 || broken(ret == 2) /* w1064v1507 */, "__fpe_flt_rounds returned %d\n", ret); 337 + 338 + ok((_controlfp(_RC_CHOP, _RC_CHOP) & _RC_CHOP) == _RC_CHOP, "_controlfp(_RC_CHOP, _RC_CHOP) failed\n"); 339 + ret = __fpe_flt_rounds(); 340 + ok(ret == 0, "__fpe_flt_rounds returned %d\n", ret); 341 + 342 + _controlfp(cfp, _MCW_EM | _MCW_RC | _MCW_PC); 343 + } 344 + 345 + static void test__control87_2(void) 346 + { 347 + #ifdef __i386__ 348 + unsigned int x86_cw_init, sse2_cw_init, x86_cw, sse2_cw, r; 349 + 350 + r = __control87_2(0, 0, &x86_cw_init, &sse2_cw_init); 351 + ok(r == 1, "__control87_2 returned %d\n", r); 352 + 353 + r = __control87_2(0, _EM_INVALID, &x86_cw, NULL); 354 + ok(r == 1, "__control87_2 returned %d\n", r); 355 + ok(x86_cw == (x86_cw_init & ~_EM_INVALID), "x86_cw = %x, x86_cw_init = %x\n", x86_cw, x86_cw_init); 356 + 357 + r = __control87_2(0, 0, &x86_cw, &sse2_cw); 358 + ok(r == 1, "__control87_2 returned %d\n", r); 359 + ok(x86_cw == (x86_cw_init & ~_EM_INVALID), "x86_cw = %x, x86_cw_init = %x\n", x86_cw, x86_cw_init); 360 + ok(sse2_cw == sse2_cw_init, "sse2_cw = %x, sse2_cw_init = %x\n", sse2_cw, sse2_cw_init); 361 + 362 + r = _control87(0, 0); 363 + ok(r == (x86_cw | sse2_cw | _EM_AMBIGUOUS), "r = %x, expected %x\n", 364 + r, x86_cw | sse2_cw | _EM_AMBIGUOUS); 365 + 366 + _control87(x86_cw_init, ~0); 367 + #endif 368 + } 369 + 370 + static void __cdecl global_invalid_parameter_handler( 371 + const wchar_t *expression, const wchar_t *function, 372 + const wchar_t *file, unsigned line, uintptr_t arg) 373 + { 374 + CHECK_EXPECT2(global_invalid_parameter_handler); 375 + } 376 + 377 + static void __cdecl thread_invalid_parameter_handler( 378 + const wchar_t *expression, const wchar_t *function, 379 + const wchar_t *file, unsigned line, uintptr_t arg) 380 + { 381 + CHECK_EXPECT(thread_invalid_parameter_handler); 382 + } 383 + 384 + static void test_invalid_parameter_handler(void) 385 + { 386 + _invalid_parameter_handler ret; 387 + 388 + ret = _get_invalid_parameter_handler(); 389 + ok(!ret, "ret != NULL\n"); 390 + 391 + ret = _get_thread_local_invalid_parameter_handler(); 392 + ok(!ret, "ret != NULL\n"); 393 + 394 + ret = _set_thread_local_invalid_parameter_handler(thread_invalid_parameter_handler); 395 + ok(!ret, "ret != NULL\n"); 396 + 397 + ret = _get_thread_local_invalid_parameter_handler(); 398 + ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret); 399 + 400 + ret = _get_invalid_parameter_handler(); 401 + ok(!ret, "ret != NULL\n"); 402 + 403 + ret = _set_invalid_parameter_handler(global_invalid_parameter_handler); 404 + ok(!ret, "ret != NULL\n"); 405 + 406 + ret = _get_invalid_parameter_handler(); 407 + ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret); 408 + 409 + ret = _get_thread_local_invalid_parameter_handler(); 410 + ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret); 411 + 412 + SET_EXPECT(thread_invalid_parameter_handler); 413 + _ltoa_s(0, NULL, 0, 0); 414 + CHECK_CALLED(thread_invalid_parameter_handler); 415 + 416 + ret = _set_thread_local_invalid_parameter_handler(NULL); 417 + ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret); 418 + 419 + SET_EXPECT(global_invalid_parameter_handler); 420 + _ltoa_s(0, NULL, 0, 0); 421 + CHECK_CALLED(global_invalid_parameter_handler); 422 + 423 + ret = _set_invalid_parameter_handler(NULL); 424 + ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret); 425 + 426 + ret = _set_invalid_parameter_handler(global_invalid_parameter_handler); 427 + ok(!ret, "ret != NULL\n"); 428 + } 429 + 430 + static void test__get_narrow_winmain_command_line(char *path) 431 + { 432 + PROCESS_INFORMATION proc; 433 + STARTUPINFOA startup; 434 + char cmd[MAX_PATH+32]; 435 + char *ret, *cmdline, *name; 436 + int len; 437 + 438 + ret = _get_narrow_winmain_command_line(); 439 + cmdline = GetCommandLineA(); 440 + len = strlen(cmdline); 441 + ok(ret>cmdline && ret<cmdline+len, "ret = %p, cmdline = %p (len = %d)\n", ret, cmdline, len); 442 + 443 + if(!path) { 444 + ok(!lstrcmpA(ret, "\"misc\" cmd"), "ret = %s\n", ret); 445 + return; 446 + } 447 + 448 + for(len = strlen(path); len>0; len--) 449 + if(path[len-1]=='\\' || path[len-1]=='/') break; 450 + if(len) name = path+len; 451 + else name = path; 452 + 453 + sprintf(cmd, "\"\"%c\"\"\"%s\" \t \"misc\" cmd", name[0], name+1); 454 + memset(&startup, 0, sizeof(startup)); 455 + startup.cb = sizeof(startup); 456 + CreateProcessA(path, cmd, NULL, NULL, TRUE, 457 + CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, 458 + NULL, NULL, &startup, &proc); 459 + wait_child_process(proc.hProcess); 460 + CloseHandle(proc.hProcess); 461 + CloseHandle(proc.hThread); 462 + } 463 + 464 + static void test__sopen_dispatch(void) 465 + { 466 + int ret, fd; 467 + char *tempf; 468 + 469 + tempf = _tempnam(".", "wne"); 470 + 471 + fd = 0; 472 + ret = _sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 0); 473 + ok(!ret, "got %d\n", ret); 474 + ok(fd > 0, "got fd %d\n", fd); 475 + _close(fd); 476 + unlink(tempf); 477 + 478 + SET_EXPECT(global_invalid_parameter_handler); 479 + fd = 0; 480 + ret = _sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 1); 481 + ok(ret == EINVAL, "got %d\n", ret); 482 + ok(fd == -1, "got fd %d\n", fd); 483 + CHECK_CALLED(global_invalid_parameter_handler); 484 + if (fd > 0) 485 + { 486 + _close(fd); 487 + unlink(tempf); 488 + } 489 + 490 + free(tempf); 491 + } 492 + 493 + static void test__sopen_s(void) 494 + { 495 + int ret, fd; 496 + char *tempf; 497 + 498 + tempf = _tempnam(".", "wne"); 499 + 500 + fd = 0; 501 + ret = _sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0); 502 + ok(!ret, "got %d\n", ret); 503 + ok(fd > 0, "got fd %d\n", fd); 504 + _close(fd); 505 + unlink(tempf); 506 + 507 + /* _open() does not validate pmode */ 508 + fd = _open(tempf, _O_CREAT, 0xff); 509 + ok(fd > 0, "got fd %d\n", fd); 510 + _close(fd); 511 + unlink(tempf); 512 + 513 + /* _sopen_s() invokes invalid parameter handler on invalid pmode */ 514 + SET_EXPECT(global_invalid_parameter_handler); 515 + fd = 0; 516 + ret = _sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0xff); 517 + ok(ret == EINVAL, "got %d\n", ret); 518 + ok(fd == -1, "got fd %d\n", fd); 519 + CHECK_CALLED(global_invalid_parameter_handler); 520 + 521 + free(tempf); 522 + } 523 + 524 + static void test_lldiv(void) 525 + { 526 + lldiv_t r; 527 + 528 + r = lldiv(((LONGLONG)0x111 << 32) + 0x222, (LONGLONG)1 << 32); 529 + ok(r.quot == 0x111, "quot = %s\n", wine_dbgstr_longlong(r.quot)); 530 + ok(r.rem == 0x222, "rem = %s\n", wine_dbgstr_longlong(r.rem)); 531 + 532 + r = lldiv(((LONGLONG)0x69CF0012 << 32) + 0x0033E78A, 0x30); 533 + ok(r.quot == ((LONGLONG)0x02345000 << 32) + 0x600114D2, "quot = %s\n", wine_dbgstr_longlong(r.quot)); 534 + ok(r.rem == 0x2A, "rem = %s\n", wine_dbgstr_longlong(r.rem)); 535 + 536 + r = lldiv(((LONGLONG)0x243A5678 << 32) + 0x9ABCDEF0, (LONGLONG)0x12 << 48); 537 + ok(r.quot == 0x0203, "quot = %s\n", wine_dbgstr_longlong(r.quot)); 538 + ok(r.rem == ((LONGLONG)0x00045678 << 32) + 0x9ABCDEF0, "rem = %s\n", wine_dbgstr_longlong(r.rem)); 539 + } 540 + 541 + static void test_isblank(void) 542 + { 543 + int c, r; 544 + 545 + for(c = 0; c <= 0xff; c++) { 546 + if(c == '\t') { 547 + ok(!_isctype(c, _BLANK), "tab shouldn't be blank\n"); 548 + ok(isblank(c), "%d should be blank\n", c); 549 + r = _isblank_l(c, NULL); 550 + ok(!r || broken(r == _BLANK), "tab shouldn't be blank (got %x)\n", r); 551 + } else if(c == ' ') { 552 + ok(_isctype(c, _BLANK), "space should be blank\n"); 553 + ok(isblank(c), "%d should be blank\n", c); 554 + r = _isblank_l(c, NULL); 555 + ok(r == _BLANK, "space should be blank (got %x)\n", r); 556 + } else { 557 + ok(!_isctype(c, _BLANK), "%d shouldn't be blank\n", c); 558 + ok(!isblank(c), "%d shouldn't be blank\n", c); 559 + ok(!_isblank_l(c, NULL), "%d shouldn't be blank\n", c); 560 + } 561 + } 562 + 563 + for(c = 0; c <= 0xffff; c++) { 564 + if(c == '\t' || c == ' ' || c == 0x3000 || c == 0xfeff) { 565 + if(c == '\t') 566 + ok(!_iswctype_l(c, _BLANK, NULL), "tab shouldn't be blank\n"); 567 + else 568 + ok(_iswctype_l(c, _BLANK, NULL), "%d should be blank\n", c); 569 + ok(iswblank(c), "%d should be blank\n", c); 570 + ok(_iswblank_l(c, NULL), "%d should be blank\n", c); 571 + } else { 572 + ok(!_iswctype_l(c, _BLANK, NULL), "%d shouldn't be blank\n", c); 573 + ok(!iswblank(c), "%d shouldn't be blank\n", c); 574 + ok(!_iswblank_l(c, NULL), "%d shouldn't be blank\n", c); 575 + } 576 + } 577 + } 578 + 579 + static struct _exception exception; 580 + 581 + static int CDECL matherr_callback(struct _exception *e) 582 + { 583 + exception = *e; 584 + 585 + if (!strcmp(e->name, "acos") && e->arg1 == 2) 586 + e->retval = -1; 587 + return 0; 588 + } 589 + 590 + static void test_math_errors(void) 591 + { 592 + const struct { 593 + char func[16]; 594 + double x; 595 + int error; 596 + int exception; 597 + } testsd[] = { 598 + {"_logb", -INFINITY, -1, -1}, 599 + {"_logb", -1, -1, -1}, 600 + {"_logb", 0, ERANGE, _SING}, 601 + {"_logb", INFINITY, -1, -1}, 602 + {"acos", -INFINITY, EDOM, _DOMAIN}, 603 + {"acos", -2, EDOM, _DOMAIN}, 604 + {"acos", -1, -1, -1}, 605 + {"acos", 1, -1, -1}, 606 + {"acos", 2, EDOM, _DOMAIN}, 607 + {"acos", INFINITY, EDOM, _DOMAIN}, 608 + {"acosh", -INFINITY, EDOM, -1}, 609 + {"acosh", 0, EDOM, -1}, 610 + {"acosh", 1, -1, -1}, 611 + {"acosh", INFINITY, -1, -1}, 612 + {"asin", -INFINITY, EDOM, _DOMAIN}, 613 + {"asin", -2, EDOM, _DOMAIN}, 614 + {"asin", -1, -1, -1}, 615 + {"asin", 1, -1, -1}, 616 + {"asin", 2, EDOM, _DOMAIN}, 617 + {"asin", INFINITY, EDOM, _DOMAIN}, 618 + {"asinh", -INFINITY, -1, -1}, 619 + {"asinh", INFINITY, -1, -1}, 620 + {"atan", -INFINITY, -1, -1}, 621 + {"atan", 0, -1, -1}, 622 + {"atan", INFINITY, -1, -1}, 623 + {"atanh", -INFINITY, EDOM, -1}, 624 + {"atanh", -2, EDOM, -1}, 625 + {"atanh", -1, ERANGE, -1}, 626 + {"atanh", 1, ERANGE, -1}, 627 + {"atanh", 2, EDOM, -1}, 628 + {"atanh", INFINITY, EDOM, -1}, 629 + {"cos", -INFINITY, EDOM, _DOMAIN}, 630 + {"cos", INFINITY, EDOM, _DOMAIN}, 631 + {"cosh", -INFINITY, -1, -1}, 632 + {"cosh", 0, -1, -1}, 633 + {"cosh", INFINITY, -1, -1}, 634 + {"exp", -INFINITY, -1, -1}, 635 + {"exp", -1e100, -1, _UNDERFLOW}, 636 + {"exp", 1e100, ERANGE, _OVERFLOW}, 637 + {"exp", INFINITY, -1, -1}, 638 + {"exp2", -INFINITY, -1, -1}, 639 + {"exp2", -1e100, -1, -1}, 640 + {"exp2", 1e100, ERANGE, -1}, 641 + {"exp2", INFINITY, -1, -1}, 642 + {"expm1", -INFINITY, -1, -1}, 643 + {"expm1", INFINITY, -1, -1}, 644 + {"log", -INFINITY, EDOM, _DOMAIN}, 645 + {"log", -1, EDOM, _DOMAIN}, 646 + {"log", 0, ERANGE, _SING}, 647 + {"log", INFINITY, -1, -1}, 648 + {"log10", -INFINITY, EDOM, _DOMAIN}, 649 + {"log10", -1, EDOM, _DOMAIN}, 650 + {"log10", 0, ERANGE, _SING}, 651 + {"log10", INFINITY, -1, -1}, 652 + {"log1p", -INFINITY, EDOM, -1}, 653 + {"log1p", -2, EDOM, -1}, 654 + {"log1p", -1, ERANGE, -1}, 655 + {"log1p", INFINITY, -1, -1}, 656 + {"log2", INFINITY, -1, -1}, 657 + {"sin", -INFINITY, EDOM, _DOMAIN}, 658 + {"sin", INFINITY, EDOM, _DOMAIN}, 659 + {"sinh", -INFINITY, -1, -1}, 660 + {"sinh", 0, -1, -1}, 661 + {"sinh", INFINITY, -1, -1}, 662 + {"sqrt", -INFINITY, EDOM, _DOMAIN}, 663 + {"sqrt", -1, EDOM, _DOMAIN}, 664 + {"sqrt", 0, -1, -1}, 665 + {"sqrt", INFINITY, -1, -1}, 666 + {"tan", -INFINITY, EDOM, _DOMAIN}, 667 + {"tan", -M_PI_2, -1, -1}, 668 + {"tan", M_PI_2, -1, -1}, 669 + {"tan", INFINITY, EDOM, _DOMAIN}, 670 + {"tanh", -INFINITY, -1, -1}, 671 + {"tanh", 0, -1, -1}, 672 + {"tanh", INFINITY, -1, -1}, 673 + }; 674 + const struct { 675 + char func[16]; 676 + double a; 677 + double b; 678 + int error; 679 + int exception; 680 + } tests2d[] = { 681 + {"atan2", -INFINITY, 0, -1, -1}, 682 + {"atan2", 0, 0, -1, -1}, 683 + {"atan2", INFINITY, 0, -1, -1}, 684 + {"atan2", 0, -INFINITY, -1, -1}, 685 + {"atan2", 0, INFINITY, -1, -1}, 686 + {"pow", -INFINITY, -2, -1, -1}, 687 + {"pow", -INFINITY, -1, -1, -1}, 688 + {"pow", -INFINITY, 0, -1, -1}, 689 + {"pow", -INFINITY, 1, -1, -1}, 690 + {"pow", -INFINITY, 2, -1, -1}, 691 + {"pow", -1e100, -10, -1, _UNDERFLOW}, 692 + {"pow", -1e100, 10, ERANGE, _OVERFLOW}, 693 + {"pow", -1, 1.5, EDOM, _DOMAIN}, 694 + {"pow", 0, -2, ERANGE, _SING}, 695 + {"pow", 0, -1, ERANGE, _SING}, 696 + {"pow", 0.5, -INFINITY, -1, -1}, 697 + {"pow", 0.5, INFINITY, -1, -1}, 698 + {"pow", 2, -INFINITY, -1, -1}, 699 + {"pow", 2, -1e100, -1, _UNDERFLOW}, 700 + {"pow", 2, 1e100, ERANGE, _OVERFLOW}, 701 + {"pow", 2, INFINITY, -1, -1}, 702 + {"pow", 1e100, -10, -1, _UNDERFLOW}, 703 + {"pow", 1e100, 10, ERANGE, _OVERFLOW}, 704 + {"pow", INFINITY, -2, -1, -1}, 705 + {"pow", INFINITY, -1, -1, -1}, 706 + {"pow", INFINITY, 0, -1, -1}, 707 + {"pow", INFINITY, 1, -1, -1}, 708 + {"pow", INFINITY, 2, -1, -1}, 709 + }; 710 + const struct { 711 + char func[16]; 712 + double a; 713 + double b; 714 + double c; 715 + int error; 716 + int exception; 717 + } tests3d[] = { 718 + /* 0 * inf --> EDOM */ 719 + {"fma", INFINITY, 0, 0, EDOM, -1}, 720 + {"fma", 0, INFINITY, 0, EDOM, -1}, 721 + /* inf - inf -> EDOM */ 722 + {"fma", INFINITY, 1, -INFINITY, EDOM, -1}, 723 + {"fma", -INFINITY, 1, INFINITY, EDOM, -1}, 724 + {"fma", 1, INFINITY, -INFINITY, EDOM, -1}, 725 + {"fma", 1, -INFINITY, INFINITY, EDOM, -1}, 726 + /* NaN */ 727 + {"fma", NAN, 0, 0, -1, -1}, 728 + {"fma", 0, NAN, 0, -1, -1}, 729 + {"fma", 0, 0, NAN, -1, -1}, 730 + /* over/underflow */ 731 + {"fma", __port_max_double(), __port_max_double(), __port_max_double(), -1, -1}, 732 + {"fma", __port_min_pos_double(), __port_min_pos_double(), 1, -1, -1}, 733 + }; 734 + const struct { 735 + char func[16]; 736 + double a; 737 + long b; 738 + int error; 739 + int exception; 740 + } testsdl[] = { 741 + {"_scalb", -INFINITY, 1, -1, -1}, 742 + {"_scalb", -1e100, 1, -1, -1}, 743 + {"_scalb", 0, 1, -1, -1}, 744 + {"_scalb", 1e100, 1, -1, -1}, 745 + {"_scalb", INFINITY, 1, -1, -1}, 746 + {"_scalb", 1, 1e9, ERANGE, _OVERFLOW}, 747 + {"ldexp", -INFINITY, 1, -1, -1}, 748 + {"ldexp", -1e100, 1, -1, -1}, 749 + {"ldexp", 0, 1, -1, -1}, 750 + {"ldexp", 1e100, 1, -1, -1}, 751 + {"ldexp", INFINITY, 1, -1, -1}, 752 + {"ldexp", 1, -1e9, -1, _UNDERFLOW}, 753 + {"ldexp", 1, 1e9, ERANGE, _OVERFLOW}, 754 + }; 755 + double (CDECL *p_funcd)(double); 756 + double (CDECL *p_func2d)(double, double); 757 + double (CDECL *p_func3d)(double, double, double); 758 + double (CDECL *p_funcdl)(double, long); 759 + HMODULE module; 760 + double d; 761 + int i; 762 + 763 + __setusermatherr(matherr_callback); 764 + module = GetModuleHandleW(L"ucrtbase.dll"); 765 + 766 + /* necessary so that exp(1e100)==INFINITY on glibc, we can remove this if we change our implementation */ 767 + fesetround(FE_TONEAREST); 768 + 769 + for(i = 0; i < ARRAY_SIZE(testsd); i++) { 770 + p_funcd = (void*)GetProcAddress(module, testsd[i].func); 771 + errno = -1; 772 + exception.type = -1; 773 + p_funcd(testsd[i].x); 774 + ok(errno == testsd[i].error, 775 + "%s(%f) got errno %d\n", testsd[i].func, testsd[i].x, errno); 776 + ok(exception.type == testsd[i].exception, 777 + "%s(%f) got exception type %d\n", testsd[i].func, testsd[i].x, exception.type); 778 + if(exception.type == -1) continue; 779 + ok(exception.arg1 == testsd[i].x, 780 + "%s(%f) got exception arg1 %f\n", testsd[i].func, testsd[i].x, exception.arg1); 781 + } 782 + 783 + for(i = 0; i < ARRAY_SIZE(tests2d); i++) { 784 + p_func2d = (void*)GetProcAddress(module, tests2d[i].func); 785 + errno = -1; 786 + exception.type = -1; 787 + p_func2d(tests2d[i].a, tests2d[i].b); 788 + ok(errno == tests2d[i].error, 789 + "%s(%f, %f) got errno %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, errno); 790 + ok(exception.type == tests2d[i].exception, 791 + "%s(%f, %f) got exception type %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.type); 792 + if(exception.type == -1) continue; 793 + ok(exception.arg1 == tests2d[i].a, 794 + "%s(%f, %f) got exception arg1 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg1); 795 + ok(exception.arg2 == tests2d[i].b, 796 + "%s(%f, %f) got exception arg2 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg2); 797 + } 798 + 799 + for(i = 0; i < ARRAY_SIZE(tests3d); i++) { 800 + p_func3d = (void*)GetProcAddress(module, tests3d[i].func); 801 + errno = -1; 802 + exception.type = -1; 803 + p_func3d(tests3d[i].a, tests3d[i].b, tests3d[i].c); 804 + ok(errno == tests3d[i].error || errno == -1, /* native is not setting errno if FMA3 is supported */ 805 + "%s(%f, %f, %f) got errno %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, errno); 806 + ok(exception.type == tests3d[i].exception, 807 + "%s(%f, %f, %f) got exception type %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.type); 808 + if(exception.type == -1) continue; 809 + ok(exception.arg1 == tests3d[i].a, 810 + "%s(%f, %f, %f) got exception arg1 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg1); 811 + ok(exception.arg2 == tests3d[i].b, 812 + "%s(%f, %f, %f) got exception arg2 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg2); 813 + } 814 + 815 + for(i = 0; i < ARRAY_SIZE(testsdl); i++) { 816 + p_funcdl = (void*)GetProcAddress(module, testsdl[i].func); 817 + errno = -1; 818 + exception.type = -1; 819 + p_funcdl(testsdl[i].a, testsdl[i].b); 820 + ok(errno == testsdl[i].error, 821 + "%s(%f, %ld) got errno %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, errno); 822 + ok(exception.type == testsdl[i].exception, 823 + "%s(%f, %ld) got exception type %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.type); 824 + if(exception.type == -1) continue; 825 + ok(exception.arg1 == testsdl[i].a, 826 + "%s(%f, %ld) got exception arg1 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg1); 827 + ok(exception.arg2 == testsdl[i].b, 828 + "%s(%f, %ld) got exception arg2 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg2); 829 + } 830 + 831 + d = acos(2.0); 832 + ok(d == -1.0, "failed to change log10 return value: %e\n", d); 833 + } 834 + 835 + static void test_asctime(void) 836 + { 837 + const struct tm epoch = { 0, 0, 0, 1, 0, 70, 4, 0, 0 }; 838 + char *ret; 839 + 840 + ret = asctime(&epoch); 841 + ok(!strcmp(ret, "Thu Jan 1 00:00:00 1970\n"), "asctime returned %s\n", ret); 842 + } 843 + 844 + static void test_strftime(void) 845 + { 846 + const struct { 847 + const char *format; 848 + const char *ret; 849 + struct tm tm; 850 + BOOL todo_value; 851 + BOOL todo_handler; 852 + } tests[] = { 853 + {"%C", "", { 0, 0, 0, 1, 0, -2000, 4, 0, 0 }}, 854 + {"%C", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }}, 855 + {"%C", "00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }}, 856 + {"%C", "18", { 0, 0, 0, 1, 0, -1, 4, 0, 0 }}, 857 + {"%C", "19", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 858 + {"%C", "99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }}, 859 + {"%C", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }}, 860 + {"%d", "", { 0, 0, 0, 0, 0, 70, 4, 0, 0 }}, 861 + {"%d", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 862 + {"%d", "31", { 0, 0, 0, 31, 0, 70, 4, 0, 0 }}, 863 + {"%d", "", { 0, 0, 0, 32, 0, 70, 4, 0, 0 }}, 864 + {"%D", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }}, 865 + {"%D", "01/01/00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }}, 866 + {"%D", "01/01/99", { 0, 0, 0, 1, 0, -1, 4, 0, 0 }}, 867 + {"%D", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 868 + {"%D", "01/01/99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }}, 869 + {"%D", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }}, 870 + {"%#D", "1/1/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 871 + {"%e", "", { 0, 0, 0, 0, 0, 70, 4, 0, 0 }}, 872 + {"%e", " 1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 873 + {"%e", "31", { 0, 0, 0, 31, 0, 70, 4, 0, 0 }}, 874 + {"%e", "", { 0, 0, 0, 32, 0, 70, 4, 0, 0 }}, 875 + {"%#e", "1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 876 + {"%F", "1970-01-01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 877 + {"%#F", "1970-1-1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 878 + {"%R", "00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 879 + {"%#R", "0:0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 880 + {"%T", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 881 + {"%#T", "0:0:0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 882 + {"%u", "", { 0, 0, 0, 1, 0, 117, -1, 0, 0 }}, 883 + {"%u", "7", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 884 + {"%u", "1", { 0, 0, 0, 1, 0, 117, 1, 0, 0 }}, 885 + {"%u", "6", { 0, 0, 0, 1, 0, 117, 6, 0, 0 }}, 886 + {"%u", "", { 0, 0, 0, 1, 0, 117, 7, 0, 0 }}, 887 + {"%h", "Jan", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 888 + {"%I", "", { 0, 0, -1, 1, 0, 70, 4, 0, 0 }}, 889 + {"%I", "12", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 890 + {"%I", "01", { 0, 0, 1, 1, 0, 70, 4, 0, 0 }}, 891 + {"%I", "11", { 0, 0, 11, 1, 0, 70, 4, 0, 0 }}, 892 + {"%I", "12", { 0, 0, 12, 1, 0, 70, 4, 0, 0 }}, 893 + {"%I", "01", { 0, 0, 13, 1, 0, 70, 4, 0, 0 }}, 894 + {"%I", "11", { 0, 0, 23, 1, 0, 70, 4, 0, 0 }}, 895 + {"%I", "", { 0, 0, 24, 1, 0, 70, 4, 0, 0 }}, 896 + {"%n", "\n", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 897 + {"%r", "12:00:00 AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 898 + {"%r", "02:00:00 PM", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }}, 899 + {"%#r", "12:0:0 AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 900 + {"%#r", "2:0:0 PM", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }}, 901 + {"%t", "\t", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 902 + {"%g", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }}, 903 + {"%g", "", { 0, 0, 0, 1, 0, -1901, 3, 364, 0 }}, 904 + {"%g", "00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }}, 905 + {"%g", "70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 906 + {"%g", "71", { 0, 0, 0, 2, 0, 72, 0, 1, 0 }}, 907 + {"%g", "72", { 0, 0, 0, 3, 0, 72, 1, 2, 0 }}, 908 + {"%g", "16", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 909 + {"%g", "99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }}, 910 + {"%g", "00", { 0, 0, 0, 1, 0, 8099, 3, 364, 0 }}, 911 + {"%g", "", { 0, 0, 0, 1, 0, 8100, 0, 0, 0 }}, 912 + {"%g", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }}, 913 + {"%G", "1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 914 + {"%G", "1971", { 0, 0, 0, 2, 0, 72, 0, 1, 0 }}, 915 + {"%G", "1972", { 0, 0, 0, 3, 0, 72, 1, 2, 0 }}, 916 + {"%G", "2016", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 917 + {"%V", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 918 + {"%V", "52", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 919 + {"%V", "53", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }}, 920 + {"%y", "", { 0, 0, 0, 0, 0, -1901, 0, 0, 0 }}, 921 + {"%y", "00", { 0, 0, 0, 0, 0, -1900, 0, 0, 0 }}, 922 + {"%y", "99", { 0, 0, 0, 0, 0, 8099, 0, 0, 0 }}, 923 + {"%y", "", { 0, 0, 0, 0, 0, 8100, 0, 0, 0 }}, 924 + {"%c", "Thu Jan 1 00:00:00 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 925 + {"%c", "Thu Feb 30 00:00:00 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 926 + {"%#c", "Thursday, January 01, 1970 00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 927 + {"%#c", "Thursday, February 30, 1970 00:00:00", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 928 + {"%x", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 929 + {"%x", "02/30/70", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 930 + {"%#x", "Thursday, January 01, 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 931 + {"%#x", "Thursday, February 30, 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 932 + {"%#x", "", { 0, 0, 0, 30, 1, 70, 7, 0, 0 }}, 933 + {"%#x", "", { 0, 0, 0, 30, 12, 70, 4, 0, 0 }}, 934 + {"%X", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 935 + {"%X", "14:00:00", { 0, 0, 14, 1, 0, 70, 4, 0, 0 }}, 936 + {"%X", "23:59:60", { 60, 59, 23, 1, 0, 70, 4, 0, 0 }}, 937 + }; 938 + 939 + const struct { 940 + const char *format; 941 + const char *ret; 942 + const wchar_t *short_date; 943 + const wchar_t *date; 944 + const wchar_t *time; 945 + struct tm tm; 946 + BOOL todo; 947 + } tests_td[] = { 948 + { "%c", "x z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 949 + { "%#c", "y z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 950 + { "%X", "M1", 0, 0, L"MMM", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 951 + { "%X", "1", 0, 0, L"h", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 952 + { "%X", "01", 0, 0, L"hh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 953 + { "%X", "h01", 0, 0, L"hhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 954 + { "%X", "hh01", 0, 0, L"hhhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 955 + { "%X", "1", 0, 0, L"H", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 956 + { "%X", "01", 0, 0, L"HH", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 957 + { "%X", "H13", 0, 0, L"HHH", { 0, 0, 13, 1, 0, 70, 0, 0, 0 }}, 958 + { "%X", "0", 0, 0, L"m", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 959 + { "%X", "00", 0, 0, L"mm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 960 + { "%X", "m00", 0, 0, L"mmm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 961 + { "%X", "0", 0, 0, L"s", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 962 + { "%X", "00", 0, 0, L"ss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 963 + { "%X", "s00", 0, 0, L"sss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 964 + { "%X", "T", 0, 0, L"t", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 965 + { "%X", "TAM", 0, 0, L"tt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 966 + { "%X", "TAM", 0, 0, L"ttttttttt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 967 + { "%X", "TAM", 0, 0, L"a", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 968 + { "%X", "TAM", 0, 0, L"aaaaa", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 969 + { "%X", "TAM", 0, 0, L"A", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 970 + { "%X", "TAM", 0, 0, L"AAAAA", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 971 + { "%x", "1", L"d", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 972 + { "%x", "01", L"dd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 973 + { "%x", "D1", L"ddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 974 + { "%x", "Day1", L"dddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 975 + { "%x", "dDay1", L"ddddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 976 + { "%x", "1", L"M", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 977 + { "%x", "01", L"MM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 978 + { "%x", "M1", L"MMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 979 + { "%x", "Mon1", L"MMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 980 + { "%x", "MMon1", L"MMMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 981 + { "%x", "y", L"y", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 982 + { "%x", "70", L"yy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 983 + { "%x", "y70", L"yyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 984 + { "%x", "1970", L"yyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 985 + { "%x", "y1970", L"yyyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 986 + { "%x", "ggggggggggg", L"ggggggggggg", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 987 + { "%#x", "1", 0, L"d", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 988 + { "%#x", "01", 0, L"dd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 989 + { "%#x", "D1", 0, L"ddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 990 + { "%#x", "Day1", 0, L"dddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 991 + { "%#x", "dDay1", 0, L"ddddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 992 + { "%#x", "1", 0, L"M", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 993 + { "%#x", "01", 0, L"MM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 994 + { "%#x", "M1", 0, L"MMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 995 + { "%#x", "Mon1", 0, L"MMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 996 + { "%#x", "MMon1", 0, L"MMMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 997 + { "%#x", "y", 0, L"y", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 998 + { "%#x", "70", 0, L"yy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 999 + { "%#x", "y70", 0, L"yyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1000 + { "%#x", "1970", 0, L"yyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1001 + { "%#x", "y1970", 0, L"yyyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1002 + { "%r", "z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1003 + }; 1004 + 1005 + const struct { 1006 + int year; 1007 + int yday; 1008 + const char *ret[7]; 1009 + } tests_yweek[] = { 1010 + { 100, 0, { "99 52", "00 01", "00 01", "00 01", "00 01", "99 53", "99 52" }}, 1011 + { 100, 1, { "99 52", "00 01", "00 01", "00 01", "00 01", "00 01", "99 53" }}, 1012 + { 100, 2, { "99 53", "00 01", "00 01", "00 01", "00 01", "00 01", "00 01" }}, 1013 + { 100, 3, { "00 01", "00 01", "00 01", "00 01", "00 01", "00 01", "00 01" }}, 1014 + { 100, 4, { "00 01", "00 02", "00 01", "00 01", "00 01", "00 01", "00 01" }}, 1015 + { 100, 5, { "00 01", "00 02", "00 02", "00 01", "00 01", "00 01", "00 01" }}, 1016 + { 100, 6, { "00 01", "00 02", "00 02", "00 02", "00 01", "00 01", "00 01" }}, 1017 + { 100, 358, { "00 51", "00 52", "00 52", "00 52", "00 52", "00 52", "00 51" }}, 1018 + { 100, 359, { "00 51", "00 52", "00 52", "00 52", "00 52", "00 52", "00 52" }}, 1019 + { 100, 360, { "00 52", "00 52", "00 52", "00 52", "00 52", "00 52", "00 52" }}, 1020 + { 100, 361, { "00 52", "00 53", "00 52", "00 52", "00 52", "00 52", "00 52" }}, 1021 + { 100, 362, { "00 52", "00 53", "00 53", "00 52", "00 52", "00 52", "00 52" }}, 1022 + { 100, 363, { "00 52", "01 01", "00 53", "00 53", "00 52", "00 52", "00 52" }}, 1023 + { 100, 364, { "00 52", "01 01", "01 01", "00 53", "00 53", "00 52", "00 52" }}, 1024 + { 100, 365, { "00 52", "01 01", "01 01", "01 01", "00 53", "00 53", "00 52" }}, 1025 + { 101, 0, { "00 52", "01 01", "01 01", "01 01", "01 01", "00 53", "00 53" }}, 1026 + { 101, 1, { "00 53", "01 01", "01 01", "01 01", "01 01", "01 01", "00 53" }}, 1027 + { 101, 2, { "00 53", "01 01", "01 01", "01 01", "01 01", "01 01", "01 01" }}, 1028 + { 101, 3, { "01 01", "01 01", "01 01", "01 01", "01 01", "01 01", "01 01" }}, 1029 + { 101, 4, { "01 01", "01 02", "01 01", "01 01", "01 01", "01 01", "01 01" }}, 1030 + { 101, 5, { "01 01", "01 02", "01 02", "01 01", "01 01", "01 01", "01 01" }}, 1031 + { 101, 6, { "01 01", "01 02", "01 02", "01 02", "01 01", "01 01", "01 01" }}, 1032 + { 101, 358, { "01 51", "01 52", "01 52", "01 52", "01 52", "01 52", "01 51" }}, 1033 + { 101, 359, { "01 51", "01 52", "01 52", "01 52", "01 52", "01 52", "01 52" }}, 1034 + { 101, 360, { "01 52", "01 52", "01 52", "01 52", "01 52", "01 52", "01 52" }}, 1035 + { 101, 361, { "01 52", "01 53", "01 52", "01 52", "01 52", "01 52", "01 52" }}, 1036 + { 101, 362, { "01 52", "02 01", "01 53", "01 52", "01 52", "01 52", "01 52" }}, 1037 + { 101, 363, { "01 52", "02 01", "02 01", "01 53", "01 52", "01 52", "01 52" }}, 1038 + { 101, 364, { "01 52", "02 01", "02 01", "02 01", "01 53", "01 52", "01 52" }}, 1039 + }; 1040 + 1041 + __lc_time_data time_data = { 1042 + { "d1", "d2", "d3", "d4", "d5", "d6", "d7" }, 1043 + { "day1", "day2", "day3", "day4", "day5", "day6", "day7" }, 1044 + { "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9", "m10", "m11", "m12" }, 1045 + { "mon1", "mon2", "mon3", "mon4", "mon5", "mon6", "mon7", "mon8", "mon9", "mon10", "mon11", "mon12" }, 1046 + "tam", "tpm", 0, 0, 0, 1, 0, 1047 + { L"D1", L"D2", L"D3", L"D4", L"D5", L"D6", L"D7" }, 1048 + { L"Day1", L"Day2", L"Day3", L"Day4", L"Day5", L"Day6", L"Day7" }, 1049 + { L"M1", L"M2", L"M3", L"M4", L"M5", L"M6", L"M7", L"M8", L"M9", L"M10", L"M11", L"M12" }, 1050 + { L"Mon1", L"Mon2", L"Mon3", L"Mon4", L"Mon5", L"Mon6", L"Mon7", L"Mon8", L"Mon9", L"Mon10", L"Mon11", L"Mon12" }, 1051 + L"TAM", L"TPM" 1052 + }; 1053 + 1054 + const struct tm epoch = { 0, 0, 0, 1, 0, 70, 4, 0, 0 }; 1055 + struct tm tm_yweek = { 0, 0, 0, 1, 0, 70, 0, 0, 0 }; 1056 + char buf[256]; 1057 + int i, ret=0; 1058 + 1059 + for (i=0; i<ARRAY_SIZE(tests); i++) 1060 + { 1061 + todo_wine_if(tests[i].todo_handler) { 1062 + if (!tests[i].ret[0]) 1063 + SET_EXPECT(global_invalid_parameter_handler); 1064 + ret = strftime(buf, sizeof(buf), tests[i].format, &tests[i].tm); 1065 + if (!tests[i].ret[0]) 1066 + CHECK_CALLED(global_invalid_parameter_handler); 1067 + } 1068 + 1069 + todo_wine_if(tests[i].todo_value) { 1070 + ok(ret == strlen(tests[i].ret), "%d) ret = %d\n", i, ret); 1071 + ok(!strcmp(buf, tests[i].ret), "%d) buf = \"%s\", expected \"%s\"\n", 1072 + i, buf, tests[i].ret); 1073 + } 1074 + } 1075 + 1076 + ret = strftime(buf, sizeof(buf), "%z", &epoch); 1077 + ok(ret == 5, "expected 5, got %d\n", ret); 1078 + ok((buf[0] == '+' || buf[0] == '-') && 1079 + isdigit(buf[1]) && isdigit(buf[2]) && 1080 + isdigit(buf[3]) && isdigit(buf[4]), "got %s\n", buf); 1081 + 1082 + for (i=0; i<ARRAY_SIZE(tests_td); i++) 1083 + { 1084 + time_data.short_dateW = tests_td[i].short_date; 1085 + time_data.dateW = tests_td[i].date; 1086 + time_data.timeW = tests_td[i].time; 1087 + ret = _Strftime(buf, sizeof(buf), tests_td[i].format, &tests_td[i].tm, &time_data); 1088 + ok(ret == strlen(buf), "%d) ret = %d\n", i, ret); 1089 + todo_wine_if(tests_td[i].todo) { 1090 + ok(!strcmp(buf, tests_td[i].ret), "%d) buf = \"%s\", expected \"%s\"\n", 1091 + i, buf, tests_td[i].ret); 1092 + } 1093 + } 1094 + 1095 + for (i=0; i<ARRAY_SIZE(tests_yweek); i++) 1096 + { 1097 + int j; 1098 + tm_yweek.tm_year = tests_yweek[i].year; 1099 + tm_yweek.tm_yday = tests_yweek[i].yday; 1100 + for (j=0; j<7; j++) 1101 + { 1102 + tm_yweek.tm_wday = j; 1103 + strftime(buf, sizeof(buf), "%g %V", &tm_yweek); 1104 + ok(!strcmp(buf, tests_yweek[i].ret[j]), "%d,%d) buf = \"%s\", expected \"%s\"\n", 1105 + i, j, buf, tests_yweek[i].ret[j]); 1106 + } 1107 + } 1108 + 1109 + if(!setlocale(LC_ALL, "fr-FR")) { 1110 + win_skip("fr-FR locale not available\n"); 1111 + return; 1112 + } 1113 + ret = strftime(buf, sizeof(buf), "%c", &epoch); 1114 + ok(ret == 19, "ret = %d\n", ret); 1115 + ok(!strcmp(buf, "01/01/1970 00:00:00"), "buf = \"%s\", expected \"%s\"\n", buf, "01/01/1970 00:00:00"); 1116 + ret = strftime(buf, sizeof(buf), "%r", &epoch); 1117 + ok(ret == 8, "ret = %d\n", ret); 1118 + ok(!strcmp(buf, "00:00:00"), "buf = \"%s\", expected \"%s\"\n", buf, "00:00:00"); 1119 + setlocale(LC_ALL, "C"); 1120 + 1121 + if(!setlocale(LC_TIME, "Japanese_Japan.932")) { 1122 + win_skip("Japanese_Japan.932 locale not available\n"); 1123 + return; 1124 + } 1125 + ret = strftime(buf, sizeof(buf), "%a", &epoch); 1126 + ok(ret == 2 || broken(ret == 1), "ret = %d\n", ret); 1127 + ok(!strcmp(buf, "\x96\xd8"), "buf = %s, expected \"\\x96\\xd8\"\n", wine_dbgstr_an(buf, 2)); 1128 + setlocale(LC_ALL, "C"); 1129 + } 1130 + 1131 + static LONG* get_failures_counter(HANDLE *map) 1132 + { 1133 + *map = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 1134 + 0, sizeof(LONG), "winetest_failures_counter"); 1135 + return MapViewOfFile(*map, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LONG)); 1136 + } 1137 + 1138 + static void free_failures_counter(LONG *mem, HANDLE map) 1139 + { 1140 + UnmapViewOfFile(mem); 1141 + CloseHandle(map); 1142 + } 1143 + 1144 + static void set_failures_counter(LONG add) 1145 + { 1146 + HANDLE failures_map; 1147 + LONG *failures; 1148 + 1149 + failures = get_failures_counter(&failures_map); 1150 + *failures = add; 1151 + free_failures_counter(failures, failures_map); 1152 + } 1153 + 1154 + static void test_exit(const char *argv0) 1155 + { 1156 + PROCESS_INFORMATION proc; 1157 + STARTUPINFOA startup = {0}; 1158 + char path[MAX_PATH]; 1159 + HANDLE failures_map, exit_event, quick_exit_event; 1160 + LONG *failures; 1161 + DWORD ret; 1162 + 1163 + exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event"); 1164 + quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event"); 1165 + 1166 + failures = get_failures_counter(&failures_map); 1167 + sprintf(path, "%s misc exit", argv0); 1168 + startup.cb = sizeof(startup); 1169 + CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc); 1170 + ret = WaitForSingleObject(proc.hProcess, INFINITE); 1171 + ok(ret == WAIT_OBJECT_0, "child process wait failed\n"); 1172 + GetExitCodeProcess(proc.hProcess, &ret); 1173 + ok(ret == 1, "child process exited with code %ld\n", ret); 1174 + CloseHandle(proc.hProcess); 1175 + CloseHandle(proc.hThread); 1176 + ok(!*failures, "%ld tests failed in child process\n", *failures); 1177 + free_failures_counter(failures, failures_map); 1178 + 1179 + 1180 + ret = WaitForSingleObject(exit_event, 0); 1181 + ok(ret == WAIT_OBJECT_0, "exit_event was not set (%lx)\n", ret); 1182 + ret = WaitForSingleObject(quick_exit_event, 0); 1183 + ok(ret == WAIT_TIMEOUT, "quick_exit_event should not have be set (%lx)\n", ret); 1184 + 1185 + CloseHandle(exit_event); 1186 + CloseHandle(quick_exit_event); 1187 + } 1188 + 1189 + static int atexit_called; 1190 + 1191 + static void CDECL at_exit_func1(void) 1192 + { 1193 + HANDLE exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event"); 1194 + 1195 + ok(exit_event != NULL, "CreateEvent failed: %ld\n", GetLastError()); 1196 + ok(atexit_called == 1, "atexit_called = %d\n", atexit_called); 1197 + atexit_called++; 1198 + SetEvent(exit_event); 1199 + CloseHandle(exit_event); 1200 + set_failures_counter(winetest_get_failures()); 1201 + } 1202 + 1203 + static void CDECL at_exit_func2(void) 1204 + { 1205 + ok(!atexit_called, "atexit_called = %d\n", atexit_called); 1206 + atexit_called++; 1207 + set_failures_counter(winetest_get_failures()); 1208 + } 1209 + 1210 + static int atquick_exit_called; 1211 + 1212 + static void CDECL at_quick_exit_func1(void) 1213 + { 1214 + HANDLE quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event"); 1215 + 1216 + ok(quick_exit_event != NULL, "CreateEvent failed: %ld\n", GetLastError()); 1217 + ok(atquick_exit_called == 1, "atquick_exit_called = %d\n", atquick_exit_called); 1218 + atquick_exit_called++; 1219 + SetEvent(quick_exit_event); 1220 + CloseHandle(quick_exit_event); 1221 + set_failures_counter(winetest_get_failures()); 1222 + } 1223 + 1224 + static void CDECL at_quick_exit_func2(void) 1225 + { 1226 + ok(!atquick_exit_called, "atquick_exit_called = %d\n", atquick_exit_called); 1227 + atquick_exit_called++; 1228 + set_failures_counter(winetest_get_failures()); 1229 + } 1230 + 1231 + static void test_call_exit(void) 1232 + { 1233 + ok(!_crt_atexit(at_exit_func1), "_crt_atexit failed\n"); 1234 + ok(!_crt_atexit(at_exit_func2), "_crt_atexit failed\n"); 1235 + 1236 + ok(!_crt_at_quick_exit(at_quick_exit_func1), "_crt_at_quick_exit failed\n"); 1237 + ok(!_crt_at_quick_exit(at_quick_exit_func2), "_crt_at_quick_exit failed\n"); 1238 + 1239 + set_failures_counter(winetest_get_failures()); 1240 + exit(1); 1241 + } 1242 + 1243 + static void test_call_quick_exit(void) 1244 + { 1245 + ok(!_crt_atexit(at_exit_func1), "_crt_atexit failed\n"); 1246 + ok(!_crt_atexit(at_exit_func2), "_crt_atexit failed\n"); 1247 + 1248 + ok(!_crt_at_quick_exit(at_quick_exit_func1), "_crt_at_quick_exit failed\n"); 1249 + ok(!_crt_at_quick_exit(at_quick_exit_func2), "_crt_at_quick_exit failed\n"); 1250 + 1251 + set_failures_counter(winetest_get_failures()); 1252 + quick_exit(2); 1253 + } 1254 + 1255 + static void test_quick_exit(const char *argv0) 1256 + { 1257 + PROCESS_INFORMATION proc; 1258 + STARTUPINFOA startup = {0}; 1259 + char path[MAX_PATH]; 1260 + HANDLE failures_map, exit_event, quick_exit_event; 1261 + LONG *failures; 1262 + DWORD ret; 1263 + 1264 + exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event"); 1265 + quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event"); 1266 + 1267 + failures = get_failures_counter(&failures_map); 1268 + sprintf(path, "%s misc quick_exit", argv0); 1269 + startup.cb = sizeof(startup); 1270 + CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc); 1271 + ret = WaitForSingleObject(proc.hProcess, INFINITE); 1272 + ok(ret == WAIT_OBJECT_0, "child process wait failed\n"); 1273 + GetExitCodeProcess(proc.hProcess, &ret); 1274 + ok(ret == 2, "child process exited with code %ld\n", ret); 1275 + CloseHandle(proc.hProcess); 1276 + CloseHandle(proc.hThread); 1277 + ok(!*failures, "%ld tests failed in child process\n", *failures); 1278 + free_failures_counter(failures, failures_map); 1279 + 1280 + ret = WaitForSingleObject(quick_exit_event, 0); 1281 + ok(ret == WAIT_OBJECT_0, "quick_exit_event was not set (%lx)\n", ret); 1282 + ret = WaitForSingleObject(exit_event, 0); 1283 + ok(ret == WAIT_TIMEOUT, "exit_event should not have be set (%lx)\n", ret); 1284 + 1285 + CloseHandle(exit_event); 1286 + CloseHandle(quick_exit_event); 1287 + } 1288 + 1289 + static void test__stat32(void) 1290 + { 1291 + static const char test_file[] = "\\stat_file.tst"; 1292 + static const char test_dir[] = "\\stat_dir.tst"; 1293 + 1294 + char path[2*MAX_PATH]; 1295 + struct _stat32 buf; 1296 + int fd, ret; 1297 + DWORD len; 1298 + 1299 + len = GetTempPathA(MAX_PATH, path); 1300 + ok(len, "GetTempPathA failed\n"); 1301 + 1302 + ret = _stat32("c:", &buf); 1303 + ok(ret == -1, "_stat32('c:') returned %d\n", ret); 1304 + ret = _stat32("c:\\", &buf); 1305 + ok(!ret, "_stat32('c:\\') returned %d\n", ret); 1306 + 1307 + memcpy(path+len, test_file, sizeof(test_file)); 1308 + if((fd = open(path, O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE)) >= 0) 1309 + { 1310 + ret = _stat32(path, &buf); 1311 + ok(!ret, "_stat32('%s') returned %d\n", path, ret); 1312 + strcat(path, "\\"); 1313 + ret = _stat32(path, &buf); 1314 + ok(ret, "_stat32('%s') returned %d\n", path, ret); 1315 + close(fd); 1316 + remove(path); 1317 + } 1318 + 1319 + memcpy(path+len, test_dir, sizeof(test_dir)); 1320 + if(!mkdir(path)) 1321 + { 1322 + ret = _stat32(path, &buf); 1323 + ok(!ret, "_stat32('%s') returned %d\n", path, ret); 1324 + strcat(path, "\\"); 1325 + ret = _stat32(path, &buf); 1326 + ok(!ret, "_stat32('%s') returned %d\n", path, ret); 1327 + rmdir(path); 1328 + } 1329 + } 1330 + 1331 + static void test__o_malloc(void) 1332 + { 1333 + void *m; 1334 + size_t s; 1335 + 1336 + m = _o_malloc(1); 1337 + ok(m != NULL, "p__o_malloc(1) returned NULL\n"); 1338 + 1339 + s = _msize(m); 1340 + ok(s == 1, "_msize returned %d\n", (int)s); 1341 + 1342 + free(m); 1343 + } 1344 + 1345 + static void test_clock(void) 1346 + { 1347 + static const int thresh = 100, max_load_delay = 1000; 1348 + int c, expect_min; 1349 + FILETIME cur; 1350 + 1351 + GetSystemTimeAsFileTime(&cur); 1352 + c = clock(); 1353 + 1354 + expect_min = (((LONGLONG)cur.dwHighDateTime << 32) + cur.dwLowDateTime - crt_init_end) / 10000; 1355 + ok(c >= expect_min - thresh && c < expect_min + max_load_delay, "clock() = %d, expected range [%d, %d]\n", 1356 + c, expect_min - thresh, expect_min + max_load_delay); 1357 + } 1358 + 1359 + static void __cdecl se_translator(unsigned int u, EXCEPTION_POINTERS *ep) 1360 + { 1361 + } 1362 + 1363 + static void test_thread_storage(void) 1364 + { 1365 + void **current_exception; 1366 + void *processing_throw; 1367 + 1368 + _set_se_translator(se_translator); 1369 + current_exception = __current_exception(); 1370 + processing_throw = __processing_throw(); 1371 + 1372 + ok(current_exception+2 == processing_throw, 1373 + "current_exception = %p, processing_throw = %p\n", 1374 + current_exception, processing_throw); 1375 + ok(current_exception[-2] == se_translator, 1376 + "can't find se_translator in thread storage\n"); 1377 + } 1378 + 1379 + static unsigned long fenv_encode(unsigned int e) 1380 + { 1381 + ok(!(e & ~FE_ALL_EXCEPT), "incorrect argument: %x\n", e); 1382 + 1383 + #if defined(__i386__) 1384 + return e<<24 | e<<16 | e; 1385 + #elif defined(__x86_64__) 1386 + return e<<24 | e; 1387 + #else 1388 + return e; 1389 + #endif 1390 + } 1391 + 1392 + static void test_fenv(void) 1393 + { 1394 + static const int tests[] = { 1395 + 0, 1396 + FE_INEXACT, 1397 + FE_UNDERFLOW, 1398 + FE_OVERFLOW, 1399 + FE_DIVBYZERO, 1400 + FE_INVALID, 1401 + FE_ALL_EXCEPT, 1402 + }; 1403 + static const struct { 1404 + fexcept_t except; 1405 + unsigned int flag; 1406 + unsigned int get; 1407 + fexcept_t expect; 1408 + } tests2[] = { 1409 + /* except flag get expect */ 1410 + { 0, 0, 0, 0 }, 1411 + { FE_ALL_EXCEPT, FE_INEXACT, 0, 0 }, 1412 + { FE_ALL_EXCEPT, FE_INEXACT, FE_ALL_EXCEPT, FE_INEXACT }, 1413 + { FE_ALL_EXCEPT, FE_INEXACT, FE_INEXACT, FE_INEXACT }, 1414 + { FE_ALL_EXCEPT, FE_INEXACT, FE_OVERFLOW, 0 }, 1415 + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_ALL_EXCEPT }, 1416 + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_INEXACT, FE_INEXACT }, 1417 + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, 0, 0 }, 1418 + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, ~0, FE_ALL_EXCEPT }, 1419 + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, ~FE_ALL_EXCEPT, 0 }, 1420 + { FE_INEXACT, FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_INEXACT }, 1421 + { FE_INEXACT, FE_UNDERFLOW, FE_ALL_EXCEPT, 0 }, 1422 + { FE_UNDERFLOW, FE_INEXACT, FE_ALL_EXCEPT, 0 }, 1423 + { FE_INEXACT|FE_UNDERFLOW, FE_UNDERFLOW, FE_ALL_EXCEPT, FE_UNDERFLOW }, 1424 + { FE_UNDERFLOW, FE_INEXACT|FE_UNDERFLOW, FE_ALL_EXCEPT, FE_UNDERFLOW }, 1425 + }; 1426 + fenv_t env, env2; 1427 + fexcept_t except; 1428 + int i, ret, flags; 1429 + 1430 + _clearfp(); 1431 + 1432 + ret = fegetenv(&env); 1433 + ok(!ret, "fegetenv returned %x\n", ret); 1434 + #if defined(__i386__) || defined(__x86_64__) 1435 + if (env._Fe_ctl >> 24 != (env._Fe_ctl & 0xff)) 1436 + { 1437 + win_skip("fenv_t format not supported (too old ucrtbase)\n"); 1438 + return; 1439 + } 1440 + #endif 1441 + fesetround(FE_UPWARD); 1442 + ok(!env._Fe_stat, "env._Fe_stat = %lx\n", env._Fe_stat); 1443 + ret = fegetenv(&env2); 1444 + ok(!ret, "fegetenv returned %x\n", ret); 1445 + ok(env._Fe_ctl != env2._Fe_ctl, "fesetround didn't change _Fe_ctl (%lx).\n", env._Fe_ctl); 1446 + ret = fesetenv(&env); 1447 + ok(!ret, "fesetenv returned %x\n", ret); 1448 + ret = fegetround(); 1449 + ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret); 1450 + 1451 + except = fenv_encode(FE_ALL_EXCEPT); 1452 + ret = fesetexceptflag(&except, FE_INEXACT|FE_UNDERFLOW); 1453 + ok(!ret, "fesetexceptflag returned %x\n", ret); 1454 + except = fetestexcept(FE_ALL_EXCEPT); 1455 + ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); 1456 + 1457 + ret = feclearexcept(~FE_ALL_EXCEPT); 1458 + ok(!ret, "feclearexceptflag returned %x\n", ret); 1459 + except = fetestexcept(FE_ALL_EXCEPT); 1460 + ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); 1461 + 1462 + /* no crash, but no-op */ 1463 + ret = fesetexceptflag(NULL, 0); 1464 + ok(!ret, "fesetexceptflag returned %x\n", ret); 1465 + except = fetestexcept(FE_ALL_EXCEPT); 1466 + ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); 1467 + 1468 + /* zero clears all */ 1469 + except = 0; 1470 + ret = fesetexceptflag(&except, FE_ALL_EXCEPT); 1471 + ok(!ret, "fesetexceptflag returned %x\n", ret); 1472 + except = fetestexcept(FE_ALL_EXCEPT); 1473 + ok(!except, "expected 0, got %lx\n", except); 1474 + 1475 + ret = fetestexcept(FE_ALL_EXCEPT); 1476 + ok(!ret, "fetestexcept returned %x\n", ret); 1477 + 1478 + flags = 0; 1479 + /* adding bits with flags */ 1480 + for(i=0; i<ARRAY_SIZE(tests); i++) { 1481 + except = fenv_encode(FE_ALL_EXCEPT); 1482 + ret = fesetexceptflag(&except, tests[i]); 1483 + ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); 1484 + 1485 + ret = fetestexcept(tests[i]); 1486 + ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); 1487 + 1488 + flags |= tests[i]; 1489 + ret = fetestexcept(FE_ALL_EXCEPT); 1490 + ok(ret == flags, "Test %d: expected %x, got %x\n", i, flags, ret); 1491 + 1492 + except = ~0; 1493 + ret = fegetexceptflag(&except, ~0); 1494 + ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); 1495 + ok(except == fenv_encode(flags), 1496 + "Test %d: expected %lx, got %lx\n", i, fenv_encode(flags), except); 1497 + 1498 + except = ~0; 1499 + ret = fegetexceptflag(&except, tests[i]); 1500 + ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); 1501 + ok(except == fenv_encode(tests[i]), 1502 + "Test %d: expected %lx, got %lx\n", i, fenv_encode(tests[i]), except); 1503 + } 1504 + 1505 + for(i=0; i<ARRAY_SIZE(tests); i++) { 1506 + ret = feclearexcept(tests[i]); 1507 + ok(!ret, "Test %d: feclearexceptflag returned %x\n", i, ret); 1508 + 1509 + flags &= ~tests[i]; 1510 + except = fetestexcept(tests[i]); 1511 + ok(!except, "Test %d: expected %x, got %lx\n", i, flags, except); 1512 + } 1513 + 1514 + except = fetestexcept(FE_ALL_EXCEPT); 1515 + ok(!except, "expected 0, got %lx\n", except); 1516 + 1517 + /* setting bits with except */ 1518 + for(i=0; i<ARRAY_SIZE(tests); i++) { 1519 + except = fenv_encode(tests[i]); 1520 + ret = fesetexceptflag(&except, FE_ALL_EXCEPT); 1521 + ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); 1522 + 1523 + ret = fetestexcept(tests[i]); 1524 + ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); 1525 + 1526 + ret = fetestexcept(FE_ALL_EXCEPT); 1527 + ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); 1528 + } 1529 + 1530 + for(i=0; i<ARRAY_SIZE(tests2); i++) { 1531 + _clearfp(); 1532 + 1533 + except = fenv_encode(tests2[i].except); 1534 + ret = fesetexceptflag(&except, tests2[i].flag); 1535 + ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); 1536 + 1537 + ret = fetestexcept(tests2[i].get); 1538 + ok(ret == tests2[i].expect, "Test %d: expected %lx, got %x\n", i, tests2[i].expect, ret); 1539 + } 1540 + 1541 + ret = feclearexcept(FE_ALL_EXCEPT); 1542 + ok(!ret, "feclearexceptflag returned %x\n", ret); 1543 + except = fetestexcept(FE_ALL_EXCEPT); 1544 + ok(!except, "expected 0, got %lx\n", except); 1545 + } 1546 + 1547 + static void test_fopen_exclusive( void ) 1548 + { 1549 + char path[MAX_PATH*2]; 1550 + DWORD len; 1551 + FILE *fp; 1552 + 1553 + len = GetTempPathA(MAX_PATH, path); 1554 + ok(len, "GetTempPathA failed\n"); 1555 + strcat(path, "\\fileexcl.tst"); 1556 + 1557 + SET_EXPECT(global_invalid_parameter_handler); 1558 + fp = fopen(path, "wx"); 1559 + if(called_global_invalid_parameter_handler) 1560 + { 1561 + win_skip("skipping fopen x mode tests.\n"); 1562 + return; 1563 + } 1564 + expect_global_invalid_parameter_handler = FALSE; 1565 + ok(fp != NULL, "creating file with mode wx failed\n"); 1566 + fclose(fp); 1567 + 1568 + fp = fopen(path, "wx"); 1569 + ok(!fp, "overwrote existing file with mode wx\n"); 1570 + unlink(path); 1571 + 1572 + fp = fopen(path, "w+x"); 1573 + ok(fp != NULL, "creating file with mode w+x failed\n"); 1574 + fclose(fp); 1575 + 1576 + fp = fopen(path, "w+x"); 1577 + ok(!fp, "overwrote existing file with mode w+x\n"); 1578 + 1579 + SET_EXPECT(global_invalid_parameter_handler); 1580 + fp = fopen(path, "rx"); 1581 + CHECK_CALLED(global_invalid_parameter_handler); 1582 + ok(!fp, "opening file with mode rx succeeded\n"); 1583 + unlink(path); 1584 + 1585 + SET_EXPECT(global_invalid_parameter_handler); 1586 + fp = fopen(path, "xw"); 1587 + CHECK_CALLED(global_invalid_parameter_handler); 1588 + ok(!fp, "creating file with mode xw succeeded\n"); 1589 + 1590 + fp = fopen(path, "wbx"); 1591 + ok(fp != NULL, "creating file with mode wbx failed\n"); 1592 + fclose(fp); 1593 + unlink(path); 1594 + } 1595 + 1596 + #if defined(__i386__) 1597 + #include "pshpack1.h" 1598 + struct rewind_thunk { 1599 + BYTE push_esp[4]; /* push [esp+0x4] */ 1600 + BYTE call_rewind; /* call */ 1601 + DWORD rewind_addr; /* relative addr of rewind */ 1602 + BYTE pop_eax; /* pop eax */ 1603 + BYTE ret; /* ret */ 1604 + }; 1605 + #include "poppack.h" 1606 + 1607 + static FILE * (CDECL *test_rewind_wrapper)(FILE *fp); 1608 + 1609 + static void test_rewind_i386_abi(void) 1610 + { 1611 + FILE *fp_in, *fp_out; 1612 + 1613 + struct rewind_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 1614 + 1615 + thunk->push_esp[0] = 0xff; 1616 + thunk->push_esp[1] = 0x74; 1617 + thunk->push_esp[2] = 0x24; 1618 + thunk->push_esp[3] = 0x04; 1619 + 1620 + thunk->call_rewind = 0xe8; 1621 + thunk->rewind_addr = (BYTE *) rewind - (BYTE *) (&thunk->rewind_addr + 1); 1622 + 1623 + thunk->pop_eax = 0x58; 1624 + thunk->ret = 0xc3; 1625 + 1626 + test_rewind_wrapper = (void *) thunk; 1627 + 1628 + fp_in = fopen("rewind_abi.tst", "wb"); 1629 + fp_out = test_rewind_wrapper(fp_in); 1630 + ok(fp_in == fp_out, "rewind modified the first argument in the stack\n"); 1631 + 1632 + fclose(fp_in); 1633 + unlink("rewind_abi.tst"); 1634 + } 1635 + #endif 1636 + 1637 + static void test_gmtime64(void) 1638 + { 1639 + struct tm *ptm, tm; 1640 + __time64_t t; 1641 + int ret; 1642 + 1643 + t = -1; 1644 + memset(&tm, 0xcc, sizeof(tm)); 1645 + ptm = _gmtime64(&t); 1646 + ok(!!ptm, "got NULL.\n"); 1647 + ret = _gmtime64_s(&tm, &t); 1648 + ok(!ret, "got %d.\n", ret); 1649 + ok(tm.tm_year == 69 && tm.tm_hour == 23 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n", 1650 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1651 + 1652 + t = -43200; 1653 + memset(&tm, 0xcc, sizeof(tm)); 1654 + ptm = _gmtime64(&t); 1655 + ok(!!ptm, "got NULL.\n"); 1656 + ret = _gmtime64_s(&tm, &t); 1657 + ok(!ret, "got %d.\n", ret); 1658 + ok(tm.tm_year == 69 && tm.tm_hour == 12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n", 1659 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1660 + ptm = _gmtime32((__time32_t *)&t); 1661 + ok(!!ptm, "got NULL.\n"); 1662 + memset(&tm, 0xcc, sizeof(tm)); 1663 + ret = _gmtime32_s(&tm, (__time32_t *)&t); 1664 + ok(!ret, "got %d.\n", ret); 1665 + todo_wine_if(tm.tm_year == 69 && tm.tm_hour == 12) 1666 + ok(tm.tm_year == 70 && tm.tm_hour == -12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n", 1667 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1668 + 1669 + t = -43201; 1670 + ptm = _gmtime64(&t); 1671 + ok(!ptm, "got non-NULL.\n"); 1672 + memset(&tm, 0xcc, sizeof(tm)); 1673 + ret = _gmtime64_s(&tm, &t); 1674 + ok(ret == EINVAL, "got %d.\n", ret); 1675 + ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n", 1676 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1677 + ptm = _gmtime32((__time32_t *)&t); 1678 + ok(!ptm, "got NULL.\n"); 1679 + memset(&tm, 0xcc, sizeof(tm)); 1680 + ret = _gmtime32_s(&tm, (__time32_t *)&t); 1681 + ok(ret == EINVAL, "got %d.\n", ret); 1682 + ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n", 1683 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1684 + 1685 + t = _MAX__TIME64_T + 1605600; 1686 + memset(&tm, 0xcc, sizeof(tm)); 1687 + ptm = _gmtime64(&t); 1688 + ok(!!ptm || broken(!ptm) /* before Win10 1909 */, "got NULL.\n"); 1689 + if (!ptm) 1690 + { 1691 + win_skip("Old gmtime64 limits, skipping tests.\n"); 1692 + return; 1693 + } 1694 + ret = _gmtime64_s(&tm, &t); 1695 + ok(!ret, "got %d.\n", ret); 1696 + ok(tm.tm_year == 1101 && tm.tm_hour == 21 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n", 1697 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1698 + 1699 + t = _MAX__TIME64_T + 1605601; 1700 + ptm = _gmtime64(&t); 1701 + ok(!ptm, "got non-NULL.\n"); 1702 + memset(&tm, 0xcc, sizeof(tm)); 1703 + ret = _gmtime64_s(&tm, &t); 1704 + ok(ret == EINVAL, "got %d.\n", ret); 1705 + ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n", 1706 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1707 + } 1708 + 1709 + static void test__get_heap_handle(void) 1710 + { 1711 + ok((HANDLE)_get_heap_handle() == GetProcessHeap(), "Expected _get_heap_handle() to return GetProcessHeap()\n"); 1712 + } 1713 + 1714 + START_TEST(misc) 1715 + { 1716 + int arg_c; 1717 + char** arg_v; 1718 + FILETIME cur; 1719 + 1720 + GetSystemTimeAsFileTime(&cur); 1721 + crt_init_end = ((LONGLONG)cur.dwHighDateTime << 32) + cur.dwLowDateTime; 1722 + 1723 + arg_c = winetest_get_mainargs(&arg_v); 1724 + if(arg_c == 3) { 1725 + if(!strcmp(arg_v[2], "cmd")) 1726 + test__get_narrow_winmain_command_line(NULL); 1727 + else if(!strcmp(arg_v[2], "exit")) 1728 + test_call_exit(); 1729 + else if(!strcmp(arg_v[2], "quick_exit")) 1730 + test_call_quick_exit(); 1731 + return; 1732 + } 1733 + 1734 + test_invalid_parameter_handler(); 1735 + test__initialize_onexit_table(); 1736 + test__register_onexit_function(); 1737 + test__execute_onexit_table(); 1738 + test___fpe_flt_rounds(); 1739 + test__control87_2(); 1740 + test__get_narrow_winmain_command_line(arg_v[0]); 1741 + test__sopen_dispatch(); 1742 + test__sopen_s(); 1743 + test_lldiv(); 1744 + test_isblank(); 1745 + test_math_errors(); 1746 + test_asctime(); 1747 + test_strftime(); 1748 + test_exit(arg_v[0]); 1749 + test_quick_exit(arg_v[0]); 1750 + test__stat32(); 1751 + test__o_malloc(); 1752 + test_clock(); 1753 + test_thread_storage(); 1754 + test_fenv(); 1755 + test_fopen_exclusive(); 1756 + #if defined(__i386__) 1757 + test_rewind_i386_abi(); 1758 + #endif 1759 + test_gmtime64(); 1760 + test__get_heap_handle(); 1761 + }
+903
modules/rostests/winetests/ucrtbase/printf.c
··· 1 + /* 2 + * Conformance tests for *printf functions. 3 + * 4 + * Copyright 2002 Uwe Bonnes 5 + * Copyright 2004 Aneurin Price 6 + * Copyright 2005 Mike McCormack 7 + * Copyright 2015 Martin Storsjo 8 + * 9 + * This library is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU Lesser General Public 11 + * License as published by the Free Software Foundation; either 12 + * version 2.1 of the License, or (at your option) any later version. 13 + * 14 + * This library is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + * Lesser General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU Lesser General Public 20 + * License along with this library; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 22 + */ 23 + 24 + #include <stdio.h> 25 + #include <errno.h> 26 + #include <math.h> 27 + #include <inttypes.h> 28 + 29 + #include "windef.h" 30 + #include "winbase.h" 31 + #include "winnls.h" 32 + 33 + #include "wine/test.h" 34 + 35 + #define DEFINE_EXPECT(func) \ 36 + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 37 + 38 + #define SET_EXPECT(func) \ 39 + expect_ ## func = TRUE 40 + 41 + #define CHECK_EXPECT2(func) \ 42 + do { \ 43 + ok(expect_ ##func, "unexpected call " #func "\n"); \ 44 + called_ ## func = TRUE; \ 45 + }while(0) 46 + 47 + #define CHECK_EXPECT(func) \ 48 + do { \ 49 + CHECK_EXPECT2(func); \ 50 + expect_ ## func = FALSE; \ 51 + }while(0) 52 + 53 + #define CHECK_CALLED(func) \ 54 + do { \ 55 + ok(called_ ## func, "expected " #func "\n"); \ 56 + expect_ ## func = called_ ## func = FALSE; \ 57 + }while(0) 58 + 59 + DEFINE_EXPECT(invalid_parameter_handler); 60 + 61 + static inline float __port_ind(void) 62 + { 63 + static const unsigned __ind_bytes = 0xffc00000; 64 + return *(const float *)&__ind_bytes; 65 + } 66 + #define IND __port_ind() 67 + 68 + static void __cdecl test_invalid_parameter_handler(const wchar_t *expression, 69 + const wchar_t *function, const wchar_t *file, 70 + unsigned line, uintptr_t arg) 71 + { 72 + CHECK_EXPECT(invalid_parameter_handler); 73 + ok(expression == NULL, "expression is not NULL\n"); 74 + ok(function == NULL, "function is not NULL\n"); 75 + ok(file == NULL, "file is not NULL\n"); 76 + ok(line == 0, "line = %u\n", line); 77 + ok(arg == 0, "arg = %Ix\n", arg); 78 + } 79 + 80 + static int WINAPIV vsprintf_wrapper(unsigned __int64 options, char *str, 81 + size_t len, const char *format, ...) 82 + { 83 + int ret; 84 + va_list valist; 85 + va_start(valist, format); 86 + ret = __stdio_common_vsprintf(options, str, len, format, NULL, valist); 87 + va_end(valist); 88 + return ret; 89 + } 90 + 91 + static void test_snprintf (void) 92 + { 93 + const char *tests[] = {"short", "justfit", "justfits", "muchlonger", "", "1"}; 94 + char buffer[8]; 95 + int bufsizes[] = { 0, 1, sizeof(buffer) }; 96 + unsigned int i, j; 97 + 98 + for (j = 0; j < ARRAY_SIZE(bufsizes); j++) { 99 + const int bufsiz = bufsizes[j]; 100 + /* Legacy _snprintf style termination */ 101 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 102 + const char *fmt = tests[i]; 103 + const int expect = strlen(fmt) > bufsiz ? -1 : strlen(fmt); 104 + const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, bufsiz, fmt); 105 + const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1); 106 + 107 + ok (n == expect, "\"%s\": expected %d, returned %d\n", 108 + fmt, expect, n); 109 + ok (!memcmp (fmt, buffer, valid), 110 + "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer); 111 + } 112 + 113 + /* C99 snprintf style termination */ 114 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 115 + const char *fmt = tests[i]; 116 + const int expect = strlen(fmt); 117 + const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, bufsiz, fmt); 118 + const int valid = n >= bufsiz ? (bufsiz > 0 ? bufsiz - 1 : 0) : n < 0 ? 0 : n; 119 + 120 + ok (n == expect, "\"%s\": expected %d, returned %d\n", 121 + fmt, expect, n); 122 + ok (!memcmp (fmt, buffer, valid), 123 + "\"%s\": rendered \"%.*s\" bufsiz %d\n", fmt, valid, buffer, bufsiz); 124 + ok (bufsiz == 0 || buffer[valid] == '\0', 125 + "\"%s\": Missing null termination (ret %d) - is %d (bufsiz %d)\n", fmt, n, buffer[valid], bufsiz); 126 + } 127 + 128 + /* swprintf style termination */ 129 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 130 + const char *fmt = tests[i]; 131 + const int expect = strlen(fmt) >= bufsiz ? bufsiz > 0 ? -2 : -1 : strlen(fmt); 132 + const int n = vsprintf_wrapper (0, buffer, bufsiz, fmt); 133 + const int valid = n < 0 ? bufsiz > 0 ? bufsiz - 1 : 0 : n; 134 + 135 + ok (n == expect, "\"%s\": expected %d, returned %d\n", 136 + fmt, expect, n); 137 + ok (!memcmp (fmt, buffer, valid), 138 + "\"%s\": rendered \"%.*s\" bufsiz %d\n", fmt, valid, buffer, bufsiz); 139 + ok (bufsiz == 0 || buffer[valid] == '\0', 140 + "\"%s\": Missing null termination (ret %d) - is %d\n", fmt, n, buffer[valid]); 141 + } 142 + } 143 + 144 + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, NULL, 0, "abcd") == 4, 145 + "Failure to snprintf to NULL\n"); 146 + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, NULL, 0, "abcd") == 4, 147 + "Failure to snprintf to NULL\n"); 148 + ok (vsprintf_wrapper (0, NULL, 0, "abcd") == 4, 149 + "Failure to snprintf to NULL\n"); 150 + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, "abcd") == 4, 151 + "Failure to snprintf to zero length buffer\n"); 152 + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, "abcd") == -1, 153 + "Failure to snprintf to zero length buffer\n"); 154 + ok (vsprintf_wrapper (0, buffer, 0, "abcd") == -1, 155 + "Failure to snprintf to zero length buffer\n"); 156 + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, "") == 0, 157 + "Failure to snprintf a zero length string to a zero length buffer\n"); 158 + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, "") == 0, 159 + "Failure to snprintf a zero length string to a zero length buffer\n"); 160 + ok (vsprintf_wrapper (0, buffer, 0, "") == -1, 161 + "Failure to snprintf a zero length string to a zero length buffer\n"); 162 + } 163 + 164 + static int WINAPIV vswprintf_wrapper(unsigned __int64 options, wchar_t *str, 165 + size_t len, const wchar_t *format, ...) 166 + { 167 + int ret; 168 + va_list valist; 169 + va_start(valist, format); 170 + ret = __stdio_common_vswprintf(options, str, len, format, NULL, valist); 171 + va_end(valist); 172 + return ret; 173 + } 174 + 175 + static void test_swprintf (void) 176 + { 177 + const wchar_t str_short[] = {'s','h','o','r','t',0}; 178 + const wchar_t str_justfit[] = {'j','u','s','t','f','i','t',0}; 179 + const wchar_t str_justfits[] = {'j','u','s','t','f','i','t','s',0}; 180 + const wchar_t str_muchlonger[] = {'m','u','c','h','l','o','n','g','e','r',0}; 181 + const wchar_t str_empty[] = {0}; 182 + const wchar_t *tests[] = {str_short, str_justfit, str_justfits, str_muchlonger}; 183 + 184 + wchar_t buffer[8]; 185 + char narrow[8], narrow_fmt[16]; 186 + const int bufsiz = ARRAY_SIZE(buffer); 187 + unsigned int i; 188 + 189 + /* Legacy _snprintf style termination */ 190 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 191 + const wchar_t *fmt = tests[i]; 192 + const int expect = wcslen(fmt) > bufsiz ? -1 : wcslen(fmt); 193 + const int n = vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, bufsiz, fmt); 194 + const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1); 195 + 196 + WideCharToMultiByte (CP_ACP, 0, buffer, -1, narrow, sizeof(narrow), NULL, NULL); 197 + WideCharToMultiByte (CP_ACP, 0, fmt, -1, narrow_fmt, sizeof(narrow_fmt), NULL, NULL); 198 + ok (n == expect, "\"%s\": expected %d, returned %d\n", 199 + narrow_fmt, expect, n); 200 + ok (!memcmp (fmt, buffer, valid * sizeof(wchar_t)), 201 + "\"%s\": rendered \"%.*s\"\n", narrow_fmt, valid, narrow); 202 + } 203 + 204 + /* C99 snprintf style termination */ 205 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 206 + const wchar_t *fmt = tests[i]; 207 + const int expect = wcslen(fmt); 208 + const int n = vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, bufsiz, fmt); 209 + const int valid = n >= bufsiz ? bufsiz - 1 : n < 0 ? 0 : n; 210 + 211 + WideCharToMultiByte (CP_ACP, 0, buffer, -1, narrow, sizeof(narrow), NULL, NULL); 212 + WideCharToMultiByte (CP_ACP, 0, fmt, -1, narrow_fmt, sizeof(narrow_fmt), NULL, NULL); 213 + ok (n == expect, "\"%s\": expected %d, returned %d\n", 214 + narrow_fmt, expect, n); 215 + ok (!memcmp (fmt, buffer, valid * sizeof(wchar_t)), 216 + "\"%s\": rendered \"%.*s\"\n", narrow_fmt, valid, narrow); 217 + ok (buffer[valid] == '\0', 218 + "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt, n, buffer[valid]); 219 + } 220 + 221 + /* swprintf style termination */ 222 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 223 + const wchar_t *fmt = tests[i]; 224 + const int expect = wcslen(fmt) >= bufsiz ? -2 : wcslen(fmt); 225 + const int n = vswprintf_wrapper (0, buffer, bufsiz, fmt); 226 + const int valid = n < 0 ? bufsiz - 1 : n; 227 + 228 + WideCharToMultiByte (CP_ACP, 0, buffer, -1, narrow, sizeof(narrow), NULL, NULL); 229 + WideCharToMultiByte (CP_ACP, 0, fmt, -1, narrow_fmt, sizeof(narrow_fmt), NULL, NULL); 230 + ok (n == expect, "\"%s\": expected %d, returned %d\n", 231 + narrow_fmt, expect, n); 232 + ok (!memcmp (fmt, buffer, valid * sizeof(wchar_t)), 233 + "\"%s\": rendered \"%.*s\"\n", narrow_fmt, valid, narrow); 234 + ok (buffer[valid] == '\0', 235 + "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt, n, buffer[valid]); 236 + } 237 + 238 + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, NULL, 0, str_short) == 5, 239 + "Failure to swprintf to NULL\n"); 240 + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, NULL, 0, str_short) == 5, 241 + "Failure to swprintf to NULL\n"); 242 + ok (vswprintf_wrapper (0, NULL, 0, str_short) == 5, 243 + "Failure to swprintf to NULL\n"); 244 + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, str_short) == 5, 245 + "Failure to swprintf to a zero length buffer\n"); 246 + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, str_short) == -1, 247 + "Failure to swprintf to a zero length buffer\n"); 248 + ok (vswprintf_wrapper (0, buffer, 0, str_short) == -1, 249 + "Failure to swprintf to a zero length buffer\n"); 250 + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, str_empty) == 0, 251 + "Failure to swprintf a zero length string to a zero length buffer\n"); 252 + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, str_empty) == 0, 253 + "Failure to swprintf a zero length string to a zero length buffer\n"); 254 + ok (vswprintf_wrapper (0, buffer, 0, str_empty) == -1, 255 + "Failure to swprintf a zero length string to a zero length buffer\n"); 256 + } 257 + 258 + static int WINAPIV vfprintf_wrapper(FILE *file, 259 + const char *format, ...) 260 + { 261 + int ret; 262 + va_list valist; 263 + va_start(valist, format); 264 + ret = __stdio_common_vfprintf(0, file, format, NULL, valist); 265 + va_end(valist); 266 + return ret; 267 + } 268 + 269 + static void test_fprintf(void) 270 + { 271 + static const char file_name[] = "fprintf.tst"; 272 + 273 + FILE *fp = fopen(file_name, "wb"); 274 + char buf[1024]; 275 + int ret; 276 + 277 + ret = vfprintf_wrapper(fp, "simple test\n"); 278 + ok(ret == 12, "ret = %d\n", ret); 279 + ret = ftell(fp); 280 + ok(ret == 12, "ftell returned %d\n", ret); 281 + 282 + ret = vfprintf_wrapper(fp, "contains%cnull\n", '\0'); 283 + ok(ret == 14, "ret = %d\n", ret); 284 + ret = ftell(fp); 285 + ok(ret == 26, "ftell returned %d\n", ret); 286 + 287 + fclose(fp); 288 + 289 + fp = fopen(file_name, "rb"); 290 + fgets(buf, sizeof(buf), fp); 291 + ret = ftell(fp); 292 + ok(ret == 12, "ftell returned %d\n", ret); 293 + ok(!strcmp(buf, "simple test\n"), "buf = %s\n", buf); 294 + 295 + fgets(buf, sizeof(buf), fp); 296 + ret = ftell(fp); 297 + ok(ret == 26, "ret = %d\n", ret); 298 + ok(!memcmp(buf, "contains\0null\n", 14), "buf = %s\n", buf); 299 + 300 + fclose(fp); 301 + 302 + fp = fopen(file_name, "wt"); 303 + 304 + ret = vfprintf_wrapper(fp, "simple test\n"); 305 + ok(ret == 12, "ret = %d\n", ret); 306 + ret = ftell(fp); 307 + ok(ret == 13, "ftell returned %d\n", ret); 308 + 309 + ret = vfprintf_wrapper(fp, "contains%cnull\n", '\0'); 310 + ok(ret == 14, "ret = %d\n", ret); 311 + ret = ftell(fp); 312 + ok(ret == 28, "ftell returned %d\n", ret); 313 + 314 + fclose(fp); 315 + 316 + fp = fopen(file_name, "rb"); 317 + fgets(buf, sizeof(buf), fp); 318 + ret = ftell(fp); 319 + ok(ret == 13, "ftell returned %d\n", ret); 320 + ok(!strcmp(buf, "simple test\r\n"), "buf = %s\n", buf); 321 + 322 + fgets(buf, sizeof(buf), fp); 323 + ret = ftell(fp); 324 + ok(ret == 28, "ret = %d\n", ret); 325 + ok(!memcmp(buf, "contains\0null\r\n", 15), "buf = %s\n", buf); 326 + 327 + fclose(fp); 328 + unlink(file_name); 329 + } 330 + 331 + static int WINAPIV vfwprintf_wrapper(FILE *file, 332 + const wchar_t *format, ...) 333 + { 334 + int ret; 335 + va_list valist; 336 + va_start(valist, format); 337 + ret = __stdio_common_vfwprintf(0, file, format, NULL, valist); 338 + va_end(valist); 339 + return ret; 340 + } 341 + 342 + static void test_fwprintf(void) 343 + { 344 + static const char file_name[] = "fprintf.tst"; 345 + static const WCHAR simple[] = {'s','i','m','p','l','e',' ','t','e','s','t','\n',0}; 346 + static const WCHAR cont_fmt[] = {'c','o','n','t','a','i','n','s','%','c','n','u','l','l','\n',0}; 347 + static const WCHAR cont[] = {'c','o','n','t','a','i','n','s','\0','n','u','l','l','\n',0}; 348 + 349 + FILE *fp = fopen(file_name, "wb"); 350 + wchar_t bufw[1024]; 351 + char bufa[1024]; 352 + int ret; 353 + 354 + ret = vfwprintf_wrapper(fp, simple); 355 + ok(ret == 12, "ret = %d\n", ret); 356 + ret = ftell(fp); 357 + ok(ret == 24, "ftell returned %d\n", ret); 358 + 359 + ret = vfwprintf_wrapper(fp, cont_fmt, '\0'); 360 + ok(ret == 14, "ret = %d\n", ret); 361 + ret = ftell(fp); 362 + ok(ret == 52, "ftell returned %d\n", ret); 363 + 364 + fclose(fp); 365 + 366 + fp = fopen(file_name, "rb"); 367 + fgetws(bufw, ARRAY_SIZE(bufw), fp); 368 + ret = ftell(fp); 369 + ok(ret == 24, "ftell returned %d\n", ret); 370 + ok(!wcscmp(bufw, simple), "buf = %s\n", wine_dbgstr_w(bufw)); 371 + 372 + fgetws(bufw, ARRAY_SIZE(bufw), fp); 373 + ret = ftell(fp); 374 + ok(ret == 52, "ret = %d\n", ret); 375 + ok(!memcmp(bufw, cont, 28), "buf = %s\n", wine_dbgstr_w(bufw)); 376 + 377 + fclose(fp); 378 + 379 + fp = fopen(file_name, "wt"); 380 + 381 + ret = vfwprintf_wrapper(fp, simple); 382 + ok(ret == 12, "ret = %d\n", ret); 383 + ret = ftell(fp); 384 + ok(ret == 13, "ftell returned %d\n", ret); 385 + 386 + ret = vfwprintf_wrapper(fp, cont_fmt, '\0'); 387 + ok(ret == 14, "ret = %d\n", ret); 388 + ret = ftell(fp); 389 + ok(ret == 28, "ftell returned %d\n", ret); 390 + 391 + fclose(fp); 392 + 393 + fp = fopen(file_name, "rb"); 394 + fgets(bufa, sizeof(bufa), fp); 395 + ret = ftell(fp); 396 + ok(ret == 13, "ftell returned %d\n", ret); 397 + ok(!strcmp(bufa, "simple test\r\n"), "buf = %s\n", bufa); 398 + 399 + fgets(bufa, sizeof(bufa), fp); 400 + ret = ftell(fp); 401 + ok(ret == 28, "ret = %d\n", ret); 402 + ok(!memcmp(bufa, "contains\0null\r\n", 15), "buf = %s\n", bufa); 403 + 404 + fclose(fp); 405 + unlink(file_name); 406 + 407 + /* NULL format */ 408 + errno = 0xdeadbeef; 409 + SET_EXPECT(invalid_parameter_handler); 410 + ret = vfwprintf_wrapper(fp, NULL); 411 + ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno); 412 + ok(ret == -1, "expected ret -1, got %d\n", ret); 413 + CHECK_CALLED(invalid_parameter_handler); 414 + 415 + /* NULL file */ 416 + errno = 0xdeadbeef; 417 + SET_EXPECT(invalid_parameter_handler); 418 + ret = vfwprintf_wrapper(NULL, simple); 419 + ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno); 420 + ok(ret == -1, "expected ret -1, got %d\n", ret); 421 + CHECK_CALLED(invalid_parameter_handler); 422 + 423 + /* format using % with NULL arglist*/ 424 + /* crashes on Windows */ 425 + /* ret = __stdio_common_vfwprintf(0, fp, cont_fmt, NULL, NULL); */ 426 + } 427 + 428 + static int WINAPIV _vsnprintf_s_wrapper(char *str, size_t sizeOfBuffer, 429 + size_t count, const char *format, ...) 430 + { 431 + int ret; 432 + va_list valist; 433 + va_start(valist, format); 434 + ret = __stdio_common_vsnprintf_s(0, str, sizeOfBuffer, count, format, NULL, valist); 435 + va_end(valist); 436 + return ret; 437 + } 438 + 439 + static void test_vsnprintf_s(void) 440 + { 441 + const char format[] = "AB%uC"; 442 + const char out7[] = "AB123C"; 443 + const char out6[] = "AB123"; 444 + const char out2[] = "A"; 445 + const char out1[] = ""; 446 + char buffer[14] = { 0 }; 447 + int exp, got; 448 + 449 + /* Enough room. */ 450 + exp = strlen(out7); 451 + 452 + got = _vsnprintf_s_wrapper(buffer, 14, _TRUNCATE, format, 123); 453 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 454 + ok( !strcmp(out7, buffer), "buffer wrong, got=%s\n", buffer); 455 + 456 + got = _vsnprintf_s_wrapper(buffer, 12, _TRUNCATE, format, 123); 457 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 458 + ok( !strcmp(out7, buffer), "buffer wrong, got=%s\n", buffer); 459 + 460 + got = _vsnprintf_s_wrapper(buffer, 7, _TRUNCATE, format, 123); 461 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 462 + ok( !strcmp(out7, buffer), "buffer wrong, got=%s\n", buffer); 463 + 464 + /* Not enough room. */ 465 + exp = -1; 466 + 467 + got = _vsnprintf_s_wrapper(buffer, 6, _TRUNCATE, format, 123); 468 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 469 + ok( !strcmp(out6, buffer), "buffer wrong, got=%s\n", buffer); 470 + 471 + got = _vsnprintf_s_wrapper(buffer, 2, _TRUNCATE, format, 123); 472 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 473 + ok( !strcmp(out2, buffer), "buffer wrong, got=%s\n", buffer); 474 + 475 + got = _vsnprintf_s_wrapper(buffer, 1, _TRUNCATE, format, 123); 476 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 477 + ok( !strcmp(out1, buffer), "buffer wrong, got=%s\n", buffer); 478 + } 479 + 480 + static int WINAPIV _vsnwprintf_s_wrapper(WCHAR *str, size_t sizeOfBuffer, 481 + size_t count, const WCHAR *format, ...) 482 + { 483 + int ret; 484 + va_list valist; 485 + va_start(valist, format); 486 + ret = __stdio_common_vsnwprintf_s(0, str, sizeOfBuffer, count, format, NULL, valist); 487 + va_end(valist); 488 + return ret; 489 + } 490 + 491 + static void test_vsnwprintf_s(void) 492 + { 493 + const WCHAR format[] = {'A','B','%','u','C',0}; 494 + const WCHAR out7[] = {'A','B','1','2','3','C',0}; 495 + const WCHAR out6[] = {'A','B','1','2','3',0}; 496 + const WCHAR out2[] = {'A',0}; 497 + const WCHAR out1[] = {0}; 498 + WCHAR buffer[14] = { 0 }; 499 + int exp, got; 500 + 501 + /* Enough room. */ 502 + exp = lstrlenW(out7); 503 + 504 + got = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, format, 123); 505 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 506 + ok( !lstrcmpW(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); 507 + 508 + got = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, format, 123); 509 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 510 + ok( !lstrcmpW(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); 511 + 512 + got = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, format, 123); 513 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 514 + ok( !lstrcmpW(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); 515 + 516 + /* Not enough room. */ 517 + exp = -1; 518 + 519 + got = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, format, 123); 520 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 521 + ok( !lstrcmpW(out6, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); 522 + 523 + got = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, format, 123); 524 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 525 + ok( !lstrcmpW(out2, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); 526 + 527 + got = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, format, 123); 528 + ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); 529 + ok( !lstrcmpW(out1, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); 530 + } 531 + 532 + static void test_printf_legacy_wide(void) 533 + { 534 + const wchar_t wide[] = {'A','B','C','D',0}; 535 + const char narrow[] = "abcd"; 536 + const char out[] = "abcd ABCD"; 537 + /* The legacy wide flag doesn't affect narrow printfs, so the same 538 + * format should behave the same both with and without the flag. */ 539 + const char narrow_fmt[] = "%s %ls"; 540 + /* The standard behaviour is to use the same format as for the narrow 541 + * case, while the legacy case has got a different meaning for %s. */ 542 + const wchar_t std_wide_fmt[] = {'%','s',' ','%','l','s',0}; 543 + const wchar_t legacy_wide_fmt[] = {'%','h','s',' ','%','s',0}; 544 + char buffer[20]; 545 + wchar_t wbuffer[20]; 546 + 547 + vsprintf_wrapper(0, buffer, sizeof(buffer), narrow_fmt, narrow, wide); 548 + ok(!strcmp(buffer, out), "buffer wrong, got=%s\n", buffer); 549 + vsprintf_wrapper(_CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS, buffer, sizeof(buffer), narrow_fmt, narrow, wide); 550 + ok(!strcmp(buffer, out), "buffer wrong, got=%s\n", buffer); 551 + 552 + vswprintf_wrapper(0, wbuffer, sizeof(wbuffer), std_wide_fmt, narrow, wide); 553 + WideCharToMultiByte(CP_ACP, 0, wbuffer, -1, buffer, sizeof(buffer), NULL, NULL); 554 + ok(!strcmp(buffer, out), "buffer wrong, got=%s\n", buffer); 555 + vswprintf_wrapper(_CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS, wbuffer, sizeof(wbuffer), legacy_wide_fmt, narrow, wide); 556 + WideCharToMultiByte(CP_ACP, 0, wbuffer, -1, buffer, sizeof(buffer), NULL, NULL); 557 + ok(!strcmp(buffer, out), "buffer wrong, got=%s\n", buffer); 558 + } 559 + 560 + static void test_printf_legacy_msvcrt(void) 561 + { 562 + char buf[50]; 563 + 564 + /* In standard mode, %F is a float format conversion, while it is a 565 + * length modifier in legacy msvcrt mode. In legacy mode, N is also 566 + * a length modifier. */ 567 + vsprintf_wrapper(0, buf, sizeof(buf), "%F", 1.23); 568 + ok(!strcmp(buf, "1.230000"), "buf = %s\n", buf); 569 + vsprintf_wrapper(_CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY, buf, sizeof(buf), "%Fd %Nd", 123, 456); 570 + ok(!strcmp(buf, "123 456"), "buf = %s\n", buf); 571 + 572 + vsprintf_wrapper(0, buf, sizeof(buf), "%f %F %f %e %E %g %G", INFINITY, INFINITY, -INFINITY, INFINITY, INFINITY, INFINITY, INFINITY); 573 + ok(!strcmp(buf, "inf INF -inf inf INF inf INF"), "buf = %s\n", buf); 574 + vsprintf_wrapper(_CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY, buf, sizeof(buf), "%f", INFINITY); 575 + ok(!strcmp(buf, "1.#INF00"), "buf = %s\n", buf); 576 + vsprintf_wrapper(0, buf, sizeof(buf), "%f %F", NAN, NAN); 577 + ok(!strcmp(buf, "nan NAN"), "buf = %s\n", buf); 578 + vsprintf_wrapper(_CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY, buf, sizeof(buf), "%f", NAN); 579 + ok(!strcmp(buf, "1.#QNAN0"), "buf = %s\n", buf); 580 + vsprintf_wrapper(0, buf, sizeof(buf), "%f %F", IND, IND); 581 + ok(!strcmp(buf, "-nan(ind) -NAN(IND)"), "buf = %s\n", buf); 582 + vsprintf_wrapper(_CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY, buf, sizeof(buf), "%f", IND); 583 + ok(!strcmp(buf, "-1.#IND00"), "buf = %s\n", buf); 584 + } 585 + 586 + static void test_printf_legacy_three_digit_exp(void) 587 + { 588 + char buf[20]; 589 + 590 + vsprintf_wrapper(0, buf, sizeof(buf), "%E", 1.23); 591 + ok(!strcmp(buf, "1.230000E+00"), "buf = %s\n", buf); 592 + vsprintf_wrapper(_CRT_INTERNAL_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS, buf, sizeof(buf), "%E", 1.23); 593 + ok(!strcmp(buf, "1.230000E+000"), "buf = %s\n", buf); 594 + vsprintf_wrapper(0, buf, sizeof(buf), "%E", 1.23e+123); 595 + ok(!strcmp(buf, "1.230000E+123"), "buf = %s\n", buf); 596 + } 597 + 598 + static void test_printf_c99(void) 599 + { 600 + char buf[30]; 601 + int i; 602 + 603 + /* The msvcrt compatibility flag doesn't affect whether 'z' is interpreted 604 + * as size_t size for integers. */ 605 + for (i = 0; i < 2; i++) { 606 + unsigned __int64 options = (i == 0) ? 0 : 607 + _CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY; 608 + 609 + /* z modifier accepts size_t argument */ 610 + vsprintf_wrapper(options, buf, sizeof(buf), "%zx %d", SIZE_MAX, 1); 611 + if (sizeof(size_t) == 8) 612 + ok(!strcmp(buf, "ffffffffffffffff 1"), "buf = %s\n", buf); 613 + else 614 + ok(!strcmp(buf, "ffffffff 1"), "buf = %s\n", buf); 615 + 616 + /* j modifier with signed format accepts intmax_t argument */ 617 + vsprintf_wrapper(options, buf, sizeof(buf), "%jd %d", INTMAX_MIN, 1); 618 + ok(!strcmp(buf, "-9223372036854775808 1"), "buf = %s\n", buf); 619 + 620 + /* j modifier with unsigned format accepts uintmax_t argument */ 621 + vsprintf_wrapper(options, buf, sizeof(buf), "%ju %d", UINTMAX_MAX, 1); 622 + ok(!strcmp(buf, "18446744073709551615 1"), "buf = %s\n", buf); 623 + 624 + /* t modifier accepts ptrdiff_t argument */ 625 + vsprintf_wrapper(options, buf, sizeof(buf), "%td %d", PTRDIFF_MIN, 1); 626 + if (sizeof(ptrdiff_t) == 8) 627 + ok(!strcmp(buf, "-9223372036854775808 1"), "buf = %s\n", buf); 628 + else 629 + ok(!strcmp(buf, "-2147483648 1"), "buf = %s\n", buf); 630 + } 631 + } 632 + 633 + static void test_printf_natural_string(void) 634 + { 635 + const wchar_t wide[] = {'A','B','C','D',0}; 636 + const char narrow[] = "abcd"; 637 + const char narrow_fmt[] = "%s %Ts"; 638 + const char narrow_out[] = "abcd abcd"; 639 + const wchar_t wide_fmt[] = {'%','s',' ','%','T','s',0}; 640 + const wchar_t wide_out[] = {'a','b','c','d',' ','A','B','C','D',0}; 641 + char buffer[20]; 642 + wchar_t wbuffer[20]; 643 + 644 + vsprintf_wrapper(0, buffer, sizeof(buffer), narrow_fmt, narrow, narrow); 645 + ok(!strcmp(buffer, narrow_out), "buffer wrong, got=%s\n", buffer); 646 + 647 + vswprintf_wrapper(0, wbuffer, sizeof(wbuffer), wide_fmt, narrow, wide); 648 + ok(!lstrcmpW(wbuffer, wide_out), "buffer wrong, got=%s\n", wine_dbgstr_w(wbuffer)); 649 + } 650 + 651 + static void test_printf_fp(void) 652 + { 653 + static const int flags[] = { 654 + 0, 655 + _CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY, 656 + _CRT_INTERNAL_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS, 657 + _CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY 658 + | _CRT_INTERNAL_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS, 659 + _CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY 660 + | _CRT_INTERNAL_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS 661 + | _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING 662 + }; 663 + const struct { 664 + const char *fmt; 665 + double d; 666 + const char *res[ARRAY_SIZE(flags)]; 667 + const char *broken[ARRAY_SIZE(flags)]; 668 + } tests[] = { 669 + { "%a", NAN, { "nan", "0x1.#QNAN00000000p+0", "nan", "0x1.#QNAN00000000p+0" }}, 670 + { "%A", NAN, { "NAN", "0X1.#QNAN00000000P+0", "NAN", "0X1.#QNAN00000000P+0" }}, 671 + { "%e", NAN, { "nan", "1.#QNAN0e+00", "nan", "1.#QNAN0e+000" }}, 672 + { "%E", NAN, { "NAN", "1.#QNAN0E+00", "NAN", "1.#QNAN0E+000" }}, 673 + { "%g", NAN, { "nan", "1.#QNAN", "nan", "1.#QNAN" }}, 674 + { "%G", NAN, { "NAN", "1.#QNAN", "NAN", "1.#QNAN" }}, 675 + { "%21a", NAN, { " nan", " 0x1.#QNAN00000000p+0", " nan", " 0x1.#QNAN00000000p+0" }}, 676 + { "%20e", NAN, { " nan", " 1.#QNAN0e+00", " nan", " 1.#QNAN0e+000" }}, 677 + { "%20g", NAN, { " nan", " 1.#QNAN", " nan", " 1.#QNAN" }}, 678 + { "%.21a", NAN, { "nan", "0x1.#QNAN0000000000000000p+0", "nan", "0x1.#QNAN0000000000000000p+0" }}, 679 + { "%.20e", NAN, { "nan", "1.#QNAN000000000000000e+00", "nan", "1.#QNAN000000000000000e+000" }}, 680 + { "%.20g", NAN, { "nan", "1.#QNAN", "nan", "1.#QNAN" }}, 681 + { "%.021a", NAN, { "nan", "0x1.#QNAN0000000000000000p+0", "nan", "0x1.#QNAN0000000000000000p+0" }}, 682 + { "%.020e", NAN, { "nan", "1.#QNAN000000000000000e+00", "nan", "1.#QNAN000000000000000e+000" }}, 683 + { "%.020g", NAN, { "nan", "1.#QNAN", "nan", "1.#QNAN" }}, 684 + { "%#.21a", NAN, { "nan", "0x1.#QNAN0000000000000000p+0", "nan", "0x1.#QNAN0000000000000000p+0" }}, 685 + { "%#.20e", NAN, { "nan", "1.#QNAN000000000000000e+00", "nan", "1.#QNAN000000000000000e+000" }}, 686 + { "%#.20g", NAN, { "nan", "1.#QNAN00000000000000", "nan", "1.#QNAN00000000000000" }}, 687 + { "%.1g", NAN, { "nan", "1", "nan", "1" }}, 688 + { "%.2g", NAN, { "nan", "1.$", "nan", "1.$" }}, 689 + { "%.3g", NAN, { "nan", "1.#R", "nan", "1.#R" }}, 690 + 691 + { "%a", IND, { "-nan(ind)", "-0x1.#IND000000000p+0", "-nan(ind)", "-0x1.#IND000000000p+0" }}, 692 + { "%e", IND, { "-nan(ind)", "-1.#IND00e+00", "-nan(ind)", "-1.#IND00e+000" }}, 693 + { "%g", IND, { "-nan(ind)", "-1.#IND", "-nan(ind)", "-1.#IND" }}, 694 + { "%21a", IND, { " -nan(ind)", "-0x1.#IND000000000p+0", " -nan(ind)", "-0x1.#IND000000000p+0" }}, 695 + { "%20e", IND, { " -nan(ind)", " -1.#IND00e+00", " -nan(ind)", " -1.#IND00e+000" }}, 696 + { "%20g", IND, { " -nan(ind)", " -1.#IND", " -nan(ind)", " -1.#IND" }}, 697 + { "%.21a", IND, { "-nan(ind)", "-0x1.#IND00000000000000000p+0", "-nan(ind)", "-0x1.#IND00000000000000000p+0" }}, 698 + { "%.20e", IND, { "-nan(ind)", "-1.#IND0000000000000000e+00", "-nan(ind)", "-1.#IND0000000000000000e+000" }}, 699 + { "%.20g", IND, { "-nan(ind)", "-1.#IND", "-nan(ind)", "-1.#IND" }}, 700 + { "%.021a", IND, { "-nan(ind)", "-0x1.#IND00000000000000000p+0", "-nan(ind)", "-0x1.#IND00000000000000000p+0" }}, 701 + { "%.020e", IND, { "-nan(ind)", "-1.#IND0000000000000000e+00", "-nan(ind)", "-1.#IND0000000000000000e+000" }}, 702 + { "%.020g", IND, { "-nan(ind)", "-1.#IND", "-nan(ind)", "-1.#IND" }}, 703 + { "%#.21a", IND, { "-nan(ind)", "-0x1.#IND00000000000000000p+0", "-nan(ind)", "-0x1.#IND00000000000000000p+0" }}, 704 + { "%#.20e", IND, { "-nan(ind)", "-1.#IND0000000000000000e+00", "-nan(ind)", "-1.#IND0000000000000000e+000" }}, 705 + { "%#.20g", IND, { "-nan(ind)", "-1.#IND000000000000000", "-nan(ind)", "-1.#IND000000000000000" }}, 706 + 707 + { "%a", INFINITY, { "inf", "0x1.#INF000000000p+0", "inf", "0x1.#INF000000000p+0" }}, 708 + { "%e", INFINITY, { "inf", "1.#INF00e+00", "inf", "1.#INF00e+000" }}, 709 + { "%g", INFINITY, { "inf", "1.#INF", "inf", "1.#INF" }}, 710 + { "%21a", INFINITY, { " inf", " 0x1.#INF000000000p+0", " inf", " 0x1.#INF000000000p+0" }}, 711 + { "%20e", INFINITY, { " inf", " 1.#INF00e+00", " inf", " 1.#INF00e+000" }}, 712 + { "%20g", INFINITY, { " inf", " 1.#INF", " inf", " 1.#INF" }}, 713 + { "%.21a", INFINITY, { "inf", "0x1.#INF00000000000000000p+0", "inf", "0x1.#INF00000000000000000p+0" }}, 714 + { "%.20e", INFINITY, { "inf", "1.#INF0000000000000000e+00", "inf", "1.#INF0000000000000000e+000" }}, 715 + { "%.20g", INFINITY, { "inf", "1.#INF", "inf", "1.#INF" }}, 716 + { "%.021a", INFINITY, { "inf", "0x1.#INF00000000000000000p+0", "inf", "0x1.#INF00000000000000000p+0" }}, 717 + { "%.020e", INFINITY, { "inf", "1.#INF0000000000000000e+00", "inf", "1.#INF0000000000000000e+000" }}, 718 + { "%.020g", INFINITY, { "inf", "1.#INF", "inf", "1.#INF" }}, 719 + { "%#.21a", INFINITY, { "inf", "0x1.#INF00000000000000000p+0", "inf", "0x1.#INF00000000000000000p+0" }}, 720 + { "%#.20e", INFINITY, { "inf", "1.#INF0000000000000000e+00", "inf", "1.#INF0000000000000000e+000" }}, 721 + { "%#.20g", INFINITY, { "inf", "1.#INF000000000000000", "inf", "1.#INF000000000000000" }}, 722 + 723 + { "%a", -INFINITY, { "-inf", "-0x1.#INF000000000p+0", "-inf", "-0x1.#INF000000000p+0" }}, 724 + { "%e", -INFINITY, { "-inf", "-1.#INF00e+00", "-inf", "-1.#INF00e+000" }}, 725 + { "%g", -INFINITY, { "-inf", "-1.#INF", "-inf", "-1.#INF" }}, 726 + { "%21a", -INFINITY, { " -inf", "-0x1.#INF000000000p+0", " -inf", "-0x1.#INF000000000p+0" }}, 727 + { "%20e", -INFINITY, { " -inf", " -1.#INF00e+00", " -inf", " -1.#INF00e+000" }}, 728 + { "%20g", -INFINITY, { " -inf", " -1.#INF", " -inf", " -1.#INF" }}, 729 + { "%.21a", -INFINITY, { "-inf", "-0x1.#INF00000000000000000p+0", "-inf", "-0x1.#INF00000000000000000p+0" }}, 730 + { "%.20e", -INFINITY, { "-inf", "-1.#INF0000000000000000e+00", "-inf", "-1.#INF0000000000000000e+000" }}, 731 + { "%.20g", -INFINITY, { "-inf", "-1.#INF", "-inf", "-1.#INF" }}, 732 + { "%.021a", -INFINITY, { "-inf", "-0x1.#INF00000000000000000p+0", "-inf", "-0x1.#INF00000000000000000p+0" }}, 733 + { "%.020e", -INFINITY, { "-inf", "-1.#INF0000000000000000e+00", "-inf", "-1.#INF0000000000000000e+000" }}, 734 + { "%.020g", -INFINITY, { "-inf", "-1.#INF", "-inf", "-1.#INF" }}, 735 + { "%#.21a", -INFINITY, { "-inf", "-0x1.#INF00000000000000000p+0", "-inf", "-0x1.#INF00000000000000000p+0" }}, 736 + { "%#.20e", -INFINITY, { "-inf", "-1.#INF0000000000000000e+00", "-inf", "-1.#INF0000000000000000e+000" }}, 737 + { "%#.20g", -INFINITY, { "-inf", "-1.#INF000000000000000", "-inf", "-1.#INF000000000000000" }}, 738 + 739 + { "%a", 0, { "0x0.0000000000000p+0" }}, 740 + { "%A", 0, { "0X0.0000000000000P+0" }}, 741 + { "%a", 0.5, { "0x1.0000000000000p-1" }}, 742 + { "%a", 1, { "0x1.0000000000000p+0" }}, 743 + { "%a", 20, { "0x1.4000000000000p+4" }}, 744 + { "%a", -1, { "-0x1.0000000000000p+0" }}, 745 + { "%a", 0.1, { "0x1.999999999999ap-4" }}, 746 + { "%24a", 0.1, { " 0x1.999999999999ap-4" }}, 747 + { "%024a", 0.1, { "0x00001.999999999999ap-4" }}, 748 + { "%.2a", 0.1, { "0x1.9ap-4" }}, 749 + { "%.20a", 0.1, { "0x1.999999999999a0000000p-4" }}, 750 + { "%.a", 0.1e-20, { "0x1p-70" }}, 751 + { "%a", 0.1e-20, { "0x1.2e3b40a0e9b4fp-70" }}, 752 + { "%a", 4.9406564584124654e-324, { "0x0.0000000000001p-1022" }}, 753 + { "%.0a", -1.5, { "-0x2p+0" }, { "-0x1p+0" }}, 754 + { "%.0a", -0.5, { "-0x1p-1" }}, 755 + { "%.0a", 0.5, { "0x1p-1" }}, 756 + { "%.0a", 1.5, { "0x2p+0" }, { "0x1p+0" }}, 757 + { "%.0a", 1.99, { "0x2p+0" }}, 758 + { "%.0a", 2, { "0x1p+1" }}, 759 + { "%.0a", 9.5, { "0x1p+3" }}, 760 + { "%.0a", 10.5, { "0x1p+3" }}, 761 + { "%#.0a", -1.5, { "-0x2.p+0" }, { "-0x1.p+0" }}, 762 + { "%#.0a", -0.5, { "-0x1.p-1" }}, 763 + { "%#.0a", 0.5, { "0x1.p-1" }}, 764 + { "%#.0a", 1.5, { "0x2.p+0" }, { "0x1.p+0" }}, 765 + { "%#.1a", 1.03125, { "0x1.1p+0", NULL, NULL, NULL, "0x1.0p+0" }, { "0x1.0p+0" }}, 766 + { "%#.1a", 1.09375, { "0x1.2p+0" }, { "0x1.1p+0" }}, 767 + { "%#.1a", 1.15625, { "0x1.3p+0", NULL, NULL, NULL, "0x1.2p+0" }, { "0x1.2p+0" }}, 768 + 769 + { "%f", 0, { "0.000000" }}, 770 + { "%e", 0, { "0.000000e+00", NULL, "0.000000e+000" }}, 771 + { "%g", 0, { "0" }}, 772 + { "%21f", 0, { " 0.000000" }}, 773 + { "%20e", 0, { " 0.000000e+00", NULL, " 0.000000e+000" }}, 774 + { "%20g", 0, { " 0" }}, 775 + { "%.21f", 0, { "0.000000000000000000000" }}, 776 + { "%.20e", 0, { "0.00000000000000000000e+00", NULL, "0.00000000000000000000e+000" }}, 777 + { "%.20g", 0, { "0" }}, 778 + { "%.021f", 0, { "0.000000000000000000000" }}, 779 + { "%.020e", 0, { "0.00000000000000000000e+00", NULL, "0.00000000000000000000e+000" }}, 780 + { "%.020g", 0, { "0" }}, 781 + { "%#.21f", 0, { "0.000000000000000000000" }}, 782 + { "%#.20e", 0, { "0.00000000000000000000e+00", NULL, "0.00000000000000000000e+000" }}, 783 + { "%#.20g", 0, { "0.0000000000000000000" }, { "0.00000000000000000000" }}, 784 + 785 + { "%f", 123, { "123.000000" }}, 786 + { "%e", 123, { "1.230000e+02", NULL, "1.230000e+002" }}, 787 + { "%g", 123, { "123" }}, 788 + { "%21f", 123, { " 123.000000" }}, 789 + { "%20e", 123, { " 1.230000e+02", NULL, " 1.230000e+002" }}, 790 + { "%20g", 123, { " 123" }}, 791 + { "%.21f", 123, { "123.000000000000000000000" }}, 792 + { "%.20e", 123, { "1.23000000000000000000e+02", NULL, "1.23000000000000000000e+002" }}, 793 + { "%.20g", 123, { "123" }}, 794 + { "%.021f", 123, { "123.000000000000000000000" }}, 795 + { "%.020e", 123, { "1.23000000000000000000e+02", NULL, "1.23000000000000000000e+002" }}, 796 + { "%.020g", 123, { "123" }}, 797 + { "%#.21f", 123, { "123.000000000000000000000" }}, 798 + { "%#.20e", 123, { "1.23000000000000000000e+02", NULL, "1.23000000000000000000e+002" }}, 799 + { "%#.20g", 123, { "123.00000000000000000" }}, 800 + 801 + { "%f", -765, { "-765.000000" }}, 802 + { "%e", -765, { "-7.650000e+02", NULL, "-7.650000e+002" }}, 803 + { "%g", -765, { "-765" }}, 804 + { "%21f", -765, { " -765.000000" }}, 805 + { "%20e", -765, { " -7.650000e+02", NULL, " -7.650000e+002" }}, 806 + { "%20g", -765, { " -765" }}, 807 + { "%.21f", -765, { "-765.000000000000000000000" }}, 808 + { "%.20e", -765, { "-7.65000000000000000000e+02", NULL, "-7.65000000000000000000e+002" }}, 809 + { "%.20g", -765, { "-765" }}, 810 + { "%.021f", -765, { "-765.000000000000000000000" }}, 811 + { "%.020e", -765, { "-7.65000000000000000000e+02", NULL, "-7.65000000000000000000e+002" }}, 812 + { "%.020g", -765, { "-765" }}, 813 + { "%#.21f", -765, { "-765.000000000000000000000" }}, 814 + { "%#.20e", -765, { "-7.65000000000000000000e+02", NULL, "-7.65000000000000000000e+002" }}, 815 + { "%#.20g", -765, { "-765.00000000000000000" }}, 816 + { "%.30f", 1.0/3.0, { "0.333333333333333314829616256247" }}, 817 + { "%.30lf", sqrt(2), { "1.414213562373095145474621858739" }}, 818 + { "%f", 3.141592653590000, { "3.141593" }}, 819 + { "%.10f", 3.141592653590000, { "3.1415926536" }}, 820 + { "%.11f", 3.141592653590000, { "3.14159265359" }}, 821 + { "%.15f", 3.141592653590000, { "3.141592653590000" }}, 822 + { "%.15f", M_PI, { "3.141592653589793" }}, 823 + { "%.13f", 37.866261574537077, { "37.8662615745371" }}, 824 + { "%.14f", 37.866261574537077, { "37.86626157453708" }}, 825 + { "%.15f", 37.866261574537077, { "37.866261574537077" }}, 826 + { "%.0g", 9.8949714229143402e-05, { "0.0001" }}, 827 + { "%.0f", 0.5, { "1", NULL, NULL, NULL, "0" }, {NULL, NULL, NULL, NULL, "1" }}, 828 + { "%.0f", 1.5, { "2" }}, 829 + { "%.0f", 2.5, { "3", NULL, NULL, NULL, "2" }, {NULL, NULL, NULL, NULL, "3" }}, 830 + { "%g", 9.999999999999999e-5, { "0.0001" }}, 831 + 832 + { "%g", 0.0005, { "0.0005" }}, 833 + { "%g", 0.00005, { "5e-05", NULL, "5e-005" }}, 834 + { "%g", 0.000005, { "5e-06", NULL, "5e-006" }}, 835 + { "%g", 999999999999999.0, { "1e+15", NULL, "1e+015" }}, 836 + { "%g", 1000000000000000.0, { "1e+15", NULL, "1e+015" }}, 837 + { "%.15g", 0.0005, { "0.0005" }}, 838 + { "%.15g", 0.00005, { "5e-05", NULL, "5e-005" }}, 839 + { "%.15g", 0.000005, { "5e-06", NULL, "5e-006" }}, 840 + { "%.15g", 999999999999999.0, { "999999999999999" }}, 841 + { "%.15g", 1000000000000000.0, { "1e+15", NULL, "1e+015" }}, 842 + }; 843 + 844 + const char *res = NULL; 845 + const char *broken_res; 846 + char buf[100]; 847 + int i, j, r; 848 + 849 + for (i = 0; i < ARRAY_SIZE(tests); i++) 850 + { 851 + broken_res = NULL; 852 + 853 + for (j = 0; j < ARRAY_SIZE(flags); j++) 854 + { 855 + if (tests[i].res[j]) res = tests[i].res[j]; 856 + if (tests[i].broken[j]) broken_res = tests[i].broken[j]; 857 + 858 + r = vsprintf_wrapper(flags[j], buf, sizeof(buf), tests[i].fmt, tests[i].d); 859 + ok(r == strlen(res) || broken(broken_res && r == strlen(broken_res)), 860 + "%d,%d) r = %d, expected %Id\n", i, j, r, strlen(res)); 861 + ok(!strcmp(buf, res) || broken(broken_res && !strcmp(buf, broken_res)), 862 + "%d,%d) buf = %s, expected %s\n", i, j, buf, res); 863 + } 864 + } 865 + } 866 + 867 + static void test_printf_width_specification(void) 868 + { 869 + int r; 870 + char buffer[20]; 871 + 872 + r = vsprintf_wrapper(0, buffer, sizeof(buffer), "%0*2d", 1, 3); 873 + ok(r == 2, "r = %d\n", r); 874 + ok(!strcmp(buffer, "03"), "buffer wrong, got=%s\n", buffer); 875 + 876 + r = vsprintf_wrapper(0, buffer, sizeof(buffer), "%*0d", 1, 2); 877 + ok(r == 1, "r = %d\n", r); 878 + ok(!strcmp(buffer, "2"), "buffer wrong, got=%s\n", buffer); 879 + 880 + r = vsprintf_wrapper(0, buffer, sizeof(buffer), "% *2d", 0, 7); 881 + ok(r == 2, "r = %d\n", r); 882 + ok(!strcmp(buffer, " 7"), "buffer wrong, got=%s\n", buffer); 883 + } 884 + 885 + START_TEST(printf) 886 + { 887 + ok(_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL, 888 + "Invalid parameter handler was already set\n"); 889 + 890 + test_snprintf(); 891 + test_swprintf(); 892 + test_fprintf(); 893 + test_fwprintf(); 894 + test_vsnprintf_s(); 895 + test_vsnwprintf_s(); 896 + test_printf_legacy_wide(); 897 + test_printf_legacy_msvcrt(); 898 + test_printf_legacy_three_digit_exp(); 899 + test_printf_c99(); 900 + test_printf_natural_string(); 901 + test_printf_fp(); 902 + test_printf_width_specification(); 903 + }
+330
modules/rostests/winetests/ucrtbase/scanf.c
··· 1 + /* 2 + * Conformance tests for *scanf functions. 3 + * 4 + * Copyright 2002 Uwe Bonnes 5 + * 6 + * This library is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU Lesser General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2.1 of the License, or (at your option) any later version. 10 + * 11 + * This library is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * Lesser General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU Lesser General Public 17 + * License along with this library; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 + */ 20 + 21 + #include <stdio.h> 22 + #include <math.h> 23 + 24 + #include "windef.h" 25 + #include "winbase.h" 26 + #include "winnls.h" 27 + 28 + #include "wine/test.h" 29 + 30 + static int WINAPIV vsscanf_wrapper(unsigned __int64 options, const char *str, size_t len, const char *format, ...) 31 + { 32 + int ret; 33 + va_list valist; 34 + va_start(valist, format); 35 + ret = __stdio_common_vsscanf(options, str, len, format, NULL, valist); 36 + va_end(valist); 37 + return ret; 38 + } 39 + 40 + static void test_sscanf(void) 41 + { 42 + static const float float1 = -82.6267f, float2 = 27.76f; 43 + char buffer[100], buffer1[100]; 44 + int result, ret, hour, min, count; 45 + LONGLONG result64; 46 + DWORD_PTR result_ptr; 47 + char c; 48 + void *ptr; 49 + float ret_float1, ret_float2; 50 + double double_res; 51 + unsigned int i; 52 + size_t ret_size; 53 + 54 + static const unsigned int tests[] = 55 + { 56 + 0, 57 + _CRT_INTERNAL_SCANF_LEGACY_WIDE_SPECIFIERS, 58 + _CRT_INTERNAL_SCANF_LEGACY_MSVCRT_COMPATIBILITY, 59 + }; 60 + 61 + for (i = 0; i < ARRAY_SIZE(tests); ++i) 62 + { 63 + ret = vsscanf_wrapper(tests[i], "", -1, "%d", &result); 64 + ok(ret == EOF, "sscanf returned %d for flags %#x\n", ret, tests[i]); 65 + 66 + ret = vsscanf_wrapper(tests[i], "000000000046F170", -1, "%p", &ptr); 67 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 68 + ok(ptr == (void *)0x46f170, "sscanf reads %p for flags %#x\n", ptr, tests[i]); 69 + 70 + ret = vsscanf_wrapper(tests[i], "0046F171", -1, "%p", &ptr); 71 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 72 + ok(ptr == (void *)0x46f171, "sscanf reads %p for flags %#x\n", ptr, tests[i]); 73 + 74 + ret = vsscanf_wrapper(tests[i], "46F172", -1, "%p", &ptr); 75 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 76 + ok(ptr == (void *)0x46f172, "sscanf reads %p for flags %#x\n", ptr, tests[i]); 77 + 78 + ret = vsscanf_wrapper(tests[i], "0x46F173", -1, "%p", &ptr); 79 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 80 + todo_wine ok(ptr == (void *)0x46f173, "sscanf reads %p for flags %#x\n", ptr, tests[i]); 81 + 82 + ret = vsscanf_wrapper(tests[i], "-46F174", -1, "%p", &ptr); 83 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 84 + ok(ptr == (void *)(ULONG_PTR)-0x46f174, "sscanf reads %p for flags %#x\n", ptr, tests[i]); 85 + 86 + ret = vsscanf_wrapper(tests[i], "+46F175", -1, "%p", &ptr); 87 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 88 + ok(ptr == (void *)0x46f175, "sscanf reads %p for flags %#x\n", ptr, tests[i]); 89 + 90 + ret = vsscanf_wrapper(tests[i], "1233", -1, "%p", &ptr); 91 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 92 + ok(ptr == (void *)0x1233, "sscanf reads %p for flags %#x\n", ptr, tests[i]); 93 + 94 + ret = vsscanf_wrapper(tests[i], "1234", -1, "%P", &ptr); 95 + todo_wine ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); 96 + 97 + ret = vsscanf_wrapper(tests[i], "0x519", -1, "%x", &result); 98 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 99 + ok(result == 0x519, "sscanf reads %#x for flags %#x\n", result, tests[i]); 100 + 101 + ret = vsscanf_wrapper(tests[i], "0x51a", -1, "%x", &result); 102 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 103 + ok(result == 0x51a, "sscanf reads %#x for flags %#x\n", result, tests[i]); 104 + 105 + ret = vsscanf_wrapper(tests[i], "0x51g", -1, "%x", &result); 106 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 107 + ok(result == 0x51, "sscanf reads %#x for flags %#x\n", result, tests[i]); 108 + 109 + result = 0; 110 + ret = vsscanf_wrapper(tests[i], "-1", -1, "%x", &result); 111 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 112 + ok(result == -1, "sscanf reads %#x for flags %#x\n", result, tests[i]); 113 + 114 + ret = vsscanf_wrapper(tests[i], "\"%12@", -1, "%\"%%%d%@", &result); 115 + todo_wine ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); 116 + 117 + sprintf(buffer, "%f %f", float1, float2); 118 + ret = vsscanf_wrapper(tests[i], buffer, -1, "%f%f", &ret_float1, &ret_float2); 119 + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); 120 + ok(ret_float1 == float1, "got wrong float %.8e for flags %#x\n", ret_float1, tests[i]); 121 + ok(ret_float2 == float2, "got wrong float %.8e for flags %#x\n", ret_float2, tests[i]); 122 + 123 + sprintf(buffer, "%lf", 32.715); 124 + ret = vsscanf_wrapper(tests[i], buffer, -1, "%lf", &double_res); 125 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 126 + ok(double_res == 32.715, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 127 + ret = vsscanf_wrapper(tests[i], buffer, -1, "%Lf", &double_res); 128 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 129 + ok(double_res == 32.715, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 130 + 131 + ret = vsscanf_wrapper(tests[i], "1.1e-30", -1, "%lf", &double_res); 132 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 133 + ok(double_res == 1.1e-30, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 134 + 135 + ret = vsscanf_wrapper(tests[i], " Waverly", -1, "%*c%[^\n]", buffer); 136 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 137 + ok(!strcmp(buffer, " Waverly"), "got string '%s' for flags %#x\n", buffer, tests[i]); 138 + 139 + ret = vsscanf_wrapper(tests[i], "abcefgdh", -1, "%*[a-cg-e]%c", &buffer[0]); 140 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 141 + ok(buffer[0] == 'd', "got char '%c' for flags %#x\n", buffer[0], tests[i]); 142 + 143 + ret = vsscanf_wrapper(tests[i], "abcefgdh", -1, "%*[a-cd-dg-e]%c", &buffer[0]); 144 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 145 + ok(buffer[0] == 'h', "got char '%c' for flags %#x\n", buffer[0], tests[i]); 146 + 147 + strcpy(buffer, "foo"); 148 + strcpy(buffer1, "bar"); 149 + ret = vsscanf_wrapper(tests[i], "a", -1, "%s%s", buffer, buffer1); 150 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 151 + ok(!strcmp(buffer, "a"), "got string '%s' for flags %#x\n", buffer, tests[i]); 152 + ok(!strcmp(buffer1, "bar"), "got string '%s' for flags %#x\n", buffer1, tests[i]); 153 + 154 + ret = vsscanf_wrapper(tests[i], "21:59:20", -1, "%d%n", &result, &count); 155 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 156 + ok(result == 21, "got wrong number %d for flags %#x\n", result, tests[i]); 157 + ok(count == 2, "got wrong count %d for flags %#x\n", count, tests[i]); 158 + 159 + ret = vsscanf_wrapper(tests[i], ":59:20", -1, "%*c%n", &count); 160 + ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); 161 + ok(count == 1, "got wrong count %d for flags %#x\n", count, tests[i]); 162 + 163 + result = 0xdeadbeef; 164 + ret = vsscanf_wrapper(tests[i], "12345678", -1, "%hd", &result); 165 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 166 + ok(result == 0xdead614e, "got wrong number %#x for flags %#x\n", result, tests[i]); 167 + 168 + result = 0xdeadbeef; 169 + ret = vsscanf_wrapper(tests[i], "12345678", -1, "%hhd", &result); 170 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 171 + ok(result == 0xdeadbe4e, "got wrong number %#x for flags %#x\n", result, tests[i]); 172 + 173 + ret = vsscanf_wrapper(tests[i], "12345678901234", -1, "%lld", &result64); 174 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 175 + ok(result64 == 12345678901234, "got wrong number 0x%s for flags %#x\n", 176 + wine_dbgstr_longlong(result64), tests[i]); 177 + 178 + ret = vsscanf_wrapper(tests[i], "123", -1, "%i", &result); 179 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 180 + ok(result == 123, "got wrong number %d for flags %#x\n", result, tests[i]); 181 + 182 + ret = vsscanf_wrapper(tests[i], "-1", -1, "%i", &result); 183 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 184 + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); 185 + 186 + ret = vsscanf_wrapper(tests[i], "123", -1, "%d", &result); 187 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 188 + ok(result == 123, "got wrong number %d for flags %#x\n", result, tests[i]); 189 + 190 + ret = vsscanf_wrapper(tests[i], "-1", -1, "%d", &result); 191 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 192 + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); 193 + 194 + ret = vsscanf_wrapper(tests[i], "017", -1, "%i", &result); 195 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 196 + ok(result == 15, "got wrong number %d for flags %#x\n", result, tests[i]); 197 + 198 + ret = vsscanf_wrapper(tests[i], "0x17", -1, "%i", &result); 199 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 200 + ok(result == 23, "got wrong number %d for flags %#x\n", result, tests[i]); 201 + 202 + ret = vsscanf_wrapper(tests[i], "-1", -1, "%o", &result); 203 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 204 + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); 205 + 206 + ret = 0xdeadbeef; 207 + ret = vsscanf_wrapper(tests[i], "-1", -1, "%u", &result); 208 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 209 + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); 210 + 211 + c = 0x55; 212 + ret = vsscanf_wrapper(tests[i], "a", -1, "%c", &c); 213 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 214 + ok(c == 'a', "got wrong char '%c' for flags %#x\n", c, tests[i]); 215 + 216 + c = 0x55; 217 + ret = vsscanf_wrapper(tests[i], " a", -1, "%c", &c); 218 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 219 + ok(c == ' ', "got wrong char '%c' for flags %#x\n", c, tests[i]); 220 + 221 + c = 0x55; 222 + ret = vsscanf_wrapper(tests[i], "18:59", -1, "%d:%d%c", &hour, &min, &c); 223 + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); 224 + ok(hour == 18, "got wrong char '%c' for flags %#x\n", hour, tests[i]); 225 + ok(min == 59, "got wrong char '%c' for flags %#x\n", min, tests[i]); 226 + ok(c == 0x55, "got wrong char '%c' for flags %#x\n", c, tests[i]); 227 + 228 + strcpy(buffer, "foo"); 229 + strcpy(buffer1, "bar"); 230 + ret = vsscanf_wrapper(tests[i], "abc def", -1, "%s %n%s", buffer, &count, buffer1); 231 + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); 232 + ok(!strcmp(buffer, "abc"), "got wrong string '%s' for flags %#x\n", buffer, tests[i]); 233 + ok(count == 6, "got wrong count %d for flags %#x\n", count, tests[i]); 234 + ok(!strcmp(buffer1, "def"), "got wrong string '%s' for flags %#x\n", buffer1, tests[i]); 235 + 236 + ret = vsscanf_wrapper(tests[i], "3:45", -1, "%d:%d%n", &hour, &min, &count); 237 + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); 238 + ok(hour == 3, "got wrong char '%c' for flags %#x\n", hour, tests[i]); 239 + ok(min == 45, "got wrong char '%c' for flags %#x\n", min, tests[i]); 240 + ok(count == 4, "got wrong count %d for flags %#x\n", count, tests[i]); 241 + 242 + strcpy(buffer, "foo"); 243 + strcpy(buffer1, "bar"); 244 + ret = vsscanf_wrapper(tests[i], "test=value\xda", -1, "%[^=] = %[^;]", buffer, buffer1); 245 + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); 246 + ok(!strcmp(buffer, "test"), "got wrong string '%s' for flags %#x\n", buffer, tests[i]); 247 + ok(!strcmp(buffer1, "value\xda"), "got wrong string '%s' for flags %#x\n", buffer1, tests[i]); 248 + 249 + ret = vsscanf_wrapper(tests[i], "0.1", 3, "%lf%n", &double_res, &count); 250 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 251 + ok(double_res == 0.1, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 252 + ok(count == 3, "got wrong count %d for flags %#x\n", count, tests[i]); 253 + 254 + ret = vsscanf_wrapper(tests[i], "a", -1, "%lf%n", &double_res, &count); 255 + ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); 256 + 257 + ret = vsscanf_wrapper(tests[i], "aa", -1, "%c%lf%n", &c, &double_res, &count); 258 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 259 + 260 + ret = vsscanf_wrapper(tests[i], "a0e", -1, "%c%lf%n", &c, &double_res, &count); 261 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 262 + 263 + ret = vsscanf_wrapper(tests[i], "0.", -1, "%lf%n", &double_res, &count); 264 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 265 + ok(double_res == 0, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 266 + ok(count == 2, "got wrong count %d for flags %#x\n", count, tests[i]); 267 + 268 + ret = vsscanf_wrapper(tests[i], "0.", 2, "%lf%n", &double_res, &count); 269 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 270 + ok(double_res == 0, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 271 + ok(count == 2, "got wrong count %d for flags %#x\n", count, tests[i]); 272 + 273 + ret = vsscanf_wrapper(tests[i], "1e", -1, "%lf%n", &double_res, &count); 274 + ok(ret == -1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 275 + 276 + ret = vsscanf_wrapper(tests[i], "1e ", 2, "%lf%n", &double_res, &count); 277 + ok(ret == -1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 278 + 279 + ret = vsscanf_wrapper(tests[i], "1e+", -1, "%lf%n", &double_res, &count); 280 + ok(ret == -1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 281 + 282 + ret = vsscanf_wrapper(tests[i], "inf", -1, "%lf%n", &double_res, &count); 283 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 284 + ok(double_res == INFINITY, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 285 + ok(count == 3, "got wrong count %d for flags %#x\n", count, tests[i]); 286 + 287 + ret = vsscanf_wrapper(tests[i], "infa", -1, "%lf%n", &double_res, &count); 288 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 289 + ok(double_res == INFINITY, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); 290 + ok(count == 3, "got wrong count %d for flags %#x\n", count, tests[i]); 291 + 292 + ret = vsscanf_wrapper(tests[i], "infi", -1, "%lf%n", &double_res, &count); 293 + ok(ret == -1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 294 + 295 + ret_size = ~0; 296 + ret = vsscanf_wrapper(tests[i], "1", -1, "%zd", &ret_size); 297 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 298 + ok(ret_size == 1, "got wrong size_t %s for flags %#x\n", 299 + wine_dbgstr_longlong((LONGLONG)ret_size), tests[i]); 300 + 301 + result64 = 0; 302 + ret = vsscanf_wrapper(tests[i], "12345678901234", -1, "%I64d", &result64); 303 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 304 + ok(result64 == 12345678901234ll, "got wrong number 0x%s for flags %#x\n", 305 + wine_dbgstr_longlong(result64), tests[i]); 306 + 307 + result = 0; 308 + ret = vsscanf_wrapper(tests[i], "12345678901234", -1, "%I32d", &result); 309 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 310 + ok(result == (int)12345678901234ll, /* this is always truncated to 32bit */ 311 + "got wrong number 0x%d for flags %#x\n", result, tests[i]); 312 + 313 + result_ptr = 0; 314 + ret = vsscanf_wrapper(tests[i], "0x87654321", -1, "%Ix", &result_ptr); 315 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 316 + ok(result_ptr == 0x87654321, 317 + "got wrong number %Ix for flags %#x\n", result_ptr, tests[i]); 318 + 319 + result_ptr = 0; 320 + ret = vsscanf_wrapper(tests[i], "0x123456789", -1, "%Ix", &result_ptr); 321 + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); 322 + ok(result_ptr == (DWORD_PTR)0x123456789ull, /* this is truncated on 32bit systems */ 323 + "got wrong number %Ix for flags %#x\n", result_ptr, tests[i]); 324 + } 325 + } 326 + 327 + START_TEST(scanf) 328 + { 329 + test_sscanf(); 330 + }
+860
modules/rostests/winetests/ucrtbase/string.c
··· 1 + /* 2 + * Copyright 2015 Martin Storsjo 3 + * 4 + * This library is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU Lesser General Public 6 + * License as published by the Free Software Foundation; either 7 + * version 2.1 of the License, or (at your option) any later version. 8 + * 9 + * This library is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * Lesser General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU Lesser General Public 15 + * License along with this library; if not, write to the Free Software 16 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 + */ 18 + 19 + #include <errno.h> 20 + #include <stdarg.h> 21 + #include <stdlib.h> 22 + #include <wchar.h> 23 + #include <stdio.h> 24 + #include <locale.h> 25 + #include <mbctype.h> 26 + #include <mbstring.h> 27 + 28 + #include <windef.h> 29 + #include <winbase.h> 30 + #include "wine/test.h" 31 + 32 + #include <math.h> 33 + 34 + #define DEFINE_EXPECT(func) \ 35 + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 36 + 37 + #define SET_EXPECT(func) \ 38 + expect_ ## func = TRUE 39 + 40 + #define CHECK_EXPECT2(func) \ 41 + do { \ 42 + ok(expect_ ##func, "unexpected call " #func "\n"); \ 43 + called_ ## func = TRUE; \ 44 + }while(0) 45 + 46 + #define CHECK_EXPECT(func) \ 47 + do { \ 48 + CHECK_EXPECT2(func); \ 49 + expect_ ## func = FALSE; \ 50 + }while(0) 51 + 52 + #define CHECK_CALLED(func) \ 53 + do { \ 54 + ok(called_ ## func, "expected " #func "\n"); \ 55 + expect_ ## func = called_ ## func = FALSE; \ 56 + }while(0) 57 + 58 + DEFINE_EXPECT(invalid_parameter_handler); 59 + 60 + static void __cdecl test_invalid_parameter_handler(const wchar_t *expression, 61 + const wchar_t *function, const wchar_t *file, 62 + unsigned line, uintptr_t arg) 63 + { 64 + CHECK_EXPECT(invalid_parameter_handler); 65 + ok(expression == NULL, "expression is not NULL\n"); 66 + ok(function == NULL, "function is not NULL\n"); 67 + ok(file == NULL, "file is not NULL\n"); 68 + ok(line == 0, "line = %u\n", line); 69 + ok(arg == 0, "arg = %Ix\n", arg); 70 + } 71 + 72 + _ACRTIMP int __cdecl _o_tolower(int); 73 + _ACRTIMP int __cdecl _o_toupper(int); 74 + 75 + static BOOL local_isnan(double d) 76 + { 77 + return d != d; 78 + } 79 + 80 + #define test_strtod_str_errno(string, value, length, err) _test_strtod_str(__LINE__, string, value, length, err) 81 + #define test_strtod_str(string, value, length) _test_strtod_str(__LINE__, string, value, length, 0) 82 + static void _test_strtod_str(int line, const char* string, double value, int length, int err) 83 + { 84 + char *end; 85 + double d; 86 + errno = 0xdeadbeef; 87 + d = strtod(string, &end); 88 + if(!err) 89 + ok_(__FILE__, line)(errno == 0xdeadbeef, "errno = %d\n", errno); 90 + else 91 + ok_(__FILE__, line)(errno == err, "errno = %d\n", errno); 92 + if (local_isnan(value)) 93 + ok_(__FILE__, line)(local_isnan(d), "d = %.16le (\"%s\")\n", d, string); 94 + else 95 + ok_(__FILE__, line)(d == value, "d = %.16le (\"%s\")\n", d, string); 96 + ok_(__FILE__, line)(end == string + length, "incorrect end (%d, \"%s\")\n", (int)(end - string), string); 97 + } 98 + 99 + static void test_strtod(void) 100 + { 101 + test_strtod_str("infinity", INFINITY, 8); 102 + test_strtod_str("INFINITY", INFINITY, 8); 103 + test_strtod_str("InFiNiTy", INFINITY, 8); 104 + test_strtod_str("INF", INFINITY, 3); 105 + test_strtod_str("-inf", -INFINITY, 4); 106 + test_strtod_str("inf42", INFINITY, 3); 107 + test_strtod_str("inffoo", INFINITY, 3); 108 + test_strtod_str("infini", INFINITY, 3); 109 + test_strtod_str("input", 0, 0); 110 + test_strtod_str("-input", 0, 0); 111 + test_strtod_str_errno("1.7976931348623159e+308", INFINITY, 23, ERANGE); 112 + test_strtod_str_errno("-1.7976931348623159e+308", -INFINITY, 24, ERANGE); 113 + 114 + test_strtod_str("NAN", NAN, 3); 115 + test_strtod_str("nan", NAN, 3); 116 + test_strtod_str("NaN", NAN, 3); 117 + 118 + test_strtod_str("0x42", 66, 4); 119 + test_strtod_str("0X42", 66, 4); 120 + test_strtod_str("-0x42", -66, 5); 121 + test_strtod_str("0x1p1", 2, 5); 122 + test_strtod_str("0x1P1", 2, 5); 123 + test_strtod_str("0x1p+1", 2, 6); 124 + test_strtod_str("0x2p-1", 1, 6); 125 + test_strtod_str("0xA", 10, 3); 126 + test_strtod_str("0xa", 10, 3); 127 + test_strtod_str("0xABCDEF", 11259375, 8); 128 + test_strtod_str("0Xabcdef", 11259375, 8); 129 + 130 + test_strtod_str("0x1.1", 1.0625, 5); 131 + test_strtod_str("0x1.1p1", 2.125, 7); 132 + test_strtod_str("0x1.A", 1.625, 5); 133 + test_strtod_str("0x1p1a", 2, 5); 134 + test_strtod_str("0xp3", 0, 1); 135 + test_strtod_str("0x.", 0, 1); 136 + test_strtod_str("0x.8", 0.5, 4); 137 + test_strtod_str("0x.8p", 0.5, 4); 138 + test_strtod_str("0x0p10000000000000000000000000", 0, 30); 139 + test_strtod_str("0x1p-1026", 1.3906711615670009e-309, 9); 140 + 141 + test_strtod_str("0x1ffffffffffffe.80000000000000000000", 9007199254740990.0, 37); 142 + test_strtod_str("0x1ffffffffffffe.80000000000000000001", 9007199254740991.0, 37); 143 + test_strtod_str("0x1fffffffffffff.80000000000000000000", 9007199254740992.0, 37); 144 + test_strtod_str("0x1fffffffffffff.80000000000000000001", 9007199254740992.0, 37); 145 + 146 + test_strtod_str("4.0621786324484881721115322e-53", 4.0621786324484881721115322e-53, 31); 147 + test_strtod_str("1.8905590910042396899370942", 1.8905590910042396899370942, 27); 148 + test_strtod_str("1.7976931348623158e+308", 1.7976931348623158e+308, 23); 149 + test_strtod_str("2.2250738585072014e-308", 2.2250738585072014e-308, 23); 150 + test_strtod_str("4.9406564584124654e-324", 4.9406564584124654e-324, 23); 151 + test_strtod_str("2.48e-324", 4.9406564584124654e-324, 9); 152 + test_strtod_str_errno("2.47e-324", 0, 9, ERANGE); 153 + } 154 + 155 + static void test_strtof(void) 156 + { 157 + static const struct { 158 + const char *str; 159 + int len; 160 + float ret; 161 + int err; 162 + } tests[] = { 163 + { "12.1", 4, 12.1f }, 164 + { "-13.721", 7, -13.721f }, 165 + { "1.e40", 5, INFINITY, ERANGE }, 166 + { "-1.e40", 6, -INFINITY, ERANGE }, 167 + { "0.0", 3, 0.0f }, 168 + { "-0.0", 4, 0.0f }, 169 + { "1.4e-45", 7, 1.4e-45f }, 170 + { "-1.4e-45", 8, -1.4e-45f }, 171 + { "1.e-60", 6, 0, ERANGE }, 172 + { "-1.e-60", 7, 0, ERANGE }, 173 + }; 174 + 175 + char *end; 176 + float f; 177 + int i; 178 + 179 + for (i=0; i<ARRAY_SIZE(tests); i++) 180 + { 181 + errno = 0xdeadbeef; 182 + f = strtof(tests[i].str, &end); 183 + ok(f == tests[i].ret, "%d) f = %.16e\n", i, f); 184 + ok(end == tests[i].str + tests[i].len, "%d) len = %d\n", 185 + i, (int)(end - tests[i].str)); 186 + ok(errno == tests[i].err || (!tests[i].err && errno == 0xdeadbeef), 187 + "%d) errno = %d\n", i, errno); 188 + } 189 + } 190 + 191 + static void test__memicmp(void) 192 + { 193 + static const char *s1 = "abc"; 194 + static const char *s2 = "aBd"; 195 + int ret; 196 + 197 + ret = _memicmp(NULL, NULL, 0); 198 + ok(!ret, "got %d\n", ret); 199 + 200 + SET_EXPECT(invalid_parameter_handler); 201 + errno = 0xdeadbeef; 202 + ret = _memicmp(NULL, NULL, 1); 203 + ok(ret == _NLSCMPERROR, "got %d\n", ret); 204 + ok(errno == EINVAL, "Unexpected errno = %d\n", errno); 205 + CHECK_CALLED(invalid_parameter_handler); 206 + 207 + SET_EXPECT(invalid_parameter_handler); 208 + errno = 0xdeadbeef; 209 + ret = _memicmp(s1, NULL, 1); 210 + ok(ret == _NLSCMPERROR, "got %d\n", ret); 211 + ok(errno == EINVAL, "Unexpected errno = %d\n", errno); 212 + CHECK_CALLED(invalid_parameter_handler); 213 + 214 + SET_EXPECT(invalid_parameter_handler); 215 + errno = 0xdeadbeef; 216 + ret = _memicmp(NULL, s2, 1); 217 + ok(ret == _NLSCMPERROR, "got %d\n", ret); 218 + ok(errno == EINVAL, "Unexpected errno = %d\n", errno); 219 + CHECK_CALLED(invalid_parameter_handler); 220 + 221 + ret = _memicmp(s1, s2, 2); 222 + ok(!ret, "got %d\n", ret); 223 + 224 + ret = _memicmp(s1, s2, 3); 225 + ok(ret == -1, "got %d\n", ret); 226 + } 227 + 228 + static void test__memicmp_l(void) 229 + { 230 + static const char *s1 = "abc"; 231 + static const char *s2 = "aBd"; 232 + int ret; 233 + 234 + ret = _memicmp_l(NULL, NULL, 0, NULL); 235 + ok(!ret, "got %d\n", ret); 236 + 237 + SET_EXPECT(invalid_parameter_handler); 238 + errno = 0xdeadbeef; 239 + ret = _memicmp_l(NULL, NULL, 1, NULL); 240 + ok(ret == _NLSCMPERROR, "got %d\n", ret); 241 + ok(errno == EINVAL, "Unexpected errno = %d\n", errno); 242 + CHECK_CALLED(invalid_parameter_handler); 243 + 244 + SET_EXPECT(invalid_parameter_handler); 245 + errno = 0xdeadbeef; 246 + ret = _memicmp_l(s1, NULL, 1, NULL); 247 + ok(ret == _NLSCMPERROR, "got %d\n", ret); 248 + ok(errno == EINVAL, "Unexpected errno = %d\n", errno); 249 + CHECK_CALLED(invalid_parameter_handler); 250 + 251 + SET_EXPECT(invalid_parameter_handler); 252 + errno = 0xdeadbeef; 253 + ret = _memicmp_l(NULL, s2, 1, NULL); 254 + ok(ret == _NLSCMPERROR, "got %d\n", ret); 255 + ok(errno == EINVAL, "Unexpected errno = %d\n", errno); 256 + CHECK_CALLED(invalid_parameter_handler); 257 + 258 + ret = _memicmp_l(s1, s2, 2, NULL); 259 + ok(!ret, "got %d\n", ret); 260 + 261 + ret = _memicmp_l(s1, s2, 3, NULL); 262 + ok(ret == -1, "got %d\n", ret); 263 + } 264 + 265 + 266 + static void test___strncnt(void) 267 + { 268 + static const struct 269 + { 270 + const char *str; 271 + size_t size; 272 + size_t ret; 273 + } 274 + strncnt_tests[] = 275 + { 276 + { "a", 0, 0 }, 277 + { "a", 1, 1 }, 278 + { "a", 10, 1 }, 279 + { "abc", 1, 1 }, 280 + }; 281 + unsigned int i; 282 + size_t ret; 283 + 284 + for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i) 285 + { 286 + ret = __strncnt(strncnt_tests[i].str, strncnt_tests[i].size); 287 + ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret); 288 + } 289 + 290 + if (0) /* crashes */ 291 + { 292 + ret = __strncnt(NULL, 0); 293 + ret = __strncnt(NULL, 1); 294 + } 295 + } 296 + 297 + static void test_C_locale(void) 298 + { 299 + int i, j; 300 + wint_t ret, exp; 301 + _locale_t locale; 302 + static const char *locales[] = { NULL, "C" }; 303 + 304 + /* C locale only converts case for [a-zA-Z] */ 305 + setlocale(LC_ALL, "C"); 306 + for (i = 0; i <= 0xffff; i++) 307 + { 308 + ret = tolower(i); 309 + if (i >= 'A' && i <= 'Z') 310 + { 311 + exp = i + 'a' - 'A'; 312 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 313 + } 314 + else 315 + ok(ret == i, "expected self %x, got %x for C locale\n", i, ret); 316 + 317 + ret = _tolower(i); 318 + exp = i + 'a' - 'A'; 319 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 320 + 321 + ret = _o_tolower(i); 322 + if (i >= 'A' && i <= 'Z') 323 + { 324 + exp = i + 'a' - 'A'; 325 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 326 + } 327 + else 328 + ok(ret == i, "expected self %x, got %x for C locale\n", i, ret); 329 + 330 + ret = towlower(i); 331 + if (i >= 'A' && i <= 'Z') 332 + { 333 + exp = i + 'a' - 'A'; 334 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 335 + } 336 + else 337 + ok(ret == i, "expected self %x, got %x for C locale\n", i, ret); 338 + 339 + ret = toupper(i); 340 + if (i >= 'a' && i <= 'z') 341 + { 342 + exp = i + 'A' - 'a'; 343 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 344 + } 345 + else 346 + ok(ret == i, "expected self %x, got %x for C locale\n", i, ret); 347 + 348 + ret = _toupper(i); 349 + exp = i + 'A' - 'a'; 350 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 351 + 352 + ret = _o_toupper(i); 353 + if (i >= 'a' && i <= 'z') 354 + { 355 + exp = i + 'A' - 'a'; 356 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 357 + } 358 + else 359 + ok(ret == i, "expected self %x, got %x for C locale\n", i, ret); 360 + 361 + ret = towupper(i); 362 + if (i >= 'a' && i <= 'z') 363 + { 364 + exp = i + 'A' - 'a'; 365 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 366 + } 367 + else 368 + ok(ret == i, "expected self %x, got %x for C locale\n", i, ret); 369 + } 370 + 371 + for (i = 0; i < ARRAY_SIZE(locales); i++) { 372 + locale = locales[i] ? _create_locale(LC_ALL, locales[i]) : NULL; 373 + 374 + for (j = 0; j <= 0xffff; j++) { 375 + ret = _towlower_l(j, locale); 376 + if (j >= 'A' && j <= 'Z') 377 + { 378 + exp = j + 'a' - 'A'; 379 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 380 + } 381 + else 382 + ok(ret == j, "expected self %x, got %x for C locale\n", j, ret); 383 + 384 + ret = _towupper_l(j, locale); 385 + if (j >= 'a' && j <= 'z') 386 + { 387 + exp = j + 'A' - 'a'; 388 + ok(ret == exp, "expected %x, got %x for C locale\n", exp, ret); 389 + } 390 + else 391 + ok(ret == j, "expected self %x, got %x for C locale\n", j, ret); 392 + } 393 + 394 + _free_locale(locale); 395 + } 396 + } 397 + 398 + static void test_mbsspn( void) 399 + { 400 + unsigned char str1[] = "cabernet"; 401 + unsigned char str2[] = "shiraz"; 402 + unsigned char set[] = "abc"; 403 + unsigned char empty[] = ""; 404 + unsigned char mbstr[] = " 2019\x94\x4e" "6\x8c\x8e" "29\x93\xfa"; 405 + unsigned char mbset1[] = "0123456789 \x94\x4e"; 406 + unsigned char mbset2[] = " \x94\x4e\x8c\x8e"; 407 + unsigned char mbset3[] = "\x8e"; 408 + int ret, cp = _getmbcp(); 409 + 410 + ret = _mbsspn(str1, set); 411 + ok(ret == 3, "_mbsspn returns %d should be 3\n", ret); 412 + ret = _mbsspn(str2, set); 413 + ok(ret == 0, "_mbsspn returns %d should be 0\n", ret); 414 + ret = _mbsspn(str1, empty); 415 + ok(ret == 0, "_mbsspn returns %d should be 0\n", ret); 416 + 417 + _setmbcp(932); 418 + ret = _mbsspn(mbstr, mbset1); 419 + ok(ret == 8, "_mbsspn returns %d should be 8\n", ret); 420 + ret = _mbsspn(mbstr, mbset2); 421 + ok(ret == 1, "_mbsspn returns %d should be 1\n", ret); 422 + ret = _mbsspn(mbstr+8, mbset1); 423 + ok(ret == 0, "_mbsspn returns %d should be 0\n", ret); 424 + ret = _mbsspn(mbstr+8, mbset2); 425 + ok(ret == 2, "_mbsspn returns %d should be 2\n", ret); 426 + ret = _mbsspn(mbstr, mbset3); 427 + ok(ret == 14, "_mbsspn returns %d should be 14\n", ret); 428 + 429 + _setmbcp(cp); 430 + } 431 + 432 + static void test_wcstok(void) 433 + { 434 + static const wchar_t *input = L"two words"; 435 + wchar_t buffer[16]; 436 + wchar_t *token; 437 + wchar_t *next; 438 + 439 + next = NULL; 440 + wcscpy(buffer, input); 441 + token = wcstok(buffer, L" ", &next); 442 + ok(!wcscmp(L"two", token), "expected \"two\", got \"%ls\"\n", token); 443 + ok(next == token + 4, "expected %p, got %p\n", token + 4, next); 444 + token = wcstok(NULL, L" ", &next); 445 + ok(!wcscmp(L"words", token), "expected \"words\", got \"%ls\"\n", token); 446 + ok(next == token + 5, "expected %p, got %p\n", token + 5, next); 447 + token = wcstok(NULL, L" ", &next); 448 + ok(!token, "expected NULL, got %p\n", token); 449 + 450 + wcscpy(buffer, input); 451 + token = wcstok(buffer, L" ", NULL); 452 + ok(!wcscmp(L"two", token), "expected \"two\", got \"%ls\"\n", token); 453 + token = wcstok(NULL, L" ", NULL); 454 + ok(!wcscmp(L"words", token), "expected \"words\", got \"%ls\"\n", token); 455 + token = wcstok(NULL, L" ", NULL); 456 + ok(!token, "expected NULL, got %p\n", token); 457 + 458 + next = NULL; 459 + wcscpy(buffer, input); 460 + token = wcstok(buffer, L"=", &next); 461 + ok(!wcscmp(token, input), "expected \"%ls\", got \"%ls\"\n", input, token); 462 + ok(next == buffer + wcslen(input), "expected %p, got %p\n", buffer + wcslen(input), next); 463 + token = wcstok(NULL, L"=", &next); 464 + ok(!token, "expected NULL, got \"%ls\"\n", token); 465 + ok(next == buffer + wcslen(input), "expected %p, got %p\n", buffer + wcslen(input), next); 466 + 467 + next = NULL; 468 + wcscpy(buffer, L""); 469 + token = wcstok(buffer, L"=", &next); 470 + ok(token == NULL, "expected NULL, got \"%ls\"\n", token); 471 + ok(next == buffer, "expected %p, got %p\n", buffer, next); 472 + token = wcstok(NULL, L"=", &next); 473 + ok(!token, "expected NULL, got \"%ls\"\n", token); 474 + ok(next == buffer, "expected %p, got %p\n", buffer, next); 475 + } 476 + 477 + static void test__strnicmp(void) 478 + { 479 + static const char str1[] = "TEST"; 480 + static const char str2[] = "test"; 481 + int ret; 482 + 483 + SET_EXPECT(invalid_parameter_handler); 484 + errno = 0xdeadbeef; 485 + ret = _strnicmp(str1, NULL, 2); 486 + CHECK_CALLED(invalid_parameter_handler); 487 + ok(ret == _NLSCMPERROR, "got %d.\n", ret); 488 + ok(errno == EINVAL, "Unexpected errno %d.\n", errno); 489 + 490 + SET_EXPECT(invalid_parameter_handler); 491 + errno = 0xdeadbeef; 492 + ret = _strnicmp(str1, str2, -1); 493 + CHECK_CALLED(invalid_parameter_handler); 494 + ok(ret == _NLSCMPERROR, "got %d.\n", ret); 495 + ok(errno == EINVAL, "Unexpected errno %d.\n", errno); 496 + 497 + ret = _strnicmp(str1, str2, 0); 498 + ok(!ret, "got %d.\n", ret); 499 + 500 + ret = _strnicmp(str1, str2, 0x7fffffff); 501 + ok(!ret, "got %d.\n", ret); 502 + 503 + /* If numbers of characters to compare is too big return error */ 504 + SET_EXPECT(invalid_parameter_handler); 505 + errno = 0xdeadbeef; 506 + ret = _strnicmp(str1, str2, 0x80000000); 507 + CHECK_CALLED(invalid_parameter_handler); 508 + ok(ret == _NLSCMPERROR, "got %d.\n", ret); 509 + ok(errno == EINVAL, "Unexpected errno %d.\n", errno); 510 + } 511 + 512 + static void test_wcsnicmp(void) 513 + { 514 + static const wchar_t str1[] = L"TEST"; 515 + static const wchar_t str2[] = L"test"; 516 + int ret; 517 + 518 + errno = 0xdeadbeef; 519 + ret = wcsnicmp(str1, str2, -1); 520 + ok(!ret, "got %d.\n", ret); 521 + 522 + ret = wcsnicmp(str1, str2, 0x7fffffff); 523 + ok(!ret, "got %d.\n", ret); 524 + } 525 + 526 + static void test_SpecialCasing(void) 527 + { 528 + int i; 529 + wint_t ret, exp; 530 + _locale_t locale; 531 + struct test { 532 + const char *lang; 533 + wint_t ch; 534 + wint_t exp; 535 + }; 536 + 537 + struct test ucases[] = { 538 + {"English", 'I', 'i'}, /* LATIN CAPITAL LETTER I */ 539 + {"English", 0x0130}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ 540 + 541 + {"Turkish", 'I', 'i'}, /* LATIN CAPITAL LETTER I */ 542 + {"Turkish", 0x0130}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ 543 + }; 544 + struct test lcases[] = { 545 + {"English", 'i', 'I'}, /* LATIN SMALL LETTER I */ 546 + {"English", 0x0131}, /* LATIN SMALL LETTER DOTLESS I */ 547 + 548 + {"Turkish", 'i', 'I'}, /* LATIN SMALL LETTER I */ 549 + {"Turkish", 0x0131}, /* LATIN SMALL LETTER DOTLESS I */ 550 + }; 551 + 552 + for (i = 0; i < ARRAY_SIZE(ucases); i++) { 553 + if (!setlocale(LC_ALL, ucases[i].lang)) { 554 + win_skip("skipping special case tests for %s\n", ucases[i].lang); 555 + continue; 556 + } 557 + 558 + ret = towlower(ucases[i].ch); 559 + exp = ucases[i].exp ? ucases[i].exp : ucases[i].ch; 560 + ok(ret == exp, "expected lowercase %x, got %x for locale %s\n", exp, ret, ucases[i].lang); 561 + } 562 + 563 + for (i = 0; i < ARRAY_SIZE(lcases); i++) { 564 + if (!setlocale(LC_ALL, lcases[i].lang)) { 565 + win_skip("skipping special case tests for %s\n", lcases[i].lang); 566 + continue; 567 + } 568 + 569 + ret = towupper(lcases[i].ch); 570 + exp = lcases[i].exp ? lcases[i].exp : lcases[i].ch; 571 + ok(ret == exp, "expected uppercase %x, got %x for locale %s\n", exp, ret, lcases[i].lang); 572 + } 573 + 574 + setlocale(LC_ALL, "C"); 575 + 576 + /* test _towlower_l creating locale */ 577 + for (i = 0; i < ARRAY_SIZE(ucases); i++) { 578 + if (!(locale = _create_locale(LC_ALL, ucases[i].lang))) { 579 + win_skip("locale %s not available. skipping\n", ucases[i].lang); 580 + continue; 581 + } 582 + 583 + ret = _towlower_l(ucases[i].ch, locale); 584 + exp = ucases[i].exp ? ucases[i].exp : ucases[i].ch; 585 + ok(ret == exp, "expected lowercase %x, got %x for locale %s\n", exp, ret, ucases[i].lang); 586 + 587 + _free_locale(locale); 588 + } 589 + 590 + /* test _towupper_l creating locale */ 591 + for (i = 0; i < ARRAY_SIZE(lcases); i++) { 592 + if (!(locale = _create_locale(LC_ALL, lcases[i].lang))) { 593 + win_skip("locale %s not available. skipping\n", lcases[i].lang); 594 + continue; 595 + } 596 + 597 + ret = _towupper_l(lcases[i].ch, locale); 598 + exp = lcases[i].exp ? lcases[i].exp : lcases[i].ch; 599 + ok(ret == exp, "expected uppercase %x, got %x for locale %s\n", exp, ret, lcases[i].lang); 600 + 601 + _free_locale(locale); 602 + } 603 + } 604 + 605 + static void test__mbbtype_l(void) 606 + { 607 + int expected, ret; 608 + unsigned int c; 609 + 610 + _setmbcp(_MB_CP_LOCALE); 611 + for (c = 0; c < 256; ++c) 612 + { 613 + expected = _mbbtype(c, 0); 614 + ret = _mbbtype_l(c, 0, NULL); 615 + ok(ret == expected, "c %#x, got ret %#x, expected %#x.\n", c, ret, expected); 616 + 617 + expected = _mbbtype(c, 1); 618 + ret = _mbbtype_l(c, 1, NULL); 619 + ok(ret == expected, "c %#x, got ret %#x, expected %#x.\n", c, ret, expected); 620 + } 621 + } 622 + 623 + static void test_strcmp(void) 624 + { 625 + int ret = strcmp( "abc", "abcd" ); 626 + ok( ret == -1, "wrong ret %d\n", ret ); 627 + ret = strcmp( "", "abc" ); 628 + ok( ret == -1, "wrong ret %d\n", ret ); 629 + ret = strcmp( "abc", "ab\xa0" ); 630 + ok( ret == -1, "wrong ret %d\n", ret ); 631 + ret = strcmp( "ab\xb0", "ab\xa0" ); 632 + ok( ret == 1, "wrong ret %d\n", ret ); 633 + ret = strcmp( "ab\xc2", "ab\xc2" ); 634 + ok( ret == 0, "wrong ret %d\n", ret ); 635 + 636 + ret = strncmp( "abc", "abcd", 3 ); 637 + ok( ret == 0, "wrong ret %d\n", ret ); 638 + ret = strncmp( "", "abc", 3 ); 639 + ok( ret == -1, "wrong ret %d\n", ret ); 640 + ret = strncmp( "abc", "ab\xa0", 4 ); 641 + ok( ret == -1, "wrong ret %d\n", ret ); 642 + ret = strncmp( "ab\xb0", "ab\xa0", 3 ); 643 + ok( ret == 1, "wrong ret %d\n", ret ); 644 + ret = strncmp( "ab\xb0", "ab\xa0", 2 ); 645 + ok( ret == 0, "wrong ret %d\n", ret ); 646 + ret = strncmp( "ab\xc2", "ab\xc2", 3 ); 647 + ok( ret == 0, "wrong ret %d\n", ret ); 648 + ret = strncmp( "abc", "abd", 0 ); 649 + ok( ret == 0, "wrong ret %d\n", ret ); 650 + ret = strncmp( "abc", "abc", 12 ); 651 + ok( ret == 0, "wrong ret %d\n", ret ); 652 + } 653 + 654 + #define expect_bin(buf, value, len) { ok(memcmp((buf), value, len) == 0, \ 655 + "Binary buffer mismatch - expected %s, got %s\n", \ 656 + debugstr_an(value, len), debugstr_an((char *)(buf), len)); } 657 + 658 + static void test__mbsncpy_s(void) 659 + { 660 + unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5\x0"; 661 + unsigned char *mbstring2 = (unsigned char *)"\xb0\x0"; 662 + unsigned char buf[16]; 663 + errno_t err; 664 + int oldcp; 665 + 666 + oldcp = _getmbcp(); 667 + if (_setmbcp(936)) 668 + { 669 + skip("Code page 936 is not available, skipping test.\n"); 670 + return; 671 + } 672 + 673 + errno = 0xdeadbeef; 674 + memset(buf, 0xcc, sizeof(buf)); 675 + err = _mbsncpy_s(NULL, 0, mbstring, 0); 676 + ok(errno == 0xdeadbeef, "got %d\n", errno); 677 + ok(!err, "got %d.\n", err); 678 + 679 + errno = 0xdeadbeef; 680 + memset(buf, 0xcc, sizeof(buf)); 681 + err = _mbsncpy_s(buf, 6, mbstring, 1); 682 + ok(errno == 0xdeadbeef, "got %d\n", errno); 683 + ok(!err, "got %d.\n", err); 684 + expect_bin(buf, "\xb0\xb1\0\xcc", 4); 685 + 686 + memset(buf, 0xcc, sizeof(buf)); 687 + errno = 0xdeadbeef; 688 + err = _mbsncpy_s(buf, 6, mbstring, 2); 689 + ok(errno == 0xdeadbeef, "got %d\n", errno); 690 + ok(!err, "got %d.\n", err); 691 + expect_bin(buf, "\xb0\xb1\xb2\xb3\0\xcc", 6); 692 + 693 + errno = 0xdeadbeef; 694 + memset(buf, 0xcc, sizeof(buf)); 695 + err = _mbsncpy_s(buf, 2, mbstring, _TRUNCATE); 696 + ok(errno == 0xdeadbeef, "got %d\n", errno); 697 + ok(err == STRUNCATE, "got %d.\n", err); 698 + expect_bin(buf, "\x00\xb1\xcc", 3); 699 + 700 + memset(buf, 0xcc, sizeof(buf)); 701 + SET_EXPECT(invalid_parameter_handler); 702 + errno = 0xdeadbeef; 703 + err = _mbsncpy_s(buf, 2, mbstring, 1); 704 + ok(errno == err, "got %d.\n", errno); 705 + CHECK_CALLED(invalid_parameter_handler); 706 + ok(err == ERANGE, "got %d.\n", err); 707 + expect_bin(buf, "\x0\xcc\xcc", 3); 708 + 709 + memset(buf, 0xcc, sizeof(buf)); 710 + SET_EXPECT(invalid_parameter_handler); 711 + errno = 0xdeadbeef; 712 + err = _mbsncpy_s(buf, 2, mbstring, 3); 713 + ok(errno == err, "got %d\n", errno); 714 + CHECK_CALLED(invalid_parameter_handler); 715 + ok(err == ERANGE, "got %d.\n", err); 716 + expect_bin(buf, "\x0\xcc\xcc", 3); 717 + 718 + memset(buf, 0xcc, sizeof(buf)); 719 + SET_EXPECT(invalid_parameter_handler); 720 + errno = 0xdeadbeef; 721 + err = _mbsncpy_s(buf, 1, mbstring, 3); 722 + ok(errno == err, "got %d\n", errno); 723 + CHECK_CALLED(invalid_parameter_handler); 724 + ok(err == ERANGE, "got %d.\n", err); 725 + expect_bin(buf, "\x0\xcc", 2); 726 + 727 + memset(buf, 0xcc, sizeof(buf)); 728 + SET_EXPECT(invalid_parameter_handler); 729 + errno = 0xdeadbeef; 730 + err = _mbsncpy_s(buf, 0, mbstring, 3); 731 + ok(errno == err, "got %d\n", errno); 732 + CHECK_CALLED(invalid_parameter_handler); 733 + ok(err == EINVAL, "got %d.\n", err); 734 + expect_bin(buf, "\xcc", 1); 735 + 736 + memset(buf, 0xcc, sizeof(buf)); 737 + SET_EXPECT(invalid_parameter_handler); 738 + errno = 0xdeadbeef; 739 + err = _mbsncpy_s(buf, 0, mbstring, 0); 740 + ok(errno == err, "got %d\n", errno); 741 + CHECK_CALLED(invalid_parameter_handler); 742 + ok(err == EINVAL, "got %d.\n", err); 743 + expect_bin(buf, "\xcc", 1); 744 + 745 + memset(buf, 0xcc, sizeof(buf)); 746 + errno = 0xdeadbeef; 747 + err = _mbsncpy_s(buf, -1, mbstring, 0); 748 + ok(errno == 0xdeadbeef, "got %d\n", errno); 749 + ok(!err, "got %d.\n", err); 750 + expect_bin(buf, "\x0\xcc", 2); 751 + 752 + memset(buf, 0xcc, sizeof(buf)); 753 + errno = 0xdeadbeef; 754 + err = _mbsncpy_s(buf, -1, mbstring, 256); 755 + ok(errno == 0xdeadbeef, "got %d\n", errno); 756 + ok(!err, "got %d.\n", err); 757 + expect_bin(buf, "\xb0\xb1\xb2\xb3Q\xb4\xb5\x0\xcc", 9); 758 + 759 + memset(buf, 0xcc, sizeof(buf)); 760 + errno = 0xdeadbeef; 761 + err = _mbsncpy_s(buf, 1, mbstring2, 4); 762 + ok(errno == err, "got %d\n", errno); 763 + ok(err == EILSEQ, "got %d.\n", err); 764 + expect_bin(buf, "\x0\xcc", 2); 765 + 766 + memset(buf, 0xcc, sizeof(buf)); 767 + errno = 0xdeadbeef; 768 + err = _mbsncpy_s(buf, 2, mbstring2, 4); 769 + ok(errno == err, "got %d\n", errno); 770 + ok(err == EILSEQ, "got %d.\n", err); 771 + expect_bin(buf, "\x0\xcc", 2); 772 + 773 + memset(buf, 0xcc, sizeof(buf)); 774 + errno = 0xdeadbeef; 775 + err = _mbsncpy_s(buf, 1, mbstring2, _TRUNCATE); 776 + ok(errno == 0xdeadbeef, "got %d\n", errno); 777 + ok(err == STRUNCATE, "got %d.\n", err); 778 + expect_bin(buf, "\x0\xcc", 2); 779 + 780 + memset(buf, 0xcc, sizeof(buf)); 781 + errno = 0xdeadbeef; 782 + err = _mbsncpy_s(buf, 2, mbstring2, _TRUNCATE); 783 + ok(errno == 0xdeadbeef, "got %d\n", errno); 784 + ok(!err, "got %d.\n", err); 785 + expect_bin(buf, "\xb0\x0\xcc", 3); 786 + 787 + memset(buf, 0xcc, sizeof(buf)); 788 + errno = 0xdeadbeef; 789 + err = _mbsncpy_s(buf, 1, mbstring2, 1); 790 + ok(errno == err, "got %d\n", errno); 791 + ok(err == EILSEQ, "got %d.\n", err); 792 + expect_bin(buf, "\x0\xcc", 2); 793 + 794 + memset(buf, 0xcc, sizeof(buf)); 795 + errno = 0xdeadbeef; 796 + err = _mbsncpy_s(buf, 2, mbstring2, 1); 797 + ok(errno == err, "got %d\n", errno); 798 + ok(err == EILSEQ, "got %d.\n", err); 799 + expect_bin(buf, "\x0\xcc", 2); 800 + 801 + memset(buf, 0xcc, sizeof(buf)); 802 + errno = 0xdeadbeef; 803 + err = _mbsncpy_s(buf, 3, mbstring2, 1); 804 + ok(errno == err, "got %d\n", errno); 805 + ok(err == EILSEQ, "got %d.\n", err); 806 + expect_bin(buf, "\x0\xcc", 2); 807 + 808 + memset(buf, 0xcc, sizeof(buf)); 809 + errno = 0xdeadbeef; 810 + err = _mbsncpy_s(buf, 3, mbstring2, 2); 811 + ok(errno == err, "got %d\n", errno); 812 + ok(err == EILSEQ, "got %d.\n", err); 813 + expect_bin(buf, "\x0\xcc", 2); 814 + 815 + _setmbcp(oldcp); 816 + } 817 + 818 + static void test_mbstowcs(void) 819 + { 820 + static const char mbs[] = { 0xc3, 0xa9, 0 }; 821 + WCHAR wcs[2]; 822 + size_t ret; 823 + 824 + if (!setlocale(LC_ALL, "en_US.UTF-8")) 825 + { 826 + win_skip("skipping UTF8 mbstowcs tests\n"); 827 + return; 828 + } 829 + 830 + ret = mbstowcs(NULL, mbs, 0); 831 + ok(ret == 1, "mbstowcs returned %Id\n", ret); 832 + memset(wcs, 0xfe, sizeof(wcs)); 833 + ret = mbstowcs(wcs, mbs, 1); 834 + ok(ret == 1, "mbstowcs returned %Id\n", ret); 835 + ok(wcs[0] == 0xe9, "wcsstring[0] = %x\n", wcs[0]); 836 + ok(wcs[1] == 0xfefe, "wcsstring[1] = %x\n", wcs[1]); 837 + setlocale(LC_ALL, "C"); 838 + } 839 + 840 + START_TEST(string) 841 + { 842 + ok(_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL, 843 + "Invalid parameter handler was already set\n"); 844 + 845 + test_strtod(); 846 + test_strtof(); 847 + test__memicmp(); 848 + test__memicmp_l(); 849 + test___strncnt(); 850 + test_C_locale(); 851 + test_mbsspn(); 852 + test_wcstok(); 853 + test__strnicmp(); 854 + test_wcsnicmp(); 855 + test_SpecialCasing(); 856 + test__mbbtype_l(); 857 + test_strcmp(); 858 + test__mbsncpy_s(); 859 + test_mbstowcs(); 860 + }
+184
modules/rostests/winetests/ucrtbase/thread.c
··· 1 + /* 2 + * Copyright 2021 Arkadiusz Hiler for CodeWeavers 3 + * 4 + * This library is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU Lesser General Public 6 + * License as published by the Free Software Foundation; either 7 + * version 2.1 of the License, or (at your option) any later version. 8 + * 9 + * This library is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * Lesser General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU Lesser General Public 15 + * License along with this library; if not, write to the Free Software 16 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 + */ 18 + 19 + #include <errno.h> 20 + #include <stdarg.h> 21 + #include <process.h> 22 + 23 + #include <windef.h> 24 + #include <winbase.h> 25 + #include "wine/test.h" 26 + 27 + #include "threaddll.h" 28 + 29 + enum beginthread_method 30 + { 31 + use_beginthread, 32 + use_beginthreadex 33 + }; 34 + 35 + static char *get_thread_dll_path(void) 36 + { 37 + static char path[MAX_PATH]; 38 + const char dll_name[] = "threaddll.dll"; 39 + DWORD written; 40 + HANDLE file; 41 + HRSRC res; 42 + void *ptr; 43 + 44 + GetTempPathA(ARRAY_SIZE(path), path); 45 + strcat(path, dll_name); 46 + 47 + file = CreateFileA(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 48 + ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s: %lu.\n", 49 + debugstr_a(path), GetLastError()); 50 + 51 + res = FindResourceA(NULL, dll_name, "TESTDLL"); 52 + ok(!!res, "Failed to load resource: %lu\n", GetLastError()); 53 + ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res)); 54 + WriteFile(file, ptr, SizeofResource( GetModuleHandleA(NULL), res), &written, NULL); 55 + ok(written == SizeofResource(GetModuleHandleA(NULL), res), "Failed to write resource\n"); 56 + CloseHandle(file); 57 + 58 + return path; 59 + } 60 + 61 + static void set_thead_dll_detach_event(HANDLE dll, HANDLE event) 62 + { 63 + void (WINAPI *_set_detach_event)(HANDLE event); 64 + _set_detach_event = (void*) GetProcAddress(dll, "set_detach_event"); 65 + ok(_set_detach_event != NULL, "Failed to get set_detach_event: %lu\n", GetLastError()); 66 + _set_detach_event(event); 67 + } 68 + 69 + static void test_thread_library_reference(char *thread_dll, 70 + enum beginthread_method beginthread_method, 71 + enum thread_exit_method exit_method) 72 + { 73 + HANDLE detach_event; 74 + HMODULE dll; 75 + DWORD ret; 76 + uintptr_t thread_handle; 77 + struct threaddll_args args; 78 + 79 + args.exit_method = exit_method; 80 + 81 + detach_event = CreateEventA(NULL, FALSE, FALSE, NULL); 82 + ok(detach_event != NULL, "Failed to create an event: %lu\n", GetLastError()); 83 + args.confirm_running = CreateEventA(NULL, FALSE, FALSE, NULL); 84 + ok(args.confirm_running != NULL, "Failed to create an event: %lu\n", GetLastError()); 85 + args.past_free = CreateEventA(NULL, FALSE, FALSE, NULL); 86 + ok(args.past_free != NULL, "Failed to create an event: %lu\n", GetLastError()); 87 + 88 + dll = LoadLibraryA(thread_dll); 89 + ok(dll != NULL, "Failed to load the test dll: %lu\n", GetLastError()); 90 + 91 + set_thead_dll_detach_event(dll, detach_event); 92 + 93 + if (beginthread_method == use_beginthreadex) 94 + { 95 + _beginthreadex_start_routine_t proc = (void*) GetProcAddress(dll, "stdcall_thread_proc"); 96 + ok(proc != NULL, "Failed to get stdcall_thread_proc: %lu\n", GetLastError()); 97 + thread_handle = _beginthreadex(NULL, 0, proc, &args, 0, NULL); 98 + } 99 + else 100 + { 101 + _beginthread_start_routine_t proc = (void*) GetProcAddress(dll, "cdecl_thread_proc"); 102 + ok(proc != NULL, "Failed to get stdcall_thread_proc: %lu\n", GetLastError()); 103 + thread_handle = _beginthread(proc, 0, &args); 104 + } 105 + 106 + ok(thread_handle != -1 && thread_handle != 0, "Failed to begin thread: %u\n", errno); 107 + 108 + ret = FreeLibrary(dll); 109 + ok(ret, "Failed to free the library: %lu\n", GetLastError()); 110 + 111 + ret = WaitForSingleObject(args.confirm_running, 200); 112 + ok(ret == WAIT_OBJECT_0, "Event was not signaled, ret: %lu, err: %lu\n", ret, GetLastError()); 113 + 114 + ret = WaitForSingleObject(detach_event, 0); 115 + ok(ret == WAIT_TIMEOUT, "Thread detach happened unexpectedly signaling an event, ret: %ld, err: %lu\n", ret, GetLastError()); 116 + 117 + ret = SetEvent(args.past_free); 118 + ok(ret, "Failed to signal event: %ld\n", GetLastError()); 119 + 120 + if (beginthread_method == use_beginthreadex) 121 + { 122 + ret = WaitForSingleObject((HANDLE)thread_handle, 200); 123 + ok(ret == WAIT_OBJECT_0, "Thread has not exited, ret: %ld, err: %lu\n", ret, GetLastError()); 124 + } 125 + 126 + ret = WaitForSingleObject(detach_event, 200); 127 + ok(ret == WAIT_OBJECT_0, "Detach event was not signaled, ret: %ld, err: %lu\n", ret, GetLastError()); 128 + 129 + if (beginthread_method == use_beginthreadex) 130 + CloseHandle((HANDLE)thread_handle); 131 + 132 + CloseHandle(args.past_free); 133 + CloseHandle(args.confirm_running); 134 + CloseHandle(detach_event); 135 + } 136 + 137 + static BOOL handler_called; 138 + 139 + void CDECL test_invalid_parameter_handler(const wchar_t *expression, 140 + const wchar_t *function_name, 141 + const wchar_t *file_name, 142 + unsigned line_number, 143 + uintptr_t reserved) 144 + { 145 + handler_called = TRUE; 146 + } 147 + 148 + static void test_thread_invalid_params(void) 149 + { 150 + uintptr_t hThread; 151 + _invalid_parameter_handler old = _set_invalid_parameter_handler(test_invalid_parameter_handler); 152 + 153 + errno = 0; 154 + handler_called = FALSE; 155 + hThread = _beginthreadex(NULL, 0, NULL, NULL, 0, NULL); 156 + ok(hThread == 0, "_beginthreadex unexpected ret: %Iu\n", hThread); 157 + ok(errno == EINVAL, "_beginthreadex unexpected errno: %d\n", errno); 158 + ok(handler_called, "Expected invalid_parameter_handler to be called\n"); 159 + 160 + errno = 0; 161 + handler_called = FALSE; 162 + hThread = _beginthread(NULL, 0, NULL); 163 + ok(hThread == -1, "_beginthread unexpected ret: %Iu\n", hThread); 164 + ok(errno == EINVAL, "_beginthread unexpected errno: %d\n", errno); 165 + ok(handler_called, "Expected invalid_parameter_handler to be called\n"); 166 + 167 + _set_invalid_parameter_handler(old); 168 + } 169 + 170 + START_TEST(thread) 171 + { 172 + BOOL ret; 173 + char *thread_dll = get_thread_dll_path(); 174 + 175 + test_thread_library_reference(thread_dll, use_beginthread, thread_exit_return); 176 + test_thread_library_reference(thread_dll, use_beginthread, thread_exit_endthread); 177 + test_thread_library_reference(thread_dll, use_beginthreadex, thread_exit_return); 178 + test_thread_library_reference(thread_dll, use_beginthreadex, thread_exit_endthreadex); 179 + 180 + ret = DeleteFileA(thread_dll); 181 + ok(ret, "Failed to remove the test dll, err: %lu\n", GetLastError()); 182 + 183 + test_thread_invalid_params(); 184 + }
+71
modules/rostests/winetests/ucrtbase/threaddll.c
··· 1 + /* 2 + * Copyright 2021 Arkadiusz Hiler for CodeWeavers 3 + * 4 + * This library is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU Lesser General Public 6 + * License as published by the Free Software Foundation; either 7 + * version 2.1 of the License, or (at your option) any later version. 8 + * 9 + * This library is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * Lesser General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU Lesser General Public 15 + * License along with this library; if not, write to the Free Software 16 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 + */ 18 + 19 + #if 0 20 + #pragma makedep testdll 21 + #endif 22 + 23 + #include <windows.h> 24 + 25 + #include "threaddll.h" 26 + 27 + static HANDLE detach_event; 28 + 29 + void CDECL _endthread(void); 30 + void CDECL _endthreadex(unsigned int); 31 + 32 + void WINAPI set_detach_event(HANDLE event) 33 + { 34 + detach_event = event; 35 + } 36 + 37 + static unsigned internal_thread_proc(void *param) 38 + { 39 + struct threaddll_args *args = param; 40 + SetEvent(args->confirm_running); 41 + WaitForSingleObject(args->past_free, INFINITE); 42 + 43 + if (args->exit_method == thread_exit_endthread) 44 + _endthread(); 45 + else if (args->exit_method == thread_exit_endthreadex) 46 + _endthreadex(0); 47 + 48 + return 0; 49 + } 50 + 51 + unsigned WINAPI stdcall_thread_proc(void *param) 52 + { 53 + return internal_thread_proc(param); 54 + } 55 + 56 + void CDECL cdecl_thread_proc(void *param) 57 + { 58 + internal_thread_proc(param); 59 + } 60 + 61 + BOOL WINAPI DllMain(HINSTANCE instance_new, DWORD reason, LPVOID reserved) 62 + { 63 + switch (reason) 64 + { 65 + case DLL_PROCESS_DETACH: 66 + if (detach_event) SetEvent(detach_event); 67 + break; 68 + } 69 + 70 + return TRUE; 71 + }
+30
modules/rostests/winetests/ucrtbase/threaddll.h
··· 1 + /* 2 + * Copyright 2021 Arkadiusz Hiler for CodeWeavers 3 + * 4 + * This library is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU Lesser General Public 6 + * License as published by the Free Software Foundation; either 7 + * version 2.1 of the License, or (at your option) any later version. 8 + * 9 + * This library is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * Lesser General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU Lesser General Public 15 + * License along with this library; if not, write to the Free Software 16 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 + */ 18 + 19 + enum thread_exit_method { 20 + thread_exit_return, 21 + thread_exit_endthread, 22 + thread_exit_endthreadex 23 + }; 24 + 25 + struct threaddll_args 26 + { 27 + HANDLE confirm_running; 28 + HANDLE past_free; 29 + enum thread_exit_method exit_method; 30 + };
+3
modules/rostests/winetests/ucrtbase/threaddll.spec
··· 1 + @ stdcall set_detach_event(ptr) 2 + @ stdcall stdcall_thread_proc(ptr) 3 + @ cdecl cdecl_thread_proc(ptr)