msvcp120/tests: Test _Xtime_diff_to_millis2 overflow behavior.
[wine.git] / dlls / msvcp120 / tests / msvcp120.c
blobc0d6f186b94aef2f63ae2e4299c9bbedcb6e5f63
1 /*
2 * Copyright 2014 Yifu Wang for ESRI
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.
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.
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
19 #include <locale.h>
20 #include <stdio.h>
21 #include <math.h>
22 #include <limits.h>
24 #include "wine/test.h"
25 #include "winbase.h"
27 #undef __thiscall
28 #ifdef __i386__
29 #define __thiscall __stdcall
30 #else
31 #define __thiscall __cdecl
32 #endif
34 /* Emulate a __thiscall */
35 #ifdef __i386__
37 #include "pshpack1.h"
38 struct thiscall_thunk
40 BYTE pop_eax; /* popl %eax (ret addr) */
41 BYTE pop_edx; /* popl %edx (func) */
42 BYTE pop_ecx; /* popl %ecx (this) */
43 BYTE push_eax; /* pushl %eax */
44 WORD jmp_edx; /* jmp *%edx */
46 #include "poppack.h"
48 static void * (WINAPI *call_thiscall_func1)( void *func, void *this );
49 static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
51 static void init_thiscall_thunk(void)
53 struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
54 MEM_COMMIT, PAGE_EXECUTE_READWRITE );
55 thunk->pop_eax = 0x58; /* popl %eax */
56 thunk->pop_edx = 0x5a; /* popl %edx */
57 thunk->pop_ecx = 0x59; /* popl %ecx */
58 thunk->push_eax = 0x50; /* pushl %eax */
59 thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
60 call_thiscall_func1 = (void *)thunk;
61 call_thiscall_func2 = (void *)thunk;
64 #define call_func1(func,_this) call_thiscall_func1(func,_this)
65 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
67 #else
69 #define init_thiscall_thunk()
70 #define call_func1(func,_this) func(_this)
71 #define call_func2(func,_this,a) func(_this,a)
73 #endif /* __i386__ */
75 static inline float __port_infinity(void)
77 static const unsigned __inf_bytes = 0x7f800000;
78 return *(const float *)&__inf_bytes;
80 #define INFINITY __port_infinity()
82 static inline float __port_nan(void)
84 static const unsigned __nan_bytes = 0x7fc00000;
85 return *(const float *)&__nan_bytes;
87 #define NAN __port_nan()
89 typedef int MSVCRT_long;
90 typedef unsigned char MSVCP_bool;
92 /* xtime */
93 typedef struct {
94 __time64_t sec;
95 MSVCRT_long nsec;
96 } xtime;
98 typedef struct {
99 unsigned page;
100 int mb_max;
101 int unk;
102 BYTE isleadbyte[32];
103 } _Cvtvec;
105 struct space_info {
106 ULONGLONG capacity;
107 ULONGLONG free;
108 ULONGLONG available;
111 enum file_type {
112 status_unknown, file_not_found, regular_file, directory_file,
113 symlink_file, block_file, character_file, fifo_file, socket_file,
114 type_unknown
117 static BOOL compare_float(float f, float g, unsigned int ulps)
119 int x = *(int *)&f;
120 int y = *(int *)&g;
122 if (x < 0)
123 x = INT_MIN - x;
124 if (y < 0)
125 y = INT_MIN - y;
127 if (abs(x - y) > ulps)
128 return FALSE;
130 return TRUE;
133 static char* (__cdecl *p_setlocale)(int, const char*);
134 static int (__cdecl *p__setmbcp)(int);
135 static int (__cdecl *p_isleadbyte)(int);
137 static MSVCRT_long (__cdecl *p__Xtime_diff_to_millis2)(const xtime*, const xtime*);
138 static int (__cdecl *p_xtime_get)(xtime*, int);
139 static _Cvtvec* (__cdecl *p__Getcvt)(_Cvtvec*);
140 static void (CDECL *p__Call_once)(int *once, void (CDECL *func)(void));
141 static void (CDECL *p__Call_onceEx)(int *once, void (CDECL *func)(void*), void *argv);
142 static void (CDECL *p__Do_call)(void *this);
143 static short (__cdecl *p__Dtest)(double *d);
144 static short (__cdecl *p__Dscale)(double *d, int exp);
145 static short (__cdecl *p__FExp)(float *x, float y, int exp);
147 /* filesystem */
148 static ULONGLONG(__cdecl *p_tr2_sys__File_size)(char const*);
149 static ULONGLONG(__cdecl *p_tr2_sys__File_size_wchar)(WCHAR const*);
150 static int (__cdecl *p_tr2_sys__Equivalent)(char const*, char const*);
151 static int (__cdecl *p_tr2_sys__Equivalent_wchar)(WCHAR const*, WCHAR const*);
152 static char* (__cdecl *p_tr2_sys__Current_get)(char *);
153 static WCHAR* (__cdecl *p_tr2_sys__Current_get_wchar)(WCHAR *);
154 static MSVCP_bool (__cdecl *p_tr2_sys__Current_set)(char const*);
155 static MSVCP_bool (__cdecl *p_tr2_sys__Current_set_wchar)(WCHAR const*);
156 static int (__cdecl *p_tr2_sys__Make_dir)(char const*);
157 static int (__cdecl *p_tr2_sys__Make_dir_wchar)(WCHAR const*);
158 static MSVCP_bool (__cdecl *p_tr2_sys__Remove_dir)(char const*);
159 static MSVCP_bool (__cdecl *p_tr2_sys__Remove_dir_wchar)(WCHAR const*);
160 static int (__cdecl *p_tr2_sys__Copy_file)(char const*, char const*, MSVCP_bool);
161 static int (__cdecl *p_tr2_sys__Copy_file_wchar)(WCHAR const*, WCHAR const*, MSVCP_bool);
162 static int (__cdecl *p_tr2_sys__Rename)(char const*, char const*);
163 static int (__cdecl *p_tr2_sys__Rename_wchar)(WCHAR const*, WCHAR const*);
164 static struct space_info* (__cdecl *p_tr2_sys__Statvfs)(struct space_info*, char const*);
165 static struct space_info* (__cdecl *p_tr2_sys__Statvfs_wchar)(struct space_info*, WCHAR const*);
166 static enum file_type (__cdecl *p_tr2_sys__Stat)(char const*, int *);
167 static enum file_type (__cdecl *p_tr2_sys__Stat_wchar)(WCHAR const*, int *);
168 static enum file_type (__cdecl *p_tr2_sys__Lstat)(char const*, int *);
169 static enum file_type (__cdecl *p_tr2_sys__Lstat_wchar)(WCHAR const*, int *);
170 static __int64 (__cdecl *p_tr2_sys__Last_write_time)(char const*);
171 static void (__cdecl *p_tr2_sys__Last_write_time_set)(char const*, __int64);
172 static void* (__cdecl *p_tr2_sys__Open_dir)(char*, char const*, int *, enum file_type*);
173 static char* (__cdecl *p_tr2_sys__Read_dir)(char*, void*, enum file_type*);
174 static void (__cdecl *p_tr2_sys__Close_dir)(void*);
175 static int (__cdecl *p_tr2_sys__Link)(char const*, char const*);
176 static int (__cdecl *p_tr2_sys__Symlink)(char const*, char const*);
177 static int (__cdecl *p_tr2_sys__Unlink)(char const*);
179 /* thrd */
180 typedef struct
182 HANDLE hnd;
183 DWORD id;
184 } _Thrd_t;
186 #define TIMEDELTA 250 /* 250 ms uncertainty allowed */
188 typedef int (__cdecl *_Thrd_start_t)(void*);
190 static int (__cdecl *p__Thrd_equal)(_Thrd_t, _Thrd_t);
191 static int (__cdecl *p__Thrd_lt)(_Thrd_t, _Thrd_t);
192 static void (__cdecl *p__Thrd_sleep)(const xtime*);
193 static _Thrd_t (__cdecl *p__Thrd_current)(void);
194 static int (__cdecl *p__Thrd_create)(_Thrd_t*, _Thrd_start_t, void*);
195 static int (__cdecl *p__Thrd_join)(_Thrd_t, int*);
196 static int (__cdecl *p__Thrd_detach)(_Thrd_t);
198 #ifdef __i386__
199 static ULONGLONG (__cdecl *p_i386_Thrd_current)(void);
200 static _Thrd_t __cdecl i386_Thrd_current(void)
202 union {
203 _Thrd_t thr;
204 ULONGLONG ull;
205 } r;
206 r.ull = p_i386_Thrd_current();
207 return r.thr;
209 #endif
211 /* mtx */
212 typedef struct cs_queue
214 struct cs_queue *next;
215 BOOL free;
216 int unknown;
217 } cs_queue;
219 typedef struct
221 ULONG_PTR unk_thread_id;
222 cs_queue unk_active;
223 void *unknown[2];
224 cs_queue *head;
225 void *tail;
226 } critical_section;
228 typedef struct
230 DWORD flags;
231 critical_section cs;
232 DWORD thread_id;
233 DWORD count;
234 } *_Mtx_t;
236 static int (__cdecl *p__Mtx_init)(_Mtx_t*, int);
237 static void (__cdecl *p__Mtx_destroy)(_Mtx_t*);
238 static int (__cdecl *p__Mtx_lock)(_Mtx_t*);
239 static int (__cdecl *p__Mtx_unlock)(_Mtx_t*);
241 /* cnd */
242 typedef void *_Cnd_t;
244 static int (__cdecl *p__Cnd_init)(_Cnd_t*);
245 static void (__cdecl *p__Cnd_destroy)(_Cnd_t*);
246 static int (__cdecl *p__Cnd_wait)(_Cnd_t*, _Mtx_t*);
247 static int (__cdecl *p__Cnd_timedwait)(_Cnd_t*, _Mtx_t*, const xtime*);
248 static int (__cdecl *p__Cnd_broadcast)(_Cnd_t*);
249 static int (__cdecl *p__Cnd_signal)(_Cnd_t*);
250 static void (__cdecl *p__Cnd_register_at_thread_exit)(_Cnd_t*, _Mtx_t*, int*);
251 static void (__cdecl *p__Cnd_unregister_at_thread_exit)(_Mtx_t*);
252 static void (__cdecl *p__Cnd_do_broadcast_at_thread_exit)(void);
254 /* _Pad */
255 typedef void (*vtable_ptr)(void);
257 typedef struct
259 const vtable_ptr *vtable;
260 _Cnd_t cnd;
261 _Mtx_t mtx;
262 MSVCP_bool launched;
263 } _Pad;
265 static _Pad* (__thiscall *p__Pad_ctor)(_Pad*);
266 static _Pad* (__thiscall *p__Pad_copy_ctor)(_Pad*, const _Pad*);
267 static void (__thiscall *p__Pad_dtor)(_Pad*);
268 static _Pad* (__thiscall *p__Pad_op_assign)(_Pad*, const _Pad*);
269 static void (__thiscall *p__Pad__Launch)(_Pad*, _Thrd_t*);
270 static void (__thiscall *p__Pad__Release)(_Pad*);
272 static void (__cdecl *p_threads__Mtx_new)(void **mtx);
273 static void (__cdecl *p_threads__Mtx_delete)(void *mtx);
274 static void (__cdecl *p_threads__Mtx_lock)(void *mtx);
275 static void (__cdecl *p_threads__Mtx_unlock)(void *mtx);
277 static BOOLEAN (WINAPI *pCreateSymbolicLinkA)(LPCSTR,LPCSTR,DWORD);
279 static size_t (__cdecl *p_vector_base_v4__Segment_index_of)(size_t);
281 static HMODULE msvcp;
282 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
283 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
284 static BOOL init(void)
286 HANDLE hdll;
288 msvcp = LoadLibraryA("msvcp120.dll");
289 if(!msvcp)
291 win_skip("msvcp120.dll not installed\n");
292 return FALSE;
295 SET(p__Xtime_diff_to_millis2,
296 "_Xtime_diff_to_millis2");
297 SET(p_xtime_get,
298 "xtime_get");
299 SET(p__Getcvt,
300 "_Getcvt");
301 SET(p__Call_once,
302 "_Call_once");
303 SET(p__Call_onceEx,
304 "_Call_onceEx");
305 SET(p__Do_call,
306 "_Do_call");
307 SET(p__Dtest,
308 "_Dtest");
309 SET(p__Dscale,
310 "_Dscale");
311 SET(p__FExp,
312 "_FExp");
313 if(sizeof(void*) == 8) { /* 64-bit initialization */
314 SET(p_tr2_sys__File_size,
315 "?_File_size@sys@tr2@std@@YA_KPEBD@Z");
316 SET(p_tr2_sys__File_size_wchar,
317 "?_File_size@sys@tr2@std@@YA_KPEB_W@Z");
318 SET(p_tr2_sys__Equivalent,
319 "?_Equivalent@sys@tr2@std@@YAHPEBD0@Z");
320 SET(p_tr2_sys__Equivalent_wchar,
321 "?_Equivalent@sys@tr2@std@@YAHPEB_W0@Z");
322 SET(p_tr2_sys__Current_get,
323 "?_Current_get@sys@tr2@std@@YAPEADAEAY0BAE@D@Z");
324 SET(p_tr2_sys__Current_get_wchar,
325 "?_Current_get@sys@tr2@std@@YAPEA_WAEAY0BAE@_W@Z");
326 SET(p_tr2_sys__Current_set,
327 "?_Current_set@sys@tr2@std@@YA_NPEBD@Z");
328 SET(p_tr2_sys__Current_set_wchar,
329 "?_Current_set@sys@tr2@std@@YA_NPEB_W@Z");
330 SET(p_tr2_sys__Make_dir,
331 "?_Make_dir@sys@tr2@std@@YAHPEBD@Z");
332 SET(p_tr2_sys__Make_dir_wchar,
333 "?_Make_dir@sys@tr2@std@@YAHPEB_W@Z");
334 SET(p_tr2_sys__Remove_dir,
335 "?_Remove_dir@sys@tr2@std@@YA_NPEBD@Z");
336 SET(p_tr2_sys__Remove_dir_wchar,
337 "?_Remove_dir@sys@tr2@std@@YA_NPEB_W@Z");
338 SET(p_tr2_sys__Copy_file,
339 "?_Copy_file@sys@tr2@std@@YAHPEBD0_N@Z");
340 SET(p_tr2_sys__Copy_file_wchar,
341 "?_Copy_file@sys@tr2@std@@YAHPEB_W0_N@Z");
342 SET(p_tr2_sys__Rename,
343 "?_Rename@sys@tr2@std@@YAHPEBD0@Z");
344 SET(p_tr2_sys__Rename_wchar,
345 "?_Rename@sys@tr2@std@@YAHPEB_W0@Z");
346 SET(p_tr2_sys__Statvfs,
347 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PEBD@Z");
348 SET(p_tr2_sys__Statvfs_wchar,
349 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PEB_W@Z");
350 SET(p_tr2_sys__Stat,
351 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PEBDAEAH@Z");
352 SET(p_tr2_sys__Stat_wchar,
353 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PEB_WAEAH@Z");
354 SET(p_tr2_sys__Lstat,
355 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PEBDAEAH@Z");
356 SET(p_tr2_sys__Lstat_wchar,
357 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PEB_WAEAH@Z");
358 SET(p_tr2_sys__Last_write_time,
359 "?_Last_write_time@sys@tr2@std@@YA_JPEBD@Z");
360 SET(p_tr2_sys__Last_write_time_set,
361 "?_Last_write_time@sys@tr2@std@@YAXPEBD_J@Z");
362 SET(p_tr2_sys__Open_dir,
363 "?_Open_dir@sys@tr2@std@@YAPEAXAEAY0BAE@DPEBDAEAHAEAW4file_type@123@@Z");
364 SET(p_tr2_sys__Read_dir,
365 "?_Read_dir@sys@tr2@std@@YAPEADAEAY0BAE@DPEAXAEAW4file_type@123@@Z");
366 SET(p_tr2_sys__Close_dir,
367 "?_Close_dir@sys@tr2@std@@YAXPEAX@Z");
368 SET(p_tr2_sys__Link,
369 "?_Link@sys@tr2@std@@YAHPEBD0@Z");
370 SET(p_tr2_sys__Symlink,
371 "?_Symlink@sys@tr2@std@@YAHPEBD0@Z");
372 SET(p_tr2_sys__Unlink,
373 "?_Unlink@sys@tr2@std@@YAHPEBD@Z");
374 SET(p__Thrd_current,
375 "_Thrd_current");
376 SET(p__Pad_ctor,
377 "??0_Pad@std@@QEAA@XZ");
378 SET(p__Pad_copy_ctor,
379 "??0_Pad@std@@QEAA@AEBV01@@Z");
380 SET(p__Pad_dtor,
381 "??1_Pad@std@@QEAA@XZ");
382 SET(p__Pad_op_assign,
383 "??4_Pad@std@@QEAAAEAV01@AEBV01@@Z");
384 SET(p__Pad__Launch,
385 "?_Launch@_Pad@std@@QEAAXPEAU_Thrd_imp_t@@@Z");
386 SET(p__Pad__Release,
387 "?_Release@_Pad@std@@QEAAXXZ");
388 SET(p_threads__Mtx_new,
389 "?_Mtx_new@threads@stdext@@YAXAEAPEAX@Z");
390 SET(p_threads__Mtx_delete,
391 "?_Mtx_delete@threads@stdext@@YAXPEAX@Z");
392 SET(p_threads__Mtx_lock,
393 "?_Mtx_lock@threads@stdext@@YAXPEAX@Z");
394 SET(p_threads__Mtx_unlock,
395 "?_Mtx_unlock@threads@stdext@@YAXPEAX@Z");
396 SET(p_vector_base_v4__Segment_index_of,
397 "?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KA_K_K@Z");
398 } else {
399 SET(p_tr2_sys__File_size,
400 "?_File_size@sys@tr2@std@@YA_KPBD@Z");
401 SET(p_tr2_sys__File_size_wchar,
402 "?_File_size@sys@tr2@std@@YA_KPB_W@Z");
403 SET(p_tr2_sys__Equivalent,
404 "?_Equivalent@sys@tr2@std@@YAHPBD0@Z");
405 SET(p_tr2_sys__Equivalent_wchar,
406 "?_Equivalent@sys@tr2@std@@YAHPB_W0@Z");
407 SET(p_tr2_sys__Current_get,
408 "?_Current_get@sys@tr2@std@@YAPADAAY0BAE@D@Z");
409 SET(p_tr2_sys__Current_get_wchar,
410 "?_Current_get@sys@tr2@std@@YAPA_WAAY0BAE@_W@Z");
411 SET(p_tr2_sys__Current_set,
412 "?_Current_set@sys@tr2@std@@YA_NPBD@Z");
413 SET(p_tr2_sys__Current_set_wchar,
414 "?_Current_set@sys@tr2@std@@YA_NPB_W@Z");
415 SET(p_tr2_sys__Make_dir,
416 "?_Make_dir@sys@tr2@std@@YAHPBD@Z");
417 SET(p_tr2_sys__Make_dir_wchar,
418 "?_Make_dir@sys@tr2@std@@YAHPB_W@Z");
419 SET(p_tr2_sys__Remove_dir,
420 "?_Remove_dir@sys@tr2@std@@YA_NPBD@Z");
421 SET(p_tr2_sys__Remove_dir_wchar,
422 "?_Remove_dir@sys@tr2@std@@YA_NPB_W@Z");
423 SET(p_tr2_sys__Copy_file,
424 "?_Copy_file@sys@tr2@std@@YAHPBD0_N@Z");
425 SET(p_tr2_sys__Copy_file_wchar,
426 "?_Copy_file@sys@tr2@std@@YAHPB_W0_N@Z");
427 SET(p_tr2_sys__Rename,
428 "?_Rename@sys@tr2@std@@YAHPBD0@Z");
429 SET(p_tr2_sys__Rename_wchar,
430 "?_Rename@sys@tr2@std@@YAHPB_W0@Z");
431 SET(p_tr2_sys__Statvfs,
432 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PBD@Z");
433 SET(p_tr2_sys__Statvfs_wchar,
434 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PB_W@Z");
435 SET(p_tr2_sys__Stat,
436 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PBDAAH@Z");
437 SET(p_tr2_sys__Stat_wchar,
438 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PB_WAAH@Z");
439 SET(p_tr2_sys__Lstat,
440 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PBDAAH@Z");
441 SET(p_tr2_sys__Lstat_wchar,
442 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PB_WAAH@Z");
443 SET(p_tr2_sys__Last_write_time,
444 "?_Last_write_time@sys@tr2@std@@YA_JPBD@Z");
445 SET(p_tr2_sys__Last_write_time_set,
446 "?_Last_write_time@sys@tr2@std@@YAXPBD_J@Z");
447 SET(p_tr2_sys__Open_dir,
448 "?_Open_dir@sys@tr2@std@@YAPAXAAY0BAE@DPBDAAHAAW4file_type@123@@Z");
449 SET(p_tr2_sys__Read_dir,
450 "?_Read_dir@sys@tr2@std@@YAPADAAY0BAE@DPAXAAW4file_type@123@@Z");
451 SET(p_tr2_sys__Close_dir,
452 "?_Close_dir@sys@tr2@std@@YAXPAX@Z");
453 SET(p_tr2_sys__Link,
454 "?_Link@sys@tr2@std@@YAHPBD0@Z");
455 SET(p_tr2_sys__Symlink,
456 "?_Symlink@sys@tr2@std@@YAHPBD0@Z");
457 SET(p_tr2_sys__Unlink,
458 "?_Unlink@sys@tr2@std@@YAHPBD@Z");
459 SET(p_threads__Mtx_new,
460 "?_Mtx_new@threads@stdext@@YAXAAPAX@Z");
461 SET(p_threads__Mtx_delete,
462 "?_Mtx_delete@threads@stdext@@YAXPAX@Z");
463 SET(p_threads__Mtx_lock,
464 "?_Mtx_lock@threads@stdext@@YAXPAX@Z");
465 SET(p_threads__Mtx_unlock,
466 "?_Mtx_unlock@threads@stdext@@YAXPAX@Z");
467 SET(p_vector_base_v4__Segment_index_of,
468 "?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KAII@Z");
469 #ifdef __i386__
470 SET(p_i386_Thrd_current,
471 "_Thrd_current");
472 p__Thrd_current = i386_Thrd_current;
473 SET(p__Pad_ctor,
474 "??0_Pad@std@@QAE@XZ");
475 SET(p__Pad_copy_ctor,
476 "??0_Pad@std@@QAE@ABV01@@Z");
477 SET(p__Pad_dtor,
478 "??1_Pad@std@@QAE@XZ");
479 SET(p__Pad_op_assign,
480 "??4_Pad@std@@QAEAAV01@ABV01@@Z");
481 SET(p__Pad__Launch,
482 "?_Launch@_Pad@std@@QAEXPAU_Thrd_imp_t@@@Z");
483 SET(p__Pad__Release,
484 "?_Release@_Pad@std@@QAEXXZ");
485 #else
486 SET(p__Thrd_current,
487 "_Thrd_current");
488 SET(p__Pad_ctor,
489 "??0_Pad@std@@QAA@XZ");
490 SET(p__Pad_copy_ctor,
491 "??0_Pad@std@@QAA@ABV01@@Z");
492 SET(p__Pad_dtor,
493 "??1_Pad@std@@QAA@XZ");
494 SET(p__Pad_op_assign,
495 "??4_Pad@std@@QAAAAV01@ABV01@@Z");
496 SET(p__Pad__Launch,
497 "?_Launch@_Pad@std@@QAAXPAU_Thrd_imp_t@@@Z");
498 SET(p__Pad__Release,
499 "?_Release@_Pad@std@@QAAXXZ");
500 #endif
502 SET(p__Thrd_equal,
503 "_Thrd_equal");
504 SET(p__Thrd_lt,
505 "_Thrd_lt");
506 SET(p__Thrd_sleep,
507 "_Thrd_sleep");
508 SET(p__Thrd_create,
509 "_Thrd_create");
510 SET(p__Thrd_join,
511 "_Thrd_join");
512 SET(p__Thrd_detach,
513 "_Thrd_detach");
515 SET(p__Mtx_init,
516 "_Mtx_init");
517 SET(p__Mtx_destroy,
518 "_Mtx_destroy");
519 SET(p__Mtx_lock,
520 "_Mtx_lock");
521 SET(p__Mtx_unlock,
522 "_Mtx_unlock");
524 SET(p__Cnd_init,
525 "_Cnd_init");
526 SET(p__Cnd_destroy,
527 "_Cnd_destroy");
528 SET(p__Cnd_wait,
529 "_Cnd_wait");
530 SET(p__Cnd_timedwait,
531 "_Cnd_timedwait");
532 SET(p__Cnd_broadcast,
533 "_Cnd_broadcast");
534 SET(p__Cnd_signal,
535 "_Cnd_signal");
536 SET(p__Cnd_register_at_thread_exit,
537 "_Cnd_register_at_thread_exit");
538 SET(p__Cnd_unregister_at_thread_exit,
539 "_Cnd_unregister_at_thread_exit");
540 SET(p__Cnd_do_broadcast_at_thread_exit,
541 "_Cnd_do_broadcast_at_thread_exit");
543 hdll = GetModuleHandleA("msvcr120.dll");
544 p_setlocale = (void*)GetProcAddress(hdll, "setlocale");
545 p__setmbcp = (void*)GetProcAddress(hdll, "_setmbcp");
546 p_isleadbyte = (void*)GetProcAddress(hdll, "isleadbyte");
548 hdll = GetModuleHandleA("kernel32.dll");
549 pCreateSymbolicLinkA = (void*)GetProcAddress(hdll, "CreateSymbolicLinkA");
551 init_thiscall_thunk();
552 return TRUE;
555 static void test__Xtime_diff_to_millis2(void)
557 struct {
558 __time64_t sec_before;
559 MSVCRT_long nsec_before;
560 __time64_t sec_after;
561 MSVCRT_long nsec_after;
562 MSVCRT_long expect;
563 } tests[] = {
564 {1, 0, 2, 0, 1000},
565 {0, 1000000000, 0, 2000000000, 1000},
566 {1, 100000000, 2, 100000000, 1000},
567 {1, 100000000, 1, 200000000, 100},
568 {0, 0, 0, 1000000000, 1000},
569 {0, 0, 0, 1200000000, 1200},
570 {0, 0, 0, 1230000000, 1230},
571 {0, 0, 0, 1234000000, 1234},
572 {0, 0, 0, 1234100000, 1235},
573 {0, 0, 0, 1234900000, 1235},
574 {0, 0, 0, 1234010000, 1235},
575 {0, 0, 0, 1234090000, 1235},
576 {0, 0, 0, 1234000001, 1235},
577 {0, 0, 0, 1234000009, 1235},
578 {0, 0, -1, 0, 0},
579 {1, 0, 0, 0, 0},
580 {0, 1000000000, 0, 0, 0},
581 {0x7FFFFFFF / 1000, 0, 0, 0, 0},
582 {2147484, 0, 0, 0, 0}, /* ceil(0x80000000 / 1000) */
583 {2147485, 0, 0, 0, 0}, /* ceil(0x80000000 / 1000) + 1*/
584 {0, 0, 0x7FFFFFFF / 1000, 0, 2147483000},
585 {0, 0, 0x7FFFFFFF / 1000, 647000000, 0x7FFFFFFF}, /* max */
586 {0, 0, 0x7FFFFFFF / 1000, 647000001, -2147483648}, /* overflow. */
587 {0, 0, 2147484, 0, -2147483296}, /* ceil(0x80000000 / 1000), overflow*/
588 {0, 0, 0, -10000000, 0},
589 {0, 0, -1, -100000000, 0},
590 {-1, 0, 0, 0, 1000},
591 {0, -100000000, 0, 0, 100},
592 {-1, -100000000, 0, 0, 1100},
593 {0, 0, -1, 2000000000, 1000},
594 {0, 0, -2, 2000000000, 0},
595 {0, 0, -2, 2100000000, 100},
596 {0, 0, _I64_MAX / 1000, 0, -808}, /* Still fits in a signed 64 bit number */
597 {0, 0, _I64_MAX / 1000, 1000000000, 192}, /* Overflows a signed 64 bit number */
598 {0, 0, (((ULONGLONG)0x80000000 << 32) | 0x1000) / 1000, 1000000000, 4192}, /* 64 bit overflow */
599 {_I64_MAX - 2, 0, _I64_MAX, 0, 2000}, /* Not an overflow */
600 {_I64_MAX, 0, _I64_MAX - 2, 0, 0}, /* Not an overflow */
602 /* October 11th 2017, 12:34:59 UTC */
603 {1507725144, 983274000, 0, 0, 0},
604 {0, 0, 1507725144, 983274000, 191624088},
605 {1507725144, 983274000, 1507725145, 983274000, 1000},
606 {1507725145, 983274000, 1507725145, 983274000, 0},
608 int i;
609 MSVCRT_long ret;
610 xtime t1, t2;
612 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); ++ i)
614 t1.sec = tests[i].sec_before;
615 t1.nsec = tests[i].nsec_before;
616 t2.sec = tests[i].sec_after;
617 t2.nsec = tests[i].nsec_after;
618 ret = p__Xtime_diff_to_millis2(&t2, &t1);
619 ok(ret == tests[i].expect,
620 "_Xtime_diff_to_millis2(): test: %d expect: %d, got: %d\n",
621 i, tests[i].expect, ret);
625 static void test_xtime_get(void)
627 static const MSVCRT_long tests[] = {1, 50, 100, 200, 500};
628 MSVCRT_long diff;
629 xtime before, after;
630 int i;
632 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i ++)
634 p_xtime_get(&before, 1);
635 Sleep(tests[i]);
636 p_xtime_get(&after, 1);
638 diff = p__Xtime_diff_to_millis2(&after, &before);
640 ok(diff >= tests[i],
641 "xtime_get() not functioning correctly, test: %d, expect: %d, got: %d\n",
642 i, tests[i], diff);
645 /* Test parameter and return value */
646 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
647 i = p_xtime_get(&before, 0);
648 ok(i == 0, "expect xtime_get() to return 0, got: %d\n", i);
649 ok(before.sec == 0xdeadbeef && before.nsec == 0xdeadbeef,
650 "xtime_get() shouldn't have modified the xtime struct with the given option\n");
652 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
653 i = p_xtime_get(&before, 1);
654 ok(i == 1, "expect xtime_get() to return 1, got: %d\n", i);
655 ok(before.sec != 0xdeadbeef && before.nsec != 0xdeadbeef,
656 "xtime_get() should have modified the xtime struct with the given option\n");
659 static void test__Getcvt(void)
661 _Cvtvec cvtvec;
662 int i;
664 p__Getcvt(&cvtvec);
665 ok(cvtvec.page == 0, "cvtvec.page = %d\n", cvtvec.page);
666 ok(cvtvec.mb_max == 1, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
667 todo_wine ok(cvtvec.unk == 1, "cvtvec.unk = %d\n", cvtvec.unk);
668 for(i=0; i<32; i++)
669 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
671 if(!p_setlocale(LC_ALL, ".936")) {
672 win_skip("_Getcvt tests\n");
673 return;
675 p__Getcvt(&cvtvec);
676 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
677 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
678 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
679 for(i=0; i<32; i++)
680 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
682 p__setmbcp(936);
683 p__Getcvt(&cvtvec);
684 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
685 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
686 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
687 for(i=0; i<32; i++) {
688 BYTE b = 0;
689 int j;
691 for(j=0; j<8; j++)
692 b |= (p_isleadbyte(i*8+j) ? 1 : 0) << j;
693 ok(cvtvec.isleadbyte[i] ==b, "cvtvec.isleadbyte[%d] = %x (%x)\n", i, cvtvec.isleadbyte[i], b);
697 static int cnt;
698 static int once;
700 static void __cdecl call_once_func(void)
702 ok(!once, "once != 0\n");
703 cnt += 0x10000;
706 static void __cdecl call_once_ex_func(void *arg)
708 int *i = arg;
710 ok(!once, "once != 0\n");
711 (*i)++;
714 static DWORD WINAPI call_once_thread(void *arg)
716 p__Call_once(&once, call_once_func);
717 return 0;
720 static DWORD WINAPI call_once_ex_thread(void *arg)
722 p__Call_onceEx(&once, call_once_ex_func, &cnt);
723 return 0;
726 static void test__Call_once(void)
728 HANDLE h[4];
729 int i;
731 for(i=0; i<4; i++)
732 h[i] = CreateThread(NULL, 0, call_once_thread, &once, 0, NULL);
733 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
734 "error waiting for all threads to finish\n");
735 ok(cnt == 0x10000, "cnt = %x\n", cnt);
736 ok(once == 1, "once = %x\n", once);
738 once = cnt = 0;
739 for(i=0; i<4; i++)
740 h[i] = CreateThread(NULL, 0, call_once_ex_thread, &once, 0, NULL);
741 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
742 "error waiting for all threads to finish\n");
743 ok(cnt == 1, "cnt = %x\n", cnt);
744 ok(once == 1, "once = %x\n", once);
747 static void **vtbl_func0;
748 #ifdef __i386__
749 /* TODO: this should be a __thiscall function */
750 static void __stdcall thiscall_func(void)
752 cnt = 1;
754 #else
755 static void __cdecl thiscall_func(void *this)
757 ok(this == &vtbl_func0, "incorrect this value\n");
758 cnt = 1;
760 #endif
762 static void test__Do_call(void)
764 void *pfunc = thiscall_func;
766 cnt = 0;
767 vtbl_func0 = &pfunc;
768 p__Do_call(&vtbl_func0);
769 ok(cnt == 1, "func was not called\n");
772 static void test__Dtest(void)
774 double d;
775 short ret;
777 d = 0;
778 ret = p__Dtest(&d);
779 ok(ret == FP_ZERO, "_Dtest(0) returned %x\n", ret);
781 d = 1;
782 ret = p__Dtest(&d);
783 ok(ret == FP_NORMAL, "_Dtest(1) returned %x\n", ret);
785 d = -1;
786 ret = p__Dtest(&d);
787 ok(ret == FP_NORMAL, "_Dtest(-1) returned %x\n", ret);
789 d = INFINITY;
790 ret = p__Dtest(&d);
791 ok(ret == FP_INFINITE, "_Dtest(INF) returned %x\n", ret);
793 d = NAN;
794 ret = p__Dtest(&d);
795 ok(ret == FP_NAN, "_Dtest(NAN) returned %x\n", ret);
798 static void test__Dscale(void)
800 double d;
801 short ret;
803 d = 0;
804 ret = p__Dscale(&d, 0);
805 ok(d == 0, "d = %f\n", d);
806 ok(ret == FP_ZERO, "ret = %x\n", ret);
808 d = 0;
809 ret = p__Dscale(&d, 1);
810 ok(d == 0, "d = %f\n", d);
811 ok(ret == FP_ZERO, "ret = %x\n", ret);
813 d = 0;
814 ret = p__Dscale(&d, -1);
815 ok(d == 0, "d = %f\n", d);
816 ok(ret == FP_ZERO, "ret = %x\n", ret);
818 d = 1;
819 ret = p__Dscale(&d, 0);
820 ok(d == 1, "d = %f\n", d);
821 ok(ret == FP_NORMAL, "ret = %x\n", ret);
823 d = 1;
824 ret = p__Dscale(&d, 1);
825 ok(d == 2, "d = %f\n", d);
826 ok(ret == FP_NORMAL, "ret = %x\n", ret);
828 d = 1;
829 ret = p__Dscale(&d, -1);
830 ok(d == 0.5, "d = %f\n", d);
831 ok(ret == FP_NORMAL, "ret = %x\n", ret);
833 d = 1;
834 ret = p__Dscale(&d, -99999);
835 ok(d == 0, "d = %f\n", d);
836 ok(ret == FP_ZERO, "ret = %x\n", ret);
838 d = 1;
839 ret = p__Dscale(&d, 999999);
840 ok(d == INFINITY, "d = %f\n", d);
841 ok(ret == FP_INFINITE, "ret = %x\n", ret);
843 d = NAN;
844 ret = p__Dscale(&d, 1);
845 ok(ret == FP_NAN, "ret = %x\n", ret);
848 static void test__FExp(void)
850 float d;
851 short ret;
853 d = 0;
854 ret = p__FExp(&d, 0, 0);
855 ok(d == 0, "d = %f\n", d);
856 ok(ret == FP_ZERO, "ret = %x\n", ret);
858 d = 0;
859 ret = p__FExp(&d, 1, 0);
860 ok(d == 1.0, "d = %f\n", d);
861 ok(ret == FP_NORMAL, "ret = %x\n", ret);
863 d = 0;
864 ret = p__FExp(&d, 1, 1);
865 ok(d == 2.0, "d = %f\n", d);
866 ok(ret == FP_NORMAL, "ret = %x\n", ret);
868 d = 0;
869 ret = p__FExp(&d, 1, 2);
870 ok(d == 4.0, "d = %f\n", d);
871 ok(ret == FP_NORMAL, "ret = %x\n", ret);
873 d = 0;
874 ret = p__FExp(&d, 10, 0);
875 ok(d == 10.0, "d = %f\n", d);
876 ok(ret == FP_NORMAL, "ret = %x\n", ret);
878 d = 1;
879 ret = p__FExp(&d, 0, 0);
880 ok(d == 0, "d = %f\n", d);
881 ok(ret == FP_ZERO, "ret = %x\n", ret);
883 d = 1;
884 ret = p__FExp(&d, 1, 0);
885 ok(compare_float(d, 2.7182817, 4), "d = %f\n", d);
886 ok(ret == FP_NORMAL, "ret = %x\n", ret);
888 d = 9e20;
889 ret = p__FExp(&d, 0, 0);
890 ok(d == 0, "d = %f\n", d);
891 ok(ret == FP_ZERO, "ret = %x\n", ret);
893 d = 90;
894 ret = p__FExp(&d, 1, 0);
895 ok(ret == FP_INFINITE, "ret = %x\n", ret);
897 d = 90;
898 ret = p__FExp(&d, 1, -50);
899 ok(compare_float(d, 1.0839359e+024, 4), "d = %g\n", d);
900 ok(ret == FP_NORMAL, "ret = %x\n", ret);
903 static void test_tr2_sys__File_size(void)
905 ULONGLONG val;
906 HANDLE file;
907 LARGE_INTEGER file_size;
908 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
909 CreateDirectoryA("tr2_test_dir", NULL);
911 file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
912 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
913 file_size.QuadPart = 7;
914 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
915 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
916 CloseHandle(file);
917 val = p_tr2_sys__File_size("tr2_test_dir/f1");
918 ok(val == 7, "file_size is %s\n", wine_dbgstr_longlong(val));
919 val = p_tr2_sys__File_size_wchar(testW);
920 ok(val == 7, "file_size is %s\n", wine_dbgstr_longlong(val));
922 file = CreateFileA("tr2_test_dir/f2", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
923 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
924 CloseHandle(file);
925 val = p_tr2_sys__File_size("tr2_test_dir/f2");
926 ok(val == 0, "file_size is %s\n", wine_dbgstr_longlong(val));
928 val = p_tr2_sys__File_size("tr2_test_dir");
929 ok(val == 0, "file_size is %s\n", wine_dbgstr_longlong(val));
931 errno = 0xdeadbeef;
932 val = p_tr2_sys__File_size("tr2_test_dir/not_exists_file");
933 ok(val == 0, "file_size is %s\n", wine_dbgstr_longlong(val));
934 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
936 errno = 0xdeadbeef;
937 val = p_tr2_sys__File_size(NULL);
938 ok(val == 0, "file_size is %s\n", wine_dbgstr_longlong(val));
939 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
941 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
942 ok(DeleteFileA("tr2_test_dir/f2"), "expect tr2_test_dir/f2 to exist\n");
943 ok(p_tr2_sys__Remove_dir("tr2_test_dir"), "expect tr2_test_dir to exist\n");
946 static void test_tr2_sys__Equivalent(void)
948 int val, i;
949 HANDLE file;
950 char temp_path[MAX_PATH], current_path[MAX_PATH];
951 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
952 WCHAR testW2[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','2',0};
953 struct {
954 char const *path1;
955 char const *path2;
956 int equivalent;
957 } tests[] = {
958 { NULL, NULL, -1 },
959 { NULL, "f1", -1 },
960 { "f1", NULL, -1 },
961 { "f1", "tr2_test_dir", -1 },
962 { "tr2_test_dir", "f1", -1 },
963 { "tr2_test_dir", "tr2_test_dir", -1 },
964 { "tr2_test_dir/./f1", "tr2_test_dir/f2", 0 },
965 { "tr2_test_dir/f1" , "tr2_test_dir/f1", 1 },
966 { "not_exists_file" , "tr2_test_dir/f1", 0 },
967 { "tr2_test_dir\\f1" , "tr2_test_dir/./f1", 1 },
968 { "not_exists_file" , "not_exists_file", -1 },
969 { "tr2_test_dir/f1" , "not_exists_file", 0 },
970 { "tr2_test_dir/../tr2_test_dir/f1", "tr2_test_dir/f1", 1 }
973 memset(current_path, 0, MAX_PATH);
974 GetCurrentDirectoryA(MAX_PATH, current_path);
975 memset(temp_path, 0, MAX_PATH);
976 GetTempPathA(MAX_PATH, temp_path);
977 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
978 CreateDirectoryA("tr2_test_dir", NULL);
980 file = CreateFileA("tr2_test_dir/f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
981 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
982 CloseHandle(file);
983 file = CreateFileA("tr2_test_dir/f2", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
984 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
985 CloseHandle(file);
987 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
988 errno = 0xdeadbeef;
989 val = p_tr2_sys__Equivalent(tests[i].path1, tests[i].path2);
990 ok(tests[i].equivalent == val, "tr2_sys__Equivalent(): test %d expect: %d, got %d\n", i+1, tests[i].equivalent, val);
991 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
994 val = p_tr2_sys__Equivalent_wchar(testW, testW);
995 ok(val == 1, "tr2_sys__Equivalent(): expect: 1, got %d\n", val);
996 val = p_tr2_sys__Equivalent_wchar(testW, testW2);
997 ok(val == 0, "tr2_sys__Equivalent(): expect: 0, got %d\n", val);
999 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
1000 ok(DeleteFileA("tr2_test_dir/f2"), "expect tr2_test_dir/f2 to exist\n");
1001 ok(p_tr2_sys__Remove_dir("tr2_test_dir"), "expect tr2_test_dir to exist\n");
1002 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
1005 static void test_tr2_sys__Current_get(void)
1007 char temp_path[MAX_PATH], current_path[MAX_PATH], origin_path[MAX_PATH];
1008 char *temp;
1009 WCHAR temp_path_wchar[MAX_PATH], current_path_wchar[MAX_PATH];
1010 WCHAR *temp_wchar;
1011 memset(origin_path, 0, MAX_PATH);
1012 GetCurrentDirectoryA(MAX_PATH, origin_path);
1013 memset(temp_path, 0, MAX_PATH);
1014 GetTempPathA(MAX_PATH, temp_path);
1016 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
1017 memset(current_path, 0, MAX_PATH);
1018 temp = p_tr2_sys__Current_get(current_path);
1019 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1020 temp[strlen(temp)] = '\\';
1021 ok(!strcmp(temp_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", temp_path, current_path);
1023 GetTempPathW(MAX_PATH, temp_path_wchar);
1024 ok(SetCurrentDirectoryW(temp_path_wchar), "SetCurrentDirectoryW to temp_path_wchar failed\n");
1025 memset(current_path_wchar, 0, MAX_PATH);
1026 temp_wchar = p_tr2_sys__Current_get_wchar(current_path_wchar);
1027 ok(temp_wchar == current_path_wchar, "p_tr2_sys__Current_get_wchar returned different buffer\n");
1028 temp_wchar[wcslen(temp_wchar)] = '\\';
1029 ok(!wcscmp(temp_path_wchar, current_path_wchar), "test_tr2_sys__Current_get(): expect: %s, got %s\n", wine_dbgstr_w(temp_path_wchar), wine_dbgstr_w(current_path_wchar));
1031 ok(SetCurrentDirectoryA(origin_path), "SetCurrentDirectoryA to origin_path failed\n");
1032 memset(current_path, 0, MAX_PATH);
1033 temp = p_tr2_sys__Current_get(current_path);
1034 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1035 ok(!strcmp(origin_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", origin_path, current_path);
1038 static void test_tr2_sys__Current_set(void)
1040 char temp_path[MAX_PATH], current_path[MAX_PATH], origin_path[MAX_PATH];
1041 char *temp;
1042 WCHAR testW[] = {'.','/',0};
1043 memset(temp_path, 0, MAX_PATH);
1044 GetTempPathA(MAX_PATH, temp_path);
1045 memset(origin_path, 0, MAX_PATH);
1046 GetCurrentDirectoryA(MAX_PATH, origin_path);
1047 temp = p_tr2_sys__Current_get(origin_path);
1048 ok(temp == origin_path, "p_tr2_sys__Current_get returned different buffer\n");
1050 ok(p_tr2_sys__Current_set(temp_path), "p_tr2_sys__Current_set to temp_path failed\n");
1051 memset(current_path, 0, MAX_PATH);
1052 temp = p_tr2_sys__Current_get(current_path);
1053 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1054 temp[strlen(temp)] = '\\';
1055 ok(!strcmp(temp_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", temp_path, current_path);
1057 ok(p_tr2_sys__Current_set_wchar(testW), "p_tr2_sys__Current_set_wchar to temp_path failed\n");
1058 memset(current_path, 0, MAX_PATH);
1059 temp = p_tr2_sys__Current_get(current_path);
1060 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1061 temp[strlen(temp)] = '\\';
1062 ok(!strcmp(temp_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", temp_path, current_path);
1064 errno = 0xdeadbeef;
1065 ok(!p_tr2_sys__Current_set("not_exisist_dir"), "p_tr2_sys__Current_set to not_exist_dir succeed\n");
1066 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
1068 errno = 0xdeadbeef;
1069 ok(!p_tr2_sys__Current_set("??invalid_name>>"), "p_tr2_sys__Current_set to ??invalid_name>> succeed\n");
1070 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
1072 ok(p_tr2_sys__Current_set(origin_path), "p_tr2_sys__Current_set to origin_path failed\n");
1073 memset(current_path, 0, MAX_PATH);
1074 temp = p_tr2_sys__Current_get(current_path);
1075 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1076 ok(!strcmp(origin_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", origin_path, current_path);
1079 static void test_tr2_sys__Make_dir(void)
1081 int ret, i;
1082 WCHAR testW[] = {'w','d',0};
1083 struct {
1084 char const *path;
1085 int val;
1086 } tests[] = {
1087 { "tr2_test_dir", 1 },
1088 { "tr2_test_dir", 0 },
1089 { NULL, -1 },
1090 { "??invalid_name>>", -1 }
1093 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1094 errno = 0xdeadbeef;
1095 ret = p_tr2_sys__Make_dir(tests[i].path);
1096 ok(ret == tests[i].val, "tr2_sys__Make_dir(): test %d expect: %d, got %d\n", i+1, tests[i].val, ret);
1097 ok(errno == 0xdeadbeef, "tr2_sys__Make_dir(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1099 ret = p_tr2_sys__Make_dir_wchar(testW);
1100 ok(ret == 1, "tr2_sys__Make_dir(): expect: 1, got %d\n", ret);
1102 ok(p_tr2_sys__Remove_dir("tr2_test_dir"), "expect tr2_test_dir to exist\n");
1103 ok(p_tr2_sys__Remove_dir_wchar(testW), "expect wd to exist\n");
1106 static void test_tr2_sys__Remove_dir(void)
1108 MSVCP_bool ret;
1109 int i;
1110 struct {
1111 char const *path;
1112 MSVCP_bool val;
1113 } tests[] = {
1114 { "tr2_test_dir", TRUE },
1115 { "tr2_test_dir", FALSE },
1116 { NULL, FALSE },
1117 { "??invalid_name>>", FALSE }
1120 ok(p_tr2_sys__Make_dir("tr2_test_dir"), "tr2_sys__Make_dir() failed\n");
1122 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1123 errno = 0xdeadbeef;
1124 ret = p_tr2_sys__Remove_dir(tests[i].path);
1125 ok(ret == tests[i].val, "test_tr2_sys__Remove_dir(): test %d expect: %d, got %d\n", i+1, tests[i].val, ret);
1126 ok(errno == 0xdeadbeef, "test_tr2_sys__Remove_dir(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1130 static void test_tr2_sys__Copy_file(void)
1132 HANDLE file;
1133 int ret, i;
1134 LARGE_INTEGER file_size;
1135 WCHAR testW[] = {'f','1',0}, testW2[] = {'f','w',0};
1136 struct {
1137 char const *source;
1138 char const *dest;
1139 MSVCP_bool fail_if_exists;
1140 int last_error;
1141 int last_error2;
1142 MSVCP_bool is_todo;
1143 } tests[] = {
1144 { "f1", "f1_copy", TRUE, ERROR_SUCCESS, ERROR_SUCCESS, FALSE },
1145 { "f1", "tr2_test_dir\\f1_copy", TRUE, ERROR_SUCCESS, ERROR_SUCCESS, FALSE },
1146 { "f1", "tr2_test_dir\\f1_copy", TRUE, ERROR_FILE_EXISTS, ERROR_FILE_EXISTS, FALSE },
1147 { "f1", "tr2_test_dir\\f1_copy", FALSE, ERROR_SUCCESS, ERROR_SUCCESS, FALSE },
1148 { "tr2_test_dir", "f1", TRUE, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED, FALSE },
1149 { "tr2_test_dir", "tr2_test_dir_copy", TRUE, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED, FALSE },
1150 { NULL, "f1", TRUE, ERROR_INVALID_PARAMETER, ERROR_INVALID_PARAMETER, TRUE },
1151 { "f1", NULL, TRUE, ERROR_INVALID_PARAMETER, ERROR_INVALID_PARAMETER, TRUE },
1152 { "not_exist", "tr2_test_dir", TRUE, ERROR_FILE_NOT_FOUND, ERROR_FILE_NOT_FOUND, FALSE },
1153 { "f1", "not_exist_dir\\f1_copy", TRUE, ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND, FALSE },
1154 { "f1", "tr2_test_dir", TRUE, ERROR_ACCESS_DENIED, ERROR_FILE_EXISTS, FALSE }
1157 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1158 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1159 file = CreateFileA("f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1160 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1161 file_size.QuadPart = 7;
1162 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1163 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1164 CloseHandle(file);
1166 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1167 errno = 0xdeadbeef;
1168 ret = p_tr2_sys__Copy_file(tests[i].source, tests[i].dest, tests[i].fail_if_exists);
1169 todo_wine_if(tests[i].is_todo)
1170 ok(ret == tests[i].last_error || ret == tests[i].last_error2,
1171 "test_tr2_sys__Copy_file(): test %d expect: %d, got %d\n", i+1, tests[i].last_error, ret);
1172 ok(errno == 0xdeadbeef, "test_tr2_sys__Copy_file(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1173 if(ret == ERROR_SUCCESS)
1174 ok(p_tr2_sys__File_size(tests[i].source) == p_tr2_sys__File_size(tests[i].dest),
1175 "test_tr2_sys__Copy_file(): test %d failed, two files' size are not equal\n", i+1);
1177 ret = p_tr2_sys__Copy_file_wchar(testW, testW2, TRUE);
1178 ok(ret == ERROR_SUCCESS, "test_tr2_sys__Copy_file_wchar() expect ERROR_SUCCESS, got %d\n", ret);
1180 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1181 ok(DeleteFileW(testW2), "expect fw to exist\n");
1182 ok(DeleteFileA("f1_copy"), "expect f1_copy to exist\n");
1183 ok(DeleteFileA("tr2_test_dir/f1_copy"), "expect tr2_test_dir/f1 to exist\n");
1184 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1185 ok(ret == 1, "test_tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1188 static void test_tr2_sys__Rename(void)
1190 int ret, i;
1191 HANDLE file, h1, h2;
1192 BY_HANDLE_FILE_INFORMATION info1, info2;
1193 char temp_path[MAX_PATH], current_path[MAX_PATH];
1194 LARGE_INTEGER file_size;
1195 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
1196 WCHAR testW2[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','w',0};
1197 struct {
1198 char const *old_path;
1199 char const *new_path;
1200 int val;
1201 } tests[] = {
1202 { "tr2_test_dir\\f1", "tr2_test_dir\\f1_rename", ERROR_SUCCESS },
1203 { "tr2_test_dir\\f1", NULL, ERROR_INVALID_PARAMETER },
1204 { "tr2_test_dir\\f1", "tr2_test_dir\\f1_rename", ERROR_FILE_NOT_FOUND },
1205 { NULL, "tr2_test_dir\\NULL_rename", ERROR_INVALID_PARAMETER },
1206 { "tr2_test_dir\\f1_rename", "tr2_test_dir\\??invalid_name>>", ERROR_INVALID_NAME },
1207 { "tr2_test_dir\\not_exist_file", "tr2_test_dir\\not_exist_rename", ERROR_FILE_NOT_FOUND }
1210 memset(current_path, 0, MAX_PATH);
1211 GetCurrentDirectoryA(MAX_PATH, current_path);
1212 memset(temp_path, 0, MAX_PATH);
1213 GetTempPathA(MAX_PATH, temp_path);
1214 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
1215 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1217 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1218 file = CreateFileA("tr2_test_dir\\f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1219 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1220 CloseHandle(file);
1222 ret = p_tr2_sys__Rename("tr2_test_dir\\f1", "tr2_test_dir\\f1");
1223 todo_wine ok(ERROR_SUCCESS == ret, "test_tr2_sys__Rename(): expect: ERROR_SUCCESS, got %d\n", ret);
1224 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1225 errno = 0xdeadbeef;
1226 if(tests[i].val == ERROR_SUCCESS) {
1227 h1 = CreateFileA(tests[i].old_path, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1228 NULL, OPEN_EXISTING, 0, 0);
1229 ok(h1 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1230 ok(GetFileInformationByHandle(h1, &info1), "GetFileInformationByHandle failed\n");
1231 CloseHandle(h1);
1233 SetLastError(0xdeadbeef);
1234 ret = p_tr2_sys__Rename(tests[i].old_path, tests[i].new_path);
1235 ok(ret == tests[i].val, "test_tr2_sys__Rename(): test %d expect: %d, got %d\n", i+1, tests[i].val, ret);
1236 ok(errno == 0xdeadbeef, "test_tr2_sys__Rename(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1237 if(ret == ERROR_SUCCESS) {
1238 h2 = CreateFileA(tests[i].new_path, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1239 NULL, OPEN_EXISTING, 0, 0);
1240 ok(h2 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1241 ok(GetFileInformationByHandle(h2, &info2), "GetFileInformationByHandle failed\n");
1242 CloseHandle(h2);
1243 ok(info1.nFileIndexHigh == info2.nFileIndexHigh
1244 && info1.nFileIndexLow == info2.nFileIndexLow,
1245 "test_tr2_sys__Rename(): test %d expect two files equivalent\n", i+1);
1249 file = CreateFileA("tr2_test_dir\\f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1250 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1251 file_size.QuadPart = 7;
1252 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1253 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1254 CloseHandle(file);
1255 ret = p_tr2_sys__Rename("tr2_test_dir\\f1", "tr2_test_dir\\f1_rename");
1256 ok(ret == ERROR_ALREADY_EXISTS, "test_tr2_sys__Rename(): expect: ERROR_ALREADY_EXISTS, got %d\n", ret);
1257 ok(p_tr2_sys__File_size("tr2_test_dir\\f1") == 7, "test_tr2_sys__Rename(): expect: 7, got %s\n", wine_dbgstr_longlong(p_tr2_sys__File_size("tr2_test_dir\\f1")));
1258 ok(p_tr2_sys__File_size("tr2_test_dir\\f1_rename") == 0, "test_tr2_sys__Rename(): expect: 0, got %s\n",wine_dbgstr_longlong(p_tr2_sys__File_size("tr2_test_dir\\f1_rename")));
1259 ret = p_tr2_sys__Rename_wchar(testW, testW2);
1260 ok(ret == ERROR_SUCCESS, "tr2_sys__Rename_wchar(): expect: ERROR_SUCCESS, got %d\n", ret);
1262 ok(DeleteFileW(testW2), "expect fw to exist\n");
1263 ok(DeleteFileA("tr2_test_dir\\f1_rename"), "expect f1_rename to exist\n");
1264 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1265 ok(ret == 1, "test_tr2_sys__Remove_dir(): expect %d got %d\n", 1, ret);
1266 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
1269 static void test_tr2_sys__Statvfs(void)
1271 struct space_info info;
1272 char current_path[MAX_PATH];
1273 WCHAR current_path_wchar[MAX_PATH];
1274 memset(current_path, 0, MAX_PATH);
1275 p_tr2_sys__Current_get(current_path);
1276 memset(current_path_wchar, 0, MAX_PATH);
1277 p_tr2_sys__Current_get_wchar(current_path_wchar);
1279 p_tr2_sys__Statvfs(&info, current_path);
1280 ok(info.capacity >= info.free, "test_tr2_sys__Statvfs(): info.capacity < info.free\n");
1281 ok(info.free >= info.available, "test_tr2_sys__Statvfs(): info.free < info.available\n");
1283 p_tr2_sys__Statvfs_wchar(&info, current_path_wchar);
1284 ok(info.capacity >= info.free, "tr2_sys__Statvfs_wchar(): info.capacity < info.free\n");
1285 ok(info.free >= info.available, "tr2_sys__Statvfs_wchar(): info.free < info.available\n");
1287 p_tr2_sys__Statvfs(&info, NULL);
1288 ok(info.available == 0, "test_tr2_sys__Statvfs(): info.available expect: %d, got %s\n",
1289 0, wine_dbgstr_longlong(info.available));
1290 ok(info.capacity == 0, "test_tr2_sys__Statvfs(): info.capacity expect: %d, got %s\n",
1291 0, wine_dbgstr_longlong(info.capacity));
1292 ok(info.free == 0, "test_tr2_sys__Statvfs(): info.free expect: %d, got %s\n",
1293 0, wine_dbgstr_longlong(info.free));
1295 p_tr2_sys__Statvfs(&info, "not_exist");
1296 ok(info.available == 0, "test_tr2_sys__Statvfs(): info.available expect: %d, got %s\n",
1297 0, wine_dbgstr_longlong(info.available));
1298 ok(info.capacity == 0, "test_tr2_sys__Statvfs(): info.capacity expect: %d, got %s\n",
1299 0, wine_dbgstr_longlong(info.capacity));
1300 ok(info.free == 0, "test_tr2_sys__Statvfs(): info.free expect: %d, got %s\n",
1301 0, wine_dbgstr_longlong(info.free));
1304 static void test_tr2_sys__Stat(void)
1306 int i, err_code, ret;
1307 HANDLE file;
1308 enum file_type val;
1309 struct {
1310 char const *path;
1311 enum file_type ret;
1312 int err_code;
1313 int is_todo;
1314 } tests[] = {
1315 { NULL, status_unknown, ERROR_INVALID_PARAMETER, FALSE },
1316 { "tr2_test_dir", directory_file, ERROR_SUCCESS, FALSE },
1317 { "tr2_test_dir\\f1", regular_file, ERROR_SUCCESS, FALSE },
1318 { "tr2_test_dir\\not_exist_file ", file_not_found, ERROR_SUCCESS, FALSE },
1319 { "tr2_test_dir\\??invalid_name>>", file_not_found, ERROR_SUCCESS, FALSE },
1320 { "tr2_test_dir\\f1_link" , regular_file, ERROR_SUCCESS, TRUE },
1321 { "tr2_test_dir\\dir_link", directory_file, ERROR_SUCCESS, TRUE },
1323 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r',0};
1324 WCHAR testW2[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
1326 CreateDirectoryA("tr2_test_dir", NULL);
1327 file = CreateFileA("tr2_test_dir/f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1328 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1329 ok(CloseHandle(file), "CloseHandle\n");
1330 SetLastError(0xdeadbeef);
1331 ret = pCreateSymbolicLinkA ? pCreateSymbolicLinkA("tr2_test_dir/f1_link", "tr2_test_dir/f1", 0) : FALSE;
1332 if(!ret && (!pCreateSymbolicLinkA || GetLastError()==ERROR_PRIVILEGE_NOT_HELD||GetLastError()==ERROR_INVALID_FUNCTION)) {
1333 tests[5].ret = tests[6].ret = file_not_found;
1334 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
1335 }else {
1336 ok(ret, "CreateSymbolicLinkA failed\n");
1337 ok(pCreateSymbolicLinkA("tr2_test_dir/dir_link", "tr2_test_dir", 1), "CreateSymbolicLinkA failed\n");
1340 file = CreateNamedPipeA("\\\\.\\PiPe\\tests_pipe.c",
1341 PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024,
1342 NMPWAIT_USE_DEFAULT_WAIT, NULL);
1343 ok(file != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1344 err_code = 0xdeadbeef;
1345 val = p_tr2_sys__Stat("\\\\.\\PiPe\\tests_pipe.c", &err_code);
1346 todo_wine ok(regular_file == val, "tr2_sys__Stat(): expect: regular_file, got %d\n", val);
1347 todo_wine ok(ERROR_SUCCESS == err_code, "tr2_sys__Stat(): err_code expect: ERROR_SUCCESS, got %d\n", err_code);
1348 err_code = 0xdeadbeef;
1349 val = p_tr2_sys__Lstat("\\\\.\\PiPe\\tests_pipe.c", &err_code);
1350 ok(status_unknown == val, "tr2_sys__Lstat(): expect: status_unknown, got %d\n", val);
1351 todo_wine ok(ERROR_PIPE_BUSY == err_code, "tr2_sys__Lstat(): err_code expect: ERROR_PIPE_BUSY, got %d\n", err_code);
1352 ok(CloseHandle(file), "CloseHandle\n");
1353 file = CreateNamedPipeA("\\\\.\\PiPe\\tests_pipe.c",
1354 PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024,
1355 NMPWAIT_USE_DEFAULT_WAIT, NULL);
1356 ok(file != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1357 err_code = 0xdeadbeef;
1358 val = p_tr2_sys__Lstat("\\\\.\\PiPe\\tests_pipe.c", &err_code);
1359 todo_wine ok(regular_file == val, "tr2_sys__Lstat(): expect: regular_file, got %d\n", val);
1360 todo_wine ok(ERROR_SUCCESS == err_code, "tr2_sys__Lstat(): err_code expect: ERROR_SUCCESS, got %d\n", err_code);
1361 ok(CloseHandle(file), "CloseHandle\n");
1363 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1364 err_code = 0xdeadbeef;
1365 val = p_tr2_sys__Stat(tests[i].path, &err_code);
1366 todo_wine_if(tests[i].is_todo)
1367 ok(tests[i].ret == val, "tr2_sys__Stat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
1368 ok(tests[i].err_code == err_code, "tr2_sys__Stat(): test %d err_code expect: %d, got %d\n",
1369 i+1, tests[i].err_code, err_code);
1371 /* test tr2_sys__Lstat */
1372 err_code = 0xdeadbeef;
1373 val = p_tr2_sys__Lstat(tests[i].path, &err_code);
1374 todo_wine_if(tests[i].is_todo)
1375 ok(tests[i].ret == val, "tr2_sys__Lstat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
1376 ok(tests[i].err_code == err_code, "tr2_sys__Lstat(): test %d err_code expect: %d, got %d\n",
1377 i+1, tests[i].err_code, err_code);
1380 err_code = 0xdeadbeef;
1381 val = p_tr2_sys__Stat_wchar(testW, &err_code);
1382 ok(directory_file == val, "tr2_sys__Stat_wchar() expect directory_file, got %d\n", val);
1383 ok(ERROR_SUCCESS == err_code, "tr2_sys__Stat_wchar(): err_code expect ERROR_SUCCESS, got %d\n", err_code);
1384 err_code = 0xdeadbeef;
1385 val = p_tr2_sys__Lstat_wchar(testW2, &err_code);
1386 ok(regular_file == val, "tr2_sys__Lstat_wchar() expect regular_file, got %d\n", val);
1387 ok(ERROR_SUCCESS == err_code, "tr2_sys__Lstat_wchar(): err_code expect ERROR_SUCCESS, got %d\n", err_code);
1389 if(ret) {
1390 todo_wine ok(DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link to exist\n");
1391 todo_wine ok(RemoveDirectoryA("tr2_test_dir/dir_link"), "expect tr2_test_dir/dir_link to exist\n");
1393 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
1394 ok(RemoveDirectoryA("tr2_test_dir"), "expect tr2_test_dir to exist\n");
1397 static void test_tr2_sys__Last_write_time(void)
1399 HANDLE file;
1400 int ret;
1401 __int64 last_write_time, newtime;
1402 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1403 ok(ret == 1, "tr2_sys__Make_dir() expect 1 got %d\n", ret);
1405 file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1406 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1407 CloseHandle(file);
1409 last_write_time = p_tr2_sys__Last_write_time("tr2_test_dir/f1");
1410 newtime = last_write_time + 123456789;
1411 p_tr2_sys__Last_write_time_set("tr2_test_dir/f1", newtime);
1412 todo_wine ok(last_write_time == p_tr2_sys__Last_write_time("tr2_test_dir/f1"),
1413 "last_write_time should have changed: %s\n",
1414 wine_dbgstr_longlong(last_write_time));
1416 errno = 0xdeadbeef;
1417 last_write_time = p_tr2_sys__Last_write_time("not_exist");
1418 ok(errno == 0xdeadbeef, "tr2_sys__Last_write_time(): errno expect 0xdeadbeef, got %d\n", errno);
1419 ok(last_write_time == 0, "expect 0 got %s\n", wine_dbgstr_longlong(last_write_time));
1420 last_write_time = p_tr2_sys__Last_write_time(NULL);
1421 ok(last_write_time == 0, "expect 0 got %s\n", wine_dbgstr_longlong(last_write_time));
1423 p_tr2_sys__Last_write_time_set("not_exist", newtime);
1424 errno = 0xdeadbeef;
1425 p_tr2_sys__Last_write_time_set(NULL, newtime);
1426 ok(errno == 0xdeadbeef, "tr2_sys__Last_write_time(): errno expect 0xdeadbeef, got %d\n", errno);
1428 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
1429 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1430 ok(ret == 1, "test_tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1433 static void test_tr2_sys__dir_operation(void)
1435 char *file_name, first_file_name[MAX_PATH], dest[MAX_PATH], longer_path[MAX_PATH];
1436 HANDLE file, result_handle;
1437 enum file_type type;
1438 int err, num_of_f1 = 0, num_of_f2 = 0, num_of_sub_dir = 0, num_of_other_files = 0;
1440 CreateDirectoryA("tr2_test_dir", NULL);
1441 file = CreateFileA("tr2_test_dir/f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1442 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1443 CloseHandle(file);
1444 file = CreateFileA("tr2_test_dir/f2", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1445 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1446 CloseHandle(file);
1447 CreateDirectoryA("tr2_test_dir/sub_dir", NULL);
1448 file = CreateFileA("tr2_test_dir/sub_dir/sub_f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1449 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1450 CloseHandle(file);
1452 memset(longer_path, 0, MAX_PATH);
1453 GetCurrentDirectoryA(MAX_PATH, longer_path);
1454 strcat(longer_path, "\\tr2_test_dir\\");
1455 while(lstrlenA(longer_path) < MAX_PATH-1)
1456 strcat(longer_path, "s");
1457 ok(lstrlenA(longer_path) == MAX_PATH-1, "tr2_sys__Open_dir(): expect MAX_PATH, got %d\n", lstrlenA(longer_path));
1458 memset(first_file_name, 0, MAX_PATH);
1459 type = err = 0xdeadbeef;
1460 result_handle = NULL;
1461 result_handle = p_tr2_sys__Open_dir(first_file_name, longer_path, &err, &type);
1462 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect NULL, got %p\n", result_handle);
1463 ok(!*first_file_name, "tr2_sys__Open_dir(): expect: 0, got %s\n", first_file_name);
1464 ok(err == ERROR_BAD_PATHNAME, "tr2_sys__Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err);
1465 ok((int)type == 0xdeadbeef, "tr2_sys__Open_dir(): expect 0xdeadbeef, got %d\n", type);
1467 memset(first_file_name, 0, MAX_PATH);
1468 memset(dest, 0, MAX_PATH);
1469 err = type = 0xdeadbeef;
1470 result_handle = NULL;
1471 result_handle = p_tr2_sys__Open_dir(first_file_name, "tr2_test_dir", &err, &type);
1472 ok(result_handle != NULL, "tr2_sys__Open_dir(): expect: not NULL, got %p\n", result_handle);
1473 ok(err == ERROR_SUCCESS, "tr2_sys__Open_dir(): expect: ERROR_SUCCESS, got %d\n", err);
1474 file_name = first_file_name;
1475 while(*file_name) {
1476 if (!strcmp(file_name, "f1")) {
1477 ++num_of_f1;
1478 ok(type == regular_file, "expect regular_file, got %d\n", type);
1479 }else if(!strcmp(file_name, "f2")) {
1480 ++num_of_f2;
1481 ok(type == regular_file, "expect regular_file, got %d\n", type);
1482 }else if(!strcmp(file_name, "sub_dir")) {
1483 ++num_of_sub_dir;
1484 ok(type == directory_file, "expect directory_file, got %d\n", type);
1485 }else {
1486 ++num_of_other_files;
1488 file_name = p_tr2_sys__Read_dir(dest, result_handle, &type);
1490 ok(type == status_unknown, "p_tr2_sys__Read_dir(): expect: status_unknown, got %d\n", type);
1491 p_tr2_sys__Close_dir(result_handle);
1492 ok(result_handle != NULL, "tr2_sys__Open_dir(): expect: not NULL, got %p\n", result_handle);
1493 ok(num_of_f1 == 1, "found f1 %d times\n", num_of_f1);
1494 ok(num_of_f2 == 1, "found f2 %d times\n", num_of_f2);
1495 ok(num_of_sub_dir == 1, "found sub_dir %d times\n", num_of_sub_dir);
1496 ok(num_of_other_files == 0, "found %d other files\n", num_of_other_files);
1498 memset(first_file_name, 0, MAX_PATH);
1499 err = type = 0xdeadbeef;
1500 result_handle = file;
1501 result_handle = p_tr2_sys__Open_dir(first_file_name, "not_exist", &err, &type);
1502 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect: NULL, got %p\n", result_handle);
1503 todo_wine ok(err == ERROR_BAD_PATHNAME, "tr2_sys__Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err);
1504 ok((int)type == 0xdeadbeef, "tr2_sys__Open_dir(): expect: 0xdeadbeef, got %d\n", type);
1505 ok(!*first_file_name, "tr2_sys__Open_dir(): expect: 0, got %s\n", first_file_name);
1507 CreateDirectoryA("empty_dir", NULL);
1508 memset(first_file_name, 0, MAX_PATH);
1509 err = type = 0xdeadbeef;
1510 result_handle = file;
1511 result_handle = p_tr2_sys__Open_dir(first_file_name, "empty_dir", &err, &type);
1512 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect: NULL, got %p\n", result_handle);
1513 ok(err == ERROR_SUCCESS, "tr2_sys__Open_dir(): expect: ERROR_SUCCESS, got %d\n", err);
1514 ok(type == status_unknown, "tr2_sys__Open_dir(): expect: status_unknown, got %d\n", type);
1515 ok(!*first_file_name, "tr2_sys__Open_dir(): expect: 0, got %s\n", first_file_name);
1516 p_tr2_sys__Close_dir(result_handle);
1517 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect: NULL, got %p\n", result_handle);
1519 ok(RemoveDirectoryA("empty_dir"), "expect empty_dir to exist\n");
1520 ok(DeleteFileA("tr2_test_dir/sub_dir/sub_f1"), "expect tr2_test_dir/sub_dir/sub_f1 to exist\n");
1521 ok(RemoveDirectoryA("tr2_test_dir/sub_dir"), "expect tr2_test_dir/sub_dir to exist\n");
1522 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
1523 ok(DeleteFileA("tr2_test_dir/f2"), "expect tr2_test_dir/f2 to exist\n");
1524 ok(RemoveDirectoryA("tr2_test_dir"), "expect tr2_test_dir to exist\n");
1527 static void test_tr2_sys__Link(void)
1529 int ret, i;
1530 HANDLE file, h1, h2;
1531 BY_HANDLE_FILE_INFORMATION info1, info2;
1532 char temp_path[MAX_PATH], current_path[MAX_PATH];
1533 LARGE_INTEGER file_size;
1534 struct {
1535 char const *existing_path;
1536 char const *new_path;
1537 MSVCP_bool fail_if_exists;
1538 int last_error;
1539 } tests[] = {
1540 { "f1", "f1_link", TRUE, ERROR_SUCCESS },
1541 { "f1", "tr2_test_dir\\f1_link", TRUE, ERROR_SUCCESS },
1542 { "tr2_test_dir\\f1_link", "tr2_test_dir\\f1_link_link", TRUE, ERROR_SUCCESS },
1543 { "tr2_test_dir", "dir_link", TRUE, ERROR_ACCESS_DENIED },
1544 { NULL, "NULL_link", TRUE, ERROR_INVALID_PARAMETER },
1545 { "f1", NULL, TRUE, ERROR_INVALID_PARAMETER },
1546 { "not_exist", "not_exist_link", TRUE, ERROR_FILE_NOT_FOUND },
1547 { "f1", "not_exist_dir\\f1_link", TRUE, ERROR_PATH_NOT_FOUND }
1550 memset(current_path, 0, MAX_PATH);
1551 GetCurrentDirectoryA(MAX_PATH, current_path);
1552 memset(temp_path, 0, MAX_PATH);
1553 GetTempPathA(MAX_PATH, temp_path);
1554 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
1556 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1557 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1558 file = CreateFileA("f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1559 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1560 file_size.QuadPart = 7;
1561 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1562 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1563 CloseHandle(file);
1565 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1566 errno = 0xdeadbeef;
1567 ret = p_tr2_sys__Link(tests[i].existing_path, tests[i].new_path);
1568 ok(ret == tests[i].last_error, "tr2_sys__Link(): test %d expect: %d, got %d\n",
1569 i+1, tests[i].last_error, ret);
1570 ok(errno == 0xdeadbeef, "tr2_sys__Link(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1571 if(ret == ERROR_SUCCESS)
1572 ok(p_tr2_sys__File_size(tests[i].existing_path) == p_tr2_sys__File_size(tests[i].new_path),
1573 "tr2_sys__Link(): test %d failed, two files' size are not equal\n", i+1);
1576 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1577 ok(p_tr2_sys__File_size("f1_link") == p_tr2_sys__File_size("tr2_test_dir/f1_link") &&
1578 p_tr2_sys__File_size("tr2_test_dir/f1_link") == p_tr2_sys__File_size("tr2_test_dir/f1_link_link"),
1579 "tr2_sys__Link(): expect links' size are equal, got %s\n", wine_dbgstr_longlong(p_tr2_sys__File_size("tr2_test_dir/f1_link_link")));
1580 ok(p_tr2_sys__File_size("f1_link") == 7, "tr2_sys__Link(): expect f1_link's size equals to 7, got %s\n", wine_dbgstr_longlong(p_tr2_sys__File_size("f1_link")));
1582 file = CreateFileA("f1_link", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1583 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1584 file_size.QuadPart = 20;
1585 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1586 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1587 CloseHandle(file);
1588 h1 = CreateFileA("f1_link", 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1589 NULL, OPEN_EXISTING, 0, 0);
1590 ok(h1 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1591 ok(GetFileInformationByHandle(h1, &info1), "GetFileInformationByHandle failed\n");
1592 CloseHandle(h1);
1593 h2 = CreateFileA("tr2_test_dir/f1_link", 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1594 NULL, OPEN_EXISTING, 0, 0);
1595 ok(h2 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1596 ok(GetFileInformationByHandle(h2, &info2), "GetFileInformationByHandle failed\n");
1597 CloseHandle(h2);
1598 ok(info1.nFileIndexHigh == info2.nFileIndexHigh
1599 && info1.nFileIndexLow == info2.nFileIndexLow,
1600 "tr2_sys__Link(): test %d expect two files equivalent\n", i+1);
1601 ok(p_tr2_sys__File_size("f1_link") == 20, "tr2_sys__Link(): expect f1_link's size equals to 20, got %s\n", wine_dbgstr_longlong(p_tr2_sys__File_size("f1_link")));
1603 ok(DeleteFileA("f1_link"), "expect f1_link to exist\n");
1604 ok(DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link to exist\n");
1605 ok(DeleteFileA("tr2_test_dir/f1_link_link"), "expect tr2_test_dir/f1_link_link to exist\n");
1606 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1607 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1608 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
1611 static void test_tr2_sys__Symlink(void)
1613 int ret, i;
1614 HANDLE file;
1615 LARGE_INTEGER file_size;
1616 struct {
1617 char const *existing_path;
1618 char const *new_path;
1619 int last_error;
1620 MSVCP_bool is_todo;
1621 } tests[] = {
1622 { "f1", "f1_link", ERROR_SUCCESS, FALSE },
1623 { "f1", "tr2_test_dir\\f1_link", ERROR_SUCCESS, FALSE },
1624 { "tr2_test_dir\\f1_link", "tr2_test_dir\\f1_link_link", ERROR_SUCCESS, FALSE },
1625 { "tr2_test_dir", "dir_link", ERROR_SUCCESS, FALSE },
1626 { NULL, "NULL_link", ERROR_INVALID_PARAMETER, FALSE },
1627 { "f1", NULL, ERROR_INVALID_PARAMETER, FALSE },
1628 { "not_exist", "not_exist_link", ERROR_SUCCESS, FALSE },
1629 { "f1", "not_exist_dir\\f1_link", ERROR_PATH_NOT_FOUND, TRUE }
1632 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1633 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1634 file = CreateFileA("f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1635 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1636 file_size.QuadPart = 7;
1637 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1638 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1639 CloseHandle(file);
1641 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1642 errno = 0xdeadbeef;
1643 SetLastError(0xdeadbeef);
1644 ret = p_tr2_sys__Symlink(tests[i].existing_path, tests[i].new_path);
1645 if(!i && (ret==ERROR_PRIVILEGE_NOT_HELD || ret==ERROR_INVALID_FUNCTION || ret==ERROR_CALL_NOT_IMPLEMENTED)) {
1646 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
1647 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1648 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1649 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1650 return;
1653 ok(errno == 0xdeadbeef, "tr2_sys__Symlink(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1654 todo_wine_if(tests[i].is_todo)
1655 ok(ret == tests[i].last_error, "tr2_sys__Symlink(): test %d expect: %d, got %d\n", i+1, tests[i].last_error, ret);
1656 if(ret == ERROR_SUCCESS)
1657 ok(p_tr2_sys__File_size(tests[i].new_path) == 0, "tr2_sys__Symlink(): expect 0, got %s\n", wine_dbgstr_longlong(p_tr2_sys__File_size(tests[i].new_path)));
1660 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1661 todo_wine ok(DeleteFileA("f1_link"), "expect f1_link to exist\n");
1662 todo_wine ok(DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link to exist\n");
1663 todo_wine ok(DeleteFileA("tr2_test_dir/f1_link_link"), "expect tr2_test_dir/f1_link_link to exist\n");
1664 todo_wine ok(DeleteFileA("not_exist_link"), "expect not_exist_link to exist\n");
1665 todo_wine ok(DeleteFileA("dir_link"), "expect dir_link to exist\n");
1666 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1667 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1670 static void test_tr2_sys__Unlink(void)
1672 char temp_path[MAX_PATH], current_path[MAX_PATH];
1673 int ret, i;
1674 HANDLE file;
1675 LARGE_INTEGER file_size;
1676 struct {
1677 char const *path;
1678 int last_error;
1679 MSVCP_bool is_todo;
1680 } tests[] = {
1681 { "tr2_test_dir\\f1_symlink", ERROR_SUCCESS, TRUE },
1682 { "tr2_test_dir\\f1_link", ERROR_SUCCESS, FALSE },
1683 { "tr2_test_dir\\f1", ERROR_SUCCESS, FALSE },
1684 { "tr2_test_dir", ERROR_ACCESS_DENIED, FALSE },
1685 { "not_exist", ERROR_FILE_NOT_FOUND, FALSE },
1686 { "not_exist_dir\\not_exist_file", ERROR_PATH_NOT_FOUND, FALSE },
1687 { NULL, ERROR_PATH_NOT_FOUND, FALSE }
1690 GetCurrentDirectoryA(MAX_PATH, current_path);
1691 GetTempPathA(MAX_PATH, temp_path);
1692 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
1694 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1695 ok(ret == 1, "tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1696 file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1697 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1698 file_size.QuadPart = 7;
1699 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1700 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1701 CloseHandle(file);
1703 ret = p_tr2_sys__Symlink("tr2_test_dir/f1", "tr2_test_dir/f1_symlink");
1704 if(ret==ERROR_PRIVILEGE_NOT_HELD || ret==ERROR_INVALID_FUNCTION || ret==ERROR_CALL_NOT_IMPLEMENTED) {
1705 tests[0].last_error = ERROR_FILE_NOT_FOUND;
1706 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
1707 }else {
1708 ok(ret == ERROR_SUCCESS, "tr2_sys__Symlink(): expect: ERROR_SUCCESS, got %d\n", ret);
1710 ret = p_tr2_sys__Link("tr2_test_dir/f1", "tr2_test_dir/f1_link");
1711 ok(ret == ERROR_SUCCESS, "tr2_sys__Link(): expect: ERROR_SUCCESS, got %d\n", ret);
1713 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1714 errno = 0xdeadbeef;
1715 ret = p_tr2_sys__Unlink(tests[i].path);
1716 todo_wine_if(tests[i].is_todo)
1717 ok(ret == tests[i].last_error, "tr2_sys__Unlink(): test %d expect: %d, got %d\n",
1718 i+1, tests[i].last_error, ret);
1719 ok(errno == 0xdeadbeef, "tr2_sys__Unlink(): test %d errno expect: 0xdeadbeef, got %d\n", i+1, ret);
1722 ok(!DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 not to exist\n");
1723 ok(!DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link not to exist\n");
1724 ok(!DeleteFileA("tr2_test_dir/f1_symlink"), "expect tr2_test_dir/f1_symlink not to exist\n");
1725 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1726 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1728 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
1731 static int __cdecl thrd_thread(void *arg)
1733 _Thrd_t *thr = arg;
1735 if(thr)
1736 *thr = p__Thrd_current();
1737 return 0x42;
1740 static void test_thrd(void)
1742 int ret, i, r;
1743 struct test {
1744 _Thrd_t a;
1745 _Thrd_t b;
1746 int r;
1748 const HANDLE hnd1 = (HANDLE)0xcccccccc;
1749 const HANDLE hnd2 = (HANDLE)0xdeadbeef;
1750 xtime xt, before, after;
1751 MSVCRT_long diff;
1752 _Thrd_t ta, tb;
1754 struct test testeq[] = {
1755 { {0, 0}, {0, 0}, 1 },
1756 { {0, 1}, {0, 0}, 0 },
1757 { {hnd1, 0}, {hnd1, 1}, 0 },
1758 { {hnd1, 0}, {hnd2, 0}, 1 }
1761 struct test testlt[] = {
1762 { {0, 0}, {0, 0}, 0 },
1763 { {0, 0}, {0, 1}, 1 },
1764 { {0, 1}, {0, 0}, 0 },
1765 { {hnd1, 0}, {hnd2, 0}, 0 },
1766 { {hnd1, 0}, {hnd2, 1}, 1 }
1769 /* test for equal */
1770 for(i=0; i<sizeof(testeq)/sizeof(testeq[0]); i++) {
1771 ret = p__Thrd_equal(testeq[i].a, testeq[i].b);
1772 ok(ret == testeq[i].r, "(%p %u) = (%p %u) expected %d, got %d\n",
1773 testeq[i].a.hnd, testeq[i].a.id, testeq[i].b.hnd, testeq[i].b.id, testeq[i].r, ret);
1776 /* test for less than */
1777 for(i=0; i<sizeof(testlt)/sizeof(testlt[0]); i++) {
1778 ret = p__Thrd_lt(testlt[i].a, testlt[i].b);
1779 ok(ret == testlt[i].r, "(%p %u) < (%p %u) expected %d, got %d\n",
1780 testlt[i].a.hnd, testlt[i].a.id, testlt[i].b.hnd, testlt[i].b.id, testlt[i].r, ret);
1783 /* test for sleep */
1784 if (0) /* crash on Windows */
1785 p__Thrd_sleep(NULL);
1786 p_xtime_get(&xt, 1);
1787 xt.sec += 2;
1788 p_xtime_get(&before, 1);
1789 p__Thrd_sleep(&xt);
1790 p_xtime_get(&after, 1);
1791 diff = p__Xtime_diff_to_millis2(&after, &before);
1792 ok(diff > 2000 - TIMEDELTA, "got %d\n", diff);
1794 /* test for current */
1795 ta = p__Thrd_current();
1796 tb = p__Thrd_current();
1797 ok(ta.id == tb.id, "got a %d b %d\n", ta.id, tb.id);
1798 ok(ta.id == GetCurrentThreadId(), "expected %d, got %d\n", GetCurrentThreadId(), ta.id);
1799 /* these can be different if new threads are created at same time */
1800 ok(ta.hnd == tb.hnd, "got a %p b %p\n", ta.hnd, tb.hnd);
1801 ok(!CloseHandle(ta.hnd), "handle %p not closed\n", ta.hnd);
1802 ok(!CloseHandle(tb.hnd), "handle %p not closed\n", tb.hnd);
1804 /* test for create/join */
1805 if (0) /* crash on Windows */
1807 p__Thrd_create(NULL, thrd_thread, NULL);
1808 p__Thrd_create(&ta, NULL, NULL);
1810 r = -1;
1811 ret = p__Thrd_create(&ta, thrd_thread, (void*)&tb);
1812 ok(!ret, "failed to create thread, got %d\n", ret);
1813 ret = p__Thrd_join(ta, &r);
1814 ok(!ret, "failed to join thread, got %d\n", ret);
1815 ok(ta.id == tb.id, "expected %d, got %d\n", ta.id, tb.id);
1816 ok(ta.hnd != tb.hnd, "same handles, got %p\n", ta.hnd);
1817 ok(r == 0x42, "expected 0x42, got %d\n", r);
1818 ret = p__Thrd_detach(ta);
1819 ok(ret == 4, "_Thrd_detach should have failed with error 4, got %d\n", ret);
1821 ret = p__Thrd_create(&ta, thrd_thread, NULL);
1822 ok(!ret, "failed to create thread, got %d\n", ret);
1823 ret = p__Thrd_detach(ta);
1824 ok(!ret, "_Thrd_detach failed, got %d\n", ret);
1828 #define NUM_THREADS 10
1829 struct cndmtx
1831 HANDLE initialized;
1832 int started;
1833 int thread_no;
1835 _Cnd_t cnd;
1836 _Mtx_t mtx;
1837 BOOL timed_wait;
1840 static int __cdecl cnd_wait_thread(void *arg)
1842 struct cndmtx *cm = arg;
1843 int r;
1845 p__Mtx_lock(&cm->mtx);
1847 if(InterlockedIncrement(&cm->started) == cm->thread_no)
1848 SetEvent(cm->initialized);
1850 if(cm->timed_wait) {
1851 xtime xt;
1853 p_xtime_get(&xt, 1);
1854 xt.sec += 2;
1855 r = p__Cnd_timedwait(&cm->cnd, &cm->mtx, &xt);
1856 ok(!r, "timed wait failed\n");
1857 } else {
1858 r = p__Cnd_wait(&cm->cnd, &cm->mtx);
1859 ok(!r, "wait failed\n");
1862 p__Mtx_unlock(&cm->mtx);
1863 return 0;
1866 static void test_cnd(void)
1868 _Thrd_t threads[NUM_THREADS];
1869 xtime xt, before, after;
1870 MSVCRT_long diff;
1871 struct cndmtx cm;
1872 _Cnd_t cnd;
1873 _Mtx_t mtx;
1874 int r, i;
1876 r = p__Cnd_init(&cnd);
1877 ok(!r, "failed to init cnd\n");
1879 r = p__Mtx_init(&mtx, 0);
1880 ok(!r, "failed to init mtx\n");
1882 if (0) /* crash on Windows */
1884 p__Cnd_init(NULL);
1885 p__Cnd_wait(NULL, &mtx);
1886 p__Cnd_wait(&cnd, NULL);
1887 p__Cnd_timedwait(NULL, &mtx, &xt);
1888 p__Cnd_timedwait(&cnd, &mtx, &xt);
1890 p__Cnd_destroy(NULL);
1892 /* test _Cnd_signal/_Cnd_wait */
1893 cm.initialized = CreateEventW(NULL, FALSE, FALSE, NULL);
1894 cm.started = 0;
1895 cm.thread_no = 1;
1896 cm.cnd = cnd;
1897 cm.mtx = mtx;
1898 cm.timed_wait = FALSE;
1899 p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
1901 WaitForSingleObject(cm.initialized, INFINITE);
1902 p__Mtx_lock(&mtx);
1903 p__Mtx_unlock(&mtx);
1905 r = p__Cnd_signal(&cm.cnd);
1906 ok(!r, "failed to signal\n");
1907 p__Thrd_join(threads[0], NULL);
1909 /* test _Cnd_timedwait time out */
1910 p__Mtx_lock(&mtx);
1911 p_xtime_get(&before, 1);
1912 xt = before;
1913 xt.sec += 1;
1914 r = p__Cnd_timedwait(&cnd, &mtx, &xt);
1915 p_xtime_get(&after, 1);
1916 p__Mtx_unlock(&mtx);
1918 diff = p__Xtime_diff_to_millis2(&after, &before);
1919 ok(r == 2, "should have timed out\n");
1920 ok(diff > 1000 - TIMEDELTA, "got %d\n", diff);
1922 /* test _Cnd_timedwait */
1923 cm.started = 0;
1924 cm.timed_wait = TRUE;
1925 p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
1927 WaitForSingleObject(cm.initialized, INFINITE);
1928 p__Mtx_lock(&mtx);
1929 p__Mtx_unlock(&mtx);
1931 r = p__Cnd_signal(&cm.cnd);
1932 ok(!r, "failed to signal\n");
1933 p__Thrd_join(threads[0], NULL);
1935 /* test _Cnd_do_broadcast_at_thread_exit */
1936 cm.started = 0;
1937 cm.timed_wait = FALSE;
1938 p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
1940 WaitForSingleObject(cm.initialized, INFINITE);
1941 p__Mtx_lock(&mtx);
1943 r = 0xcafe;
1944 p__Cnd_unregister_at_thread_exit((_Mtx_t*)0xdeadbeef);
1945 p__Cnd_register_at_thread_exit(&cnd, &mtx, &r);
1946 ok(r == 0xcafe, "r = %x\n", r);
1947 p__Cnd_register_at_thread_exit(&cnd, &mtx, &r);
1948 p__Cnd_unregister_at_thread_exit(&mtx);
1949 p__Cnd_do_broadcast_at_thread_exit();
1950 ok(mtx->count == 1, "mtx.count = %d\n", mtx->count);
1952 p__Cnd_register_at_thread_exit(&cnd, &mtx, &r);
1953 ok(r == 0xcafe, "r = %x\n", r);
1955 p__Cnd_do_broadcast_at_thread_exit();
1956 ok(r == 1, "r = %x\n", r);
1957 p__Thrd_join(threads[0], NULL);
1959 /* crash if _Cnd_do_broadcast_at_thread_exit is called on exit */
1960 p__Cnd_register_at_thread_exit((_Cnd_t*)0xdeadbeef, (_Mtx_t*)0xdeadbeef, (int*)0xdeadbeef);
1962 /* test _Cnd_broadcast */
1963 cm.started = 0;
1964 cm.thread_no = NUM_THREADS;
1966 for(i = 0; i < cm.thread_no; i++)
1967 p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
1969 WaitForSingleObject(cm.initialized, INFINITE);
1970 p__Mtx_lock(&mtx);
1971 p__Mtx_unlock(&mtx);
1973 r = p__Cnd_broadcast(&cnd);
1974 ok(!r, "failed to broadcast\n");
1975 for(i = 0; i < cm.thread_no; i++)
1976 p__Thrd_join(threads[i], NULL);
1978 /* test broadcast with _Cnd_destroy */
1979 cm.started = 0;
1980 for(i = 0; i < cm.thread_no; i++)
1981 p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
1983 WaitForSingleObject(cm.initialized, INFINITE);
1984 p__Mtx_lock(&mtx);
1985 p__Mtx_unlock(&mtx);
1987 p__Cnd_destroy(&cnd);
1988 for(i = 0; i < cm.thread_no; i++)
1989 p__Thrd_join(threads[i], NULL);
1991 p__Mtx_destroy(&mtx);
1992 CloseHandle(cm.initialized);
1995 static struct {
1996 int value[2];
1997 const char* export_name;
1998 } vbtable_size_exports_list[] = {
1999 {{0x20, 0x20}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_istream@DU?$char_traits@D@std@@@1@@"},
2000 {{0x10, 0x10}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_ostream@DU?$char_traits@D@std@@@1@@"},
2001 {{0x20, 0x20}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_istream@GU?$char_traits@G@std@@@1@@"},
2002 {{0x10, 0x10}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_ostream@GU?$char_traits@G@std@@@1@@"},
2003 {{0x20, 0x20}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_istream@_WU?$char_traits@_W@std@@@1@@"},
2004 {{0x10, 0x10}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_ostream@_WU?$char_traits@_W@std@@@1@@"},
2005 {{0x18, 0x18}, "??_8?$basic_istream@DU?$char_traits@D@std@@@std@@7B@"},
2006 {{0x18, 0x18}, "??_8?$basic_istream@GU?$char_traits@G@std@@@std@@7B@"},
2007 {{0x18, 0x18}, "??_8?$basic_istream@_WU?$char_traits@_W@std@@@std@@7B@"},
2008 {{ 0x8, 0x10}, "??_8?$basic_ostream@DU?$char_traits@D@std@@@std@@7B@"},
2009 {{ 0x8, 0x10}, "??_8?$basic_ostream@GU?$char_traits@G@std@@@std@@7B@"},
2010 {{ 0x8, 0x10}, "??_8?$basic_ostream@_WU?$char_traits@_W@std@@@std@@7B@"},
2011 {{ 0x0, 0x0}, 0}
2014 static void test_vbtable_size_exports(void)
2016 int i;
2017 const int *p_vbtable;
2018 int arch_idx = (sizeof(void*) == 8);
2020 for (i = 0; vbtable_size_exports_list[i].export_name; i++)
2022 SET(p_vbtable, vbtable_size_exports_list[i].export_name);
2024 ok(p_vbtable[0] == 0, "vbtable[0] wrong, got 0x%x\n", p_vbtable[0]);
2025 ok(p_vbtable[1] == vbtable_size_exports_list[i].value[arch_idx],
2026 "%d: %s[1] wrong, got 0x%x\n", i, vbtable_size_exports_list[i].export_name, p_vbtable[1]);
2030 HANDLE _Pad__Launch_returned;
2031 _Pad pad;
2032 #ifdef __i386__
2033 /* TODO: this should be a __thiscall function */
2034 static unsigned int __stdcall vtbl_func__Go(void)
2035 #else
2036 static unsigned int __cdecl vtbl_func__Go(_Pad *this)
2037 #endif
2039 DWORD ret;
2041 ret = WaitForSingleObject(_Pad__Launch_returned, 100);
2042 ok(ret == WAIT_TIMEOUT, "WiatForSingleObject returned %x\n", ret);
2043 ok(!pad.mtx->count, "pad.mtx.count = %d\n", pad.mtx->count);
2044 ok(!pad.launched, "pad.launched = %x\n", pad.launched);
2045 call_func1(p__Pad__Release, &pad);
2046 ok(pad.launched, "pad.launched = %x\n", pad.launched);
2047 ret = WaitForSingleObject(_Pad__Launch_returned, 100);
2048 ok(ret == WAIT_OBJECT_0, "WiatForSingleObject returned %x\n", ret);
2049 ok(pad.mtx->count == 1, "pad.mtx.count = %d\n", pad.mtx->count);
2050 return 0;
2053 static void test__Pad(void)
2055 _Pad pad_copy;
2056 _Thrd_t thrd;
2057 vtable_ptr pfunc = (vtable_ptr)&vtbl_func__Go;
2059 _Pad__Launch_returned = CreateEventW(NULL, FALSE, FALSE, NULL);
2061 pad.vtable = (void*)1;
2062 pad.cnd = (void*)2;
2063 pad.mtx = (void*)3;
2064 pad.launched = TRUE;
2065 memset(&pad_copy, 0, sizeof(pad_copy));
2066 call_func2(p__Pad_copy_ctor, &pad_copy, &pad);
2067 ok(pad_copy.vtable != (void*)1, "pad_copy.vtable was not set\n");
2068 ok(pad_copy.cnd == (void*)2, "pad_copy.cnd = %p\n", pad_copy.cnd);
2069 ok(pad_copy.mtx == (void*)3, "pad_copy.mtx = %p\n", pad_copy.mtx);
2070 ok(pad_copy.launched, "pad_copy.launched = %x\n", pad_copy.launched);
2072 memset(&pad_copy, 0xde, sizeof(pad_copy));
2073 pad_copy.vtable = (void*)4;
2074 pad_copy.cnd = (void*)5;
2075 pad_copy.mtx = (void*)6;
2076 pad_copy.launched = FALSE;
2077 call_func2(p__Pad_op_assign, &pad_copy, &pad);
2078 ok(pad_copy.vtable == (void*)4, "pad_copy.vtable was set\n");
2079 ok(pad_copy.cnd == (void*)2, "pad_copy.cnd = %p\n", pad_copy.cnd);
2080 ok(pad_copy.mtx == (void*)3, "pad_copy.mtx = %p\n", pad_copy.mtx);
2081 ok(pad_copy.launched, "pad_copy.launched = %x\n", pad_copy.launched);
2083 call_func1(p__Pad_ctor, &pad);
2084 call_func2(p__Pad_copy_ctor, &pad_copy, &pad);
2085 ok(pad.vtable == pad_copy.vtable, "pad.vtable = %p, pad_copy.vtable = %p\n", pad.vtable, pad_copy.vtable);
2086 ok(pad.cnd == pad_copy.cnd, "pad.cnd = %p, pad_copy.cnd = %p\n", pad.cnd, pad_copy.cnd);
2087 ok(pad.mtx == pad_copy.mtx, "pad.mtx = %p, pad_copy.mtx = %p\n", pad.mtx, pad_copy.mtx);
2088 ok(pad.launched == pad_copy.launched, "pad.launched = %x, pad_copy.launched = %x\n", pad.launched, pad_copy.launched);
2089 call_func1(p__Pad_dtor, &pad);
2090 /* call_func1(p__Pad_dtor, &pad_copy); - copy constructor is broken, this causes a crash */
2092 memset(&pad, 0xfe, sizeof(pad));
2093 call_func1(p__Pad_ctor, &pad);
2094 ok(!pad.launched, "pad.launched = %x\n", pad.launched);
2095 ok(pad.mtx->count == 1, "pad.mtx.count = %d\n", pad.mtx->count);
2097 pad.vtable = &pfunc;
2098 call_func2(p__Pad__Launch, &pad, &thrd);
2099 SetEvent(_Pad__Launch_returned);
2100 ok(!p__Thrd_join(thrd, NULL), "_Thrd_join failed\n");
2102 call_func1(p__Pad_dtor, &pad);
2103 CloseHandle(_Pad__Launch_returned);
2106 static void test_threads__Mtx(void)
2108 void *mtx = NULL;
2110 p_threads__Mtx_new(&mtx);
2111 ok(mtx != NULL, "mtx == NULL\n");
2113 p_threads__Mtx_lock(mtx);
2114 p_threads__Mtx_lock(mtx);
2115 p_threads__Mtx_unlock(mtx);
2116 p_threads__Mtx_unlock(mtx);
2117 p_threads__Mtx_unlock(mtx);
2119 p_threads__Mtx_delete(mtx);
2122 static void test_vector_base_v4__Segment_index_of(void)
2124 size_t i;
2125 size_t ret;
2126 struct {
2127 size_t x;
2128 size_t expect;
2129 } tests[] = {
2130 {0, 0},
2131 {1, 0},
2132 {2, 1},
2133 {3, 1},
2134 {4, 2},
2135 {7, 2},
2136 {8, 3},
2137 {15, 3},
2138 {16, 4},
2139 {31, 4},
2140 {32, 5},
2141 {~0, 8*sizeof(void*)-1}
2144 for(i=0; i<sizeof(tests) / sizeof(tests[0]); i++) {
2145 ret = p_vector_base_v4__Segment_index_of(tests[i].x);
2146 ok(ret == tests[i].expect, "expected %ld, got %ld for %ld\n",
2147 (long)tests[i].expect, (long)ret, (long)tests[i].x);
2151 START_TEST(msvcp120)
2153 if(!init()) return;
2154 test__Xtime_diff_to_millis2();
2155 test_xtime_get();
2156 test__Getcvt();
2157 test__Call_once();
2158 test__Do_call();
2159 test__Dtest();
2160 test__Dscale();
2161 test__FExp();
2163 test_tr2_sys__File_size();
2164 test_tr2_sys__Equivalent();
2165 test_tr2_sys__Current_get();
2166 test_tr2_sys__Current_set();
2167 test_tr2_sys__Make_dir();
2168 test_tr2_sys__Remove_dir();
2169 test_tr2_sys__Copy_file();
2170 test_tr2_sys__Rename();
2171 test_tr2_sys__Statvfs();
2172 test_tr2_sys__Stat();
2173 test_tr2_sys__Last_write_time();
2174 test_tr2_sys__dir_operation();
2175 test_tr2_sys__Link();
2176 test_tr2_sys__Symlink();
2177 test_tr2_sys__Unlink();
2179 test_thrd();
2180 test_cnd();
2181 test__Pad();
2182 test_threads__Mtx();
2184 test_vector_base_v4__Segment_index_of();
2186 test_vbtable_size_exports();
2188 FreeLibrary(msvcp);