msvcp110: Add _Thrd_detach implementation.
[wine.git] / dlls / msvcp120 / tests / msvcp120.c
blob8c7c09336d7d75d7fb94caf52028f93fd36fe5a1
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 inline const char* debugstr_longlong(ULONGLONG ll)
135 static char string[17];
136 if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
137 sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
138 else
139 sprintf(string, "%lx", (unsigned long)ll);
140 return string;
143 static char* (__cdecl *p_setlocale)(int, const char*);
144 static int (__cdecl *p__setmbcp)(int);
145 static int (__cdecl *p_isleadbyte)(int);
147 static MSVCRT_long (__cdecl *p__Xtime_diff_to_millis2)(const xtime*, const xtime*);
148 static int (__cdecl *p_xtime_get)(xtime*, int);
149 static _Cvtvec* (__cdecl *p__Getcvt)(_Cvtvec*);
150 static void (CDECL *p__Call_once)(int *once, void (CDECL *func)(void));
151 static void (CDECL *p__Call_onceEx)(int *once, void (CDECL *func)(void*), void *argv);
152 static void (CDECL *p__Do_call)(void *this);
153 static short (__cdecl *p__Dtest)(double *d);
154 static short (__cdecl *p__Dscale)(double *d, int exp);
155 static short (__cdecl *p__FExp)(float *x, float y, int exp);
157 /* filesystem */
158 static ULONGLONG(__cdecl *p_tr2_sys__File_size)(char const*);
159 static ULONGLONG(__cdecl *p_tr2_sys__File_size_wchar)(WCHAR const*);
160 static int (__cdecl *p_tr2_sys__Equivalent)(char const*, char const*);
161 static int (__cdecl *p_tr2_sys__Equivalent_wchar)(WCHAR const*, WCHAR const*);
162 static char* (__cdecl *p_tr2_sys__Current_get)(char *);
163 static WCHAR* (__cdecl *p_tr2_sys__Current_get_wchar)(WCHAR *);
164 static MSVCP_bool (__cdecl *p_tr2_sys__Current_set)(char const*);
165 static MSVCP_bool (__cdecl *p_tr2_sys__Current_set_wchar)(WCHAR const*);
166 static int (__cdecl *p_tr2_sys__Make_dir)(char const*);
167 static int (__cdecl *p_tr2_sys__Make_dir_wchar)(WCHAR const*);
168 static MSVCP_bool (__cdecl *p_tr2_sys__Remove_dir)(char const*);
169 static MSVCP_bool (__cdecl *p_tr2_sys__Remove_dir_wchar)(WCHAR const*);
170 static int (__cdecl *p_tr2_sys__Copy_file)(char const*, char const*, MSVCP_bool);
171 static int (__cdecl *p_tr2_sys__Copy_file_wchar)(WCHAR const*, WCHAR const*, MSVCP_bool);
172 static int (__cdecl *p_tr2_sys__Rename)(char const*, char const*);
173 static int (__cdecl *p_tr2_sys__Rename_wchar)(WCHAR const*, WCHAR const*);
174 static struct space_info* (__cdecl *p_tr2_sys__Statvfs)(struct space_info*, char const*);
175 static struct space_info* (__cdecl *p_tr2_sys__Statvfs_wchar)(struct space_info*, WCHAR const*);
176 static enum file_type (__cdecl *p_tr2_sys__Stat)(char const*, int *);
177 static enum file_type (__cdecl *p_tr2_sys__Stat_wchar)(WCHAR const*, int *);
178 static enum file_type (__cdecl *p_tr2_sys__Lstat)(char const*, int *);
179 static enum file_type (__cdecl *p_tr2_sys__Lstat_wchar)(WCHAR const*, int *);
180 static __int64 (__cdecl *p_tr2_sys__Last_write_time)(char const*);
181 static void (__cdecl *p_tr2_sys__Last_write_time_set)(char const*, __int64);
182 static void* (__cdecl *p_tr2_sys__Open_dir)(char*, char const*, int *, enum file_type*);
183 static char* (__cdecl *p_tr2_sys__Read_dir)(char*, void*, enum file_type*);
184 static void (__cdecl *p_tr2_sys__Close_dir)(void*);
185 static int (__cdecl *p_tr2_sys__Link)(char const*, char const*);
186 static int (__cdecl *p_tr2_sys__Symlink)(char const*, char const*);
187 static int (__cdecl *p_tr2_sys__Unlink)(char const*);
189 /* thrd */
190 typedef struct
192 HANDLE hnd;
193 DWORD id;
194 } _Thrd_t;
196 #define TIMEDELTA 250 /* 250 ms uncertainty allowed */
198 typedef int (__cdecl *_Thrd_start_t)(void*);
200 static int (__cdecl *p__Thrd_equal)(_Thrd_t, _Thrd_t);
201 static int (__cdecl *p__Thrd_lt)(_Thrd_t, _Thrd_t);
202 static void (__cdecl *p__Thrd_sleep)(const xtime*);
203 static _Thrd_t (__cdecl *p__Thrd_current)(void);
204 static int (__cdecl *p__Thrd_create)(_Thrd_t*, _Thrd_start_t, void*);
205 static int (__cdecl *p__Thrd_join)(_Thrd_t, int*);
206 static int (__cdecl *p__Thrd_detach)(_Thrd_t);
208 #ifdef __i386__
209 static ULONGLONG (__cdecl *p_i386_Thrd_current)(void);
210 static _Thrd_t __cdecl i386_Thrd_current(void)
212 union {
213 _Thrd_t thr;
214 ULONGLONG ull;
215 } r;
216 r.ull = p_i386_Thrd_current();
217 return r.thr;
219 #endif
221 /* mtx */
222 typedef struct cs_queue
224 struct cs_queue *next;
225 BOOL free;
226 int unknown;
227 } cs_queue;
229 typedef struct
231 ULONG_PTR unk_thread_id;
232 cs_queue unk_active;
233 void *unknown[2];
234 cs_queue *head;
235 void *tail;
236 } critical_section;
238 typedef struct
240 DWORD flags;
241 critical_section cs;
242 DWORD thread_id;
243 DWORD count;
244 } *_Mtx_t;
246 static int (__cdecl *p__Mtx_init)(_Mtx_t*, int);
247 static void (__cdecl *p__Mtx_destroy)(_Mtx_t*);
248 static int (__cdecl *p__Mtx_lock)(_Mtx_t*);
249 static int (__cdecl *p__Mtx_unlock)(_Mtx_t*);
251 /* cnd */
252 typedef void *_Cnd_t;
254 static int (__cdecl *p__Cnd_init)(_Cnd_t*);
255 static void (__cdecl *p__Cnd_destroy)(_Cnd_t*);
256 static int (__cdecl *p__Cnd_wait)(_Cnd_t*, _Mtx_t*);
257 static int (__cdecl *p__Cnd_timedwait)(_Cnd_t*, _Mtx_t*, const xtime*);
258 static int (__cdecl *p__Cnd_broadcast)(_Cnd_t*);
259 static int (__cdecl *p__Cnd_signal)(_Cnd_t*);
261 /* _Pad */
262 typedef void (*vtable_ptr)(void);
264 typedef struct
266 const vtable_ptr *vtable;
267 _Cnd_t cnd;
268 _Mtx_t mtx;
269 MSVCP_bool launched;
270 } _Pad;
272 static _Pad* (__thiscall *p__Pad_ctor)(_Pad*);
273 static _Pad* (__thiscall *p__Pad_copy_ctor)(_Pad*, const _Pad*);
274 static void (__thiscall *p__Pad_dtor)(_Pad*);
275 static _Pad* (__thiscall *p__Pad_op_assign)(_Pad*, const _Pad*);
276 static void (__thiscall *p__Pad__Launch)(_Pad*, _Thrd_t*);
277 static void (__thiscall *p__Pad__Release)(_Pad*);
279 static HMODULE msvcp;
280 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
281 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
282 static BOOL init(void)
284 HANDLE msvcr;
286 msvcp = LoadLibraryA("msvcp120.dll");
287 if(!msvcp)
289 win_skip("msvcp120.dll not installed\n");
290 return FALSE;
293 SET(p__Xtime_diff_to_millis2,
294 "_Xtime_diff_to_millis2");
295 SET(p_xtime_get,
296 "xtime_get");
297 SET(p__Getcvt,
298 "_Getcvt");
299 SET(p__Call_once,
300 "_Call_once");
301 SET(p__Call_onceEx,
302 "_Call_onceEx");
303 SET(p__Do_call,
304 "_Do_call");
305 SET(p__Dtest,
306 "_Dtest");
307 SET(p__Dscale,
308 "_Dscale");
309 SET(p__FExp,
310 "_FExp");
311 if(sizeof(void*) == 8) { /* 64-bit initialization */
312 SET(p_tr2_sys__File_size,
313 "?_File_size@sys@tr2@std@@YA_KPEBD@Z");
314 SET(p_tr2_sys__File_size_wchar,
315 "?_File_size@sys@tr2@std@@YA_KPEB_W@Z");
316 SET(p_tr2_sys__Equivalent,
317 "?_Equivalent@sys@tr2@std@@YAHPEBD0@Z");
318 SET(p_tr2_sys__Equivalent_wchar,
319 "?_Equivalent@sys@tr2@std@@YAHPEB_W0@Z");
320 SET(p_tr2_sys__Current_get,
321 "?_Current_get@sys@tr2@std@@YAPEADAEAY0BAE@D@Z");
322 SET(p_tr2_sys__Current_get_wchar,
323 "?_Current_get@sys@tr2@std@@YAPEA_WAEAY0BAE@_W@Z");
324 SET(p_tr2_sys__Current_set,
325 "?_Current_set@sys@tr2@std@@YA_NPEBD@Z");
326 SET(p_tr2_sys__Current_set_wchar,
327 "?_Current_set@sys@tr2@std@@YA_NPEB_W@Z");
328 SET(p_tr2_sys__Make_dir,
329 "?_Make_dir@sys@tr2@std@@YAHPEBD@Z");
330 SET(p_tr2_sys__Make_dir_wchar,
331 "?_Make_dir@sys@tr2@std@@YAHPEB_W@Z");
332 SET(p_tr2_sys__Remove_dir,
333 "?_Remove_dir@sys@tr2@std@@YA_NPEBD@Z");
334 SET(p_tr2_sys__Remove_dir_wchar,
335 "?_Remove_dir@sys@tr2@std@@YA_NPEB_W@Z");
336 SET(p_tr2_sys__Copy_file,
337 "?_Copy_file@sys@tr2@std@@YAHPEBD0_N@Z");
338 SET(p_tr2_sys__Copy_file_wchar,
339 "?_Copy_file@sys@tr2@std@@YAHPEB_W0_N@Z");
340 SET(p_tr2_sys__Rename,
341 "?_Rename@sys@tr2@std@@YAHPEBD0@Z");
342 SET(p_tr2_sys__Rename_wchar,
343 "?_Rename@sys@tr2@std@@YAHPEB_W0@Z");
344 SET(p_tr2_sys__Statvfs,
345 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PEBD@Z");
346 SET(p_tr2_sys__Statvfs_wchar,
347 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PEB_W@Z");
348 SET(p_tr2_sys__Stat,
349 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PEBDAEAH@Z");
350 SET(p_tr2_sys__Stat_wchar,
351 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PEB_WAEAH@Z");
352 SET(p_tr2_sys__Lstat,
353 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PEBDAEAH@Z");
354 SET(p_tr2_sys__Lstat_wchar,
355 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PEB_WAEAH@Z");
356 SET(p_tr2_sys__Last_write_time,
357 "?_Last_write_time@sys@tr2@std@@YA_JPEBD@Z");
358 SET(p_tr2_sys__Last_write_time_set,
359 "?_Last_write_time@sys@tr2@std@@YAXPEBD_J@Z");
360 SET(p_tr2_sys__Open_dir,
361 "?_Open_dir@sys@tr2@std@@YAPEAXAEAY0BAE@DPEBDAEAHAEAW4file_type@123@@Z");
362 SET(p_tr2_sys__Read_dir,
363 "?_Read_dir@sys@tr2@std@@YAPEADAEAY0BAE@DPEAXAEAW4file_type@123@@Z");
364 SET(p_tr2_sys__Close_dir,
365 "?_Close_dir@sys@tr2@std@@YAXPEAX@Z");
366 SET(p_tr2_sys__Link,
367 "?_Link@sys@tr2@std@@YAHPEBD0@Z");
368 SET(p_tr2_sys__Symlink,
369 "?_Symlink@sys@tr2@std@@YAHPEBD0@Z");
370 SET(p_tr2_sys__Unlink,
371 "?_Unlink@sys@tr2@std@@YAHPEBD@Z");
372 SET(p__Thrd_current,
373 "_Thrd_current");
374 SET(p__Pad_ctor,
375 "??0_Pad@std@@QEAA@XZ");
376 SET(p__Pad_copy_ctor,
377 "??0_Pad@std@@QEAA@AEBV01@@Z");
378 SET(p__Pad_dtor,
379 "??1_Pad@std@@QEAA@XZ");
380 SET(p__Pad_op_assign,
381 "??4_Pad@std@@QEAAAEAV01@AEBV01@@Z");
382 SET(p__Pad__Launch,
383 "?_Launch@_Pad@std@@QEAAXPEAU_Thrd_imp_t@@@Z");
384 SET(p__Pad__Release,
385 "?_Release@_Pad@std@@QEAAXXZ");
386 } else {
387 SET(p_tr2_sys__File_size,
388 "?_File_size@sys@tr2@std@@YA_KPBD@Z");
389 SET(p_tr2_sys__File_size_wchar,
390 "?_File_size@sys@tr2@std@@YA_KPB_W@Z");
391 SET(p_tr2_sys__Equivalent,
392 "?_Equivalent@sys@tr2@std@@YAHPBD0@Z");
393 SET(p_tr2_sys__Equivalent_wchar,
394 "?_Equivalent@sys@tr2@std@@YAHPB_W0@Z");
395 SET(p_tr2_sys__Current_get,
396 "?_Current_get@sys@tr2@std@@YAPADAAY0BAE@D@Z");
397 SET(p_tr2_sys__Current_get_wchar,
398 "?_Current_get@sys@tr2@std@@YAPA_WAAY0BAE@_W@Z");
399 SET(p_tr2_sys__Current_set,
400 "?_Current_set@sys@tr2@std@@YA_NPBD@Z");
401 SET(p_tr2_sys__Current_set_wchar,
402 "?_Current_set@sys@tr2@std@@YA_NPB_W@Z");
403 SET(p_tr2_sys__Make_dir,
404 "?_Make_dir@sys@tr2@std@@YAHPBD@Z");
405 SET(p_tr2_sys__Make_dir_wchar,
406 "?_Make_dir@sys@tr2@std@@YAHPB_W@Z");
407 SET(p_tr2_sys__Remove_dir,
408 "?_Remove_dir@sys@tr2@std@@YA_NPBD@Z");
409 SET(p_tr2_sys__Remove_dir_wchar,
410 "?_Remove_dir@sys@tr2@std@@YA_NPB_W@Z");
411 SET(p_tr2_sys__Copy_file,
412 "?_Copy_file@sys@tr2@std@@YAHPBD0_N@Z");
413 SET(p_tr2_sys__Copy_file_wchar,
414 "?_Copy_file@sys@tr2@std@@YAHPB_W0_N@Z");
415 SET(p_tr2_sys__Rename,
416 "?_Rename@sys@tr2@std@@YAHPBD0@Z");
417 SET(p_tr2_sys__Rename_wchar,
418 "?_Rename@sys@tr2@std@@YAHPB_W0@Z");
419 SET(p_tr2_sys__Statvfs,
420 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PBD@Z");
421 SET(p_tr2_sys__Statvfs_wchar,
422 "?_Statvfs@sys@tr2@std@@YA?AUspace_info@123@PB_W@Z");
423 SET(p_tr2_sys__Stat,
424 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PBDAAH@Z");
425 SET(p_tr2_sys__Stat_wchar,
426 "?_Stat@sys@tr2@std@@YA?AW4file_type@123@PB_WAAH@Z");
427 SET(p_tr2_sys__Lstat,
428 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PBDAAH@Z");
429 SET(p_tr2_sys__Lstat_wchar,
430 "?_Lstat@sys@tr2@std@@YA?AW4file_type@123@PB_WAAH@Z");
431 SET(p_tr2_sys__Last_write_time,
432 "?_Last_write_time@sys@tr2@std@@YA_JPBD@Z");
433 SET(p_tr2_sys__Last_write_time_set,
434 "?_Last_write_time@sys@tr2@std@@YAXPBD_J@Z");
435 SET(p_tr2_sys__Open_dir,
436 "?_Open_dir@sys@tr2@std@@YAPAXAAY0BAE@DPBDAAHAAW4file_type@123@@Z");
437 SET(p_tr2_sys__Read_dir,
438 "?_Read_dir@sys@tr2@std@@YAPADAAY0BAE@DPAXAAW4file_type@123@@Z");
439 SET(p_tr2_sys__Close_dir,
440 "?_Close_dir@sys@tr2@std@@YAXPAX@Z");
441 SET(p_tr2_sys__Link,
442 "?_Link@sys@tr2@std@@YAHPBD0@Z");
443 SET(p_tr2_sys__Symlink,
444 "?_Symlink@sys@tr2@std@@YAHPBD0@Z");
445 SET(p_tr2_sys__Unlink,
446 "?_Unlink@sys@tr2@std@@YAHPBD@Z");
447 #ifdef __i386__
448 SET(p_i386_Thrd_current,
449 "_Thrd_current");
450 p__Thrd_current = i386_Thrd_current;
451 SET(p__Pad_ctor,
452 "??0_Pad@std@@QAE@XZ");
453 SET(p__Pad_copy_ctor,
454 "??0_Pad@std@@QAE@ABV01@@Z");
455 SET(p__Pad_dtor,
456 "??1_Pad@std@@QAE@XZ");
457 SET(p__Pad_op_assign,
458 "??4_Pad@std@@QAEAAV01@ABV01@@Z");
459 SET(p__Pad__Launch,
460 "?_Launch@_Pad@std@@QAEXPAU_Thrd_imp_t@@@Z");
461 SET(p__Pad__Release,
462 "?_Release@_Pad@std@@QAEXXZ");
463 #else
464 SET(p__Thrd_current,
465 "_Thrd_current");
466 SET(p__Pad_ctor,
467 "??0_Pad@std@@QAA@XZ");
468 SET(p__Pad_copy_ctor,
469 "??0_Pad@std@@QAA@ABV01@@Z");
470 SET(p__Pad_dtor,
471 "??1_Pad@std@@QAA@XZ");
472 SET(p__Pad_op_assign,
473 "??4_Pad@std@@QAAAAV01@ABV01@@Z");
474 SET(p__Pad__Launch,
475 "?_Launch@_Pad@std@@QAAXPAU_Thrd_imp_t@@@Z");
476 SET(p__Pad__Release,
477 "?_Release@_Pad@std@@QAAXXZ");
478 #endif
480 SET(p__Thrd_equal,
481 "_Thrd_equal");
482 SET(p__Thrd_lt,
483 "_Thrd_lt");
484 SET(p__Thrd_sleep,
485 "_Thrd_sleep");
486 SET(p__Thrd_create,
487 "_Thrd_create");
488 SET(p__Thrd_join,
489 "_Thrd_join");
490 SET(p__Thrd_detach,
491 "_Thrd_detach");
493 SET(p__Mtx_init,
494 "_Mtx_init");
495 SET(p__Mtx_destroy,
496 "_Mtx_destroy");
497 SET(p__Mtx_lock,
498 "_Mtx_lock");
499 SET(p__Mtx_unlock,
500 "_Mtx_unlock");
502 SET(p__Cnd_init,
503 "_Cnd_init");
504 SET(p__Cnd_destroy,
505 "_Cnd_destroy");
506 SET(p__Cnd_wait,
507 "_Cnd_wait");
508 SET(p__Cnd_timedwait,
509 "_Cnd_timedwait");
510 SET(p__Cnd_broadcast,
511 "_Cnd_broadcast");
512 SET(p__Cnd_signal,
513 "_Cnd_signal");
515 msvcr = GetModuleHandleA("msvcr120.dll");
516 p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
517 p__setmbcp = (void*)GetProcAddress(msvcr, "_setmbcp");
518 p_isleadbyte = (void*)GetProcAddress(msvcr, "isleadbyte");
520 init_thiscall_thunk();
521 return TRUE;
524 static void test__Xtime_diff_to_millis2(void)
526 struct {
527 __time64_t sec_before;
528 MSVCRT_long nsec_before;
529 __time64_t sec_after;
530 MSVCRT_long nsec_after;
531 MSVCRT_long expect;
532 } tests[] = {
533 {1, 0, 2, 0, 1000},
534 {0, 1000000000, 0, 2000000000, 1000},
535 {1, 100000000, 2, 100000000, 1000},
536 {1, 100000000, 1, 200000000, 100},
537 {0, 0, 0, 1000000000, 1000},
538 {0, 0, 0, 1200000000, 1200},
539 {0, 0, 0, 1230000000, 1230},
540 {0, 0, 0, 1234000000, 1234},
541 {0, 0, 0, 1234100000, 1235},
542 {0, 0, 0, 1234900000, 1235},
543 {0, 0, 0, 1234010000, 1235},
544 {0, 0, 0, 1234090000, 1235},
545 {0, 0, 0, 1234000001, 1235},
546 {0, 0, 0, 1234000009, 1235},
547 {0, 0, -1, 0, 0},
548 {0, 0, 0, -10000000, 0},
549 {0, 0, -1, -100000000, 0},
550 {-1, 0, 0, 0, 1000},
551 {0, -100000000, 0, 0, 100},
552 {-1, -100000000, 0, 0, 1100},
553 {0, 0, -1, 2000000000, 1000},
554 {0, 0, -2, 2000000000, 0},
555 {0, 0, -2, 2100000000, 100}
557 int i;
558 MSVCRT_long ret;
559 xtime t1, t2;
561 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); ++ i)
563 t1.sec = tests[i].sec_before;
564 t1.nsec = tests[i].nsec_before;
565 t2.sec = tests[i].sec_after;
566 t2.nsec = tests[i].nsec_after;
567 ret = p__Xtime_diff_to_millis2(&t2, &t1);
568 ok(ret == tests[i].expect,
569 "_Xtime_diff_to_millis2(): test: %d expect: %d, got: %d\n",
570 i, tests[i].expect, ret);
574 static void test_xtime_get(void)
576 static const MSVCRT_long tests[] = {1, 50, 100, 200, 500};
577 MSVCRT_long diff;
578 xtime before, after;
579 int i;
581 for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i ++)
583 p_xtime_get(&before, 1);
584 Sleep(tests[i]);
585 p_xtime_get(&after, 1);
587 diff = p__Xtime_diff_to_millis2(&after, &before);
589 ok(diff >= tests[i],
590 "xtime_get() not functioning correctly, test: %d, expect: ge %d, got: %d\n",
591 i, tests[i], diff);
594 /* Test parameter and return value */
595 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
596 i = p_xtime_get(&before, 0);
597 ok(i == 0, "expect xtime_get() to return 0, got: %d\n", i);
598 ok(before.sec == 0xdeadbeef && before.nsec == 0xdeadbeef,
599 "xtime_get() shouldn't have modified the xtime struct with the given option\n");
601 before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef;
602 i = p_xtime_get(&before, 1);
603 ok(i == 1, "expect xtime_get() to return 1, got: %d\n", i);
604 ok(before.sec != 0xdeadbeef && before.nsec != 0xdeadbeef,
605 "xtime_get() should have modified the xtime struct with the given option\n");
608 static void test__Getcvt(void)
610 _Cvtvec cvtvec;
611 int i;
613 p__Getcvt(&cvtvec);
614 ok(cvtvec.page == 0, "cvtvec.page = %d\n", cvtvec.page);
615 ok(cvtvec.mb_max == 1, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
616 todo_wine ok(cvtvec.unk == 1, "cvtvec.unk = %d\n", cvtvec.unk);
617 for(i=0; i<32; i++)
618 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
620 if(!p_setlocale(LC_ALL, ".936")) {
621 win_skip("_Getcvt tests\n");
622 return;
624 p__Getcvt(&cvtvec);
625 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
626 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
627 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
628 for(i=0; i<32; i++)
629 ok(cvtvec.isleadbyte[i] == 0, "cvtvec.isleadbyte[%d] = %x\n", i, cvtvec.isleadbyte[i]);
631 p__setmbcp(936);
632 p__Getcvt(&cvtvec);
633 ok(cvtvec.page == 936, "cvtvec.page = %d\n", cvtvec.page);
634 ok(cvtvec.mb_max == 2, "cvtvec.mb_max = %d\n", cvtvec.mb_max);
635 ok(cvtvec.unk == 0, "cvtvec.unk = %d\n", cvtvec.unk);
636 for(i=0; i<32; i++) {
637 BYTE b = 0;
638 int j;
640 for(j=0; j<8; j++)
641 b |= (p_isleadbyte(i*8+j) ? 1 : 0) << j;
642 ok(cvtvec.isleadbyte[i] ==b, "cvtvec.isleadbyte[%d] = %x (%x)\n", i, cvtvec.isleadbyte[i], b);
646 static int cnt;
647 static int once;
649 static void __cdecl call_once_func(void)
651 ok(!once, "once != 0\n");
652 cnt += 0x10000;
655 static void __cdecl call_once_ex_func(void *arg)
657 int *i = arg;
659 ok(!once, "once != 0\n");
660 (*i)++;
663 static DWORD WINAPI call_once_thread(void *arg)
665 p__Call_once(&once, call_once_func);
666 return 0;
669 static DWORD WINAPI call_once_ex_thread(void *arg)
671 p__Call_onceEx(&once, call_once_ex_func, &cnt);
672 return 0;
675 static void test__Call_once(void)
677 HANDLE h[4];
678 int i;
680 for(i=0; i<4; i++)
681 h[i] = CreateThread(NULL, 0, call_once_thread, &once, 0, NULL);
682 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
683 "error waiting for all threads to finish\n");
684 ok(cnt == 0x10000, "cnt = %x\n", cnt);
685 ok(once == 1, "once = %x\n", once);
687 once = cnt = 0;
688 for(i=0; i<4; i++)
689 h[i] = CreateThread(NULL, 0, call_once_ex_thread, &once, 0, NULL);
690 ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
691 "error waiting for all threads to finish\n");
692 ok(cnt == 1, "cnt = %x\n", cnt);
693 ok(once == 1, "once = %x\n", once);
696 static void **vtbl_func0;
697 #ifdef __i386__
698 /* TODO: this should be a __thiscall function */
699 static void __stdcall thiscall_func(void)
701 cnt = 1;
703 #else
704 static void __cdecl thiscall_func(void *this)
706 ok(this == &vtbl_func0, "incorrect this value\n");
707 cnt = 1;
709 #endif
711 static void test__Do_call(void)
713 void *pfunc = thiscall_func;
715 cnt = 0;
716 vtbl_func0 = &pfunc;
717 p__Do_call(&vtbl_func0);
718 ok(cnt == 1, "func was not called\n");
721 static void test__Dtest(void)
723 double d;
724 short ret;
726 d = 0;
727 ret = p__Dtest(&d);
728 ok(ret == FP_ZERO, "_Dtest(0) returned %x\n", ret);
730 d = 1;
731 ret = p__Dtest(&d);
732 ok(ret == FP_NORMAL, "_Dtest(1) returned %x\n", ret);
734 d = -1;
735 ret = p__Dtest(&d);
736 ok(ret == FP_NORMAL, "_Dtest(-1) returned %x\n", ret);
738 d = INFINITY;
739 ret = p__Dtest(&d);
740 ok(ret == FP_INFINITE, "_Dtest(INF) returned %x\n", ret);
742 d = NAN;
743 ret = p__Dtest(&d);
744 ok(ret == FP_NAN, "_Dtest(NAN) returned %x\n", ret);
747 static void test__Dscale(void)
749 double d;
750 short ret;
752 d = 0;
753 ret = p__Dscale(&d, 0);
754 ok(d == 0, "d = %f\n", d);
755 ok(ret == FP_ZERO, "ret = %x\n", ret);
757 d = 0;
758 ret = p__Dscale(&d, 1);
759 ok(d == 0, "d = %f\n", d);
760 ok(ret == FP_ZERO, "ret = %x\n", ret);
762 d = 0;
763 ret = p__Dscale(&d, -1);
764 ok(d == 0, "d = %f\n", d);
765 ok(ret == FP_ZERO, "ret = %x\n", ret);
767 d = 1;
768 ret = p__Dscale(&d, 0);
769 ok(d == 1, "d = %f\n", d);
770 ok(ret == FP_NORMAL, "ret = %x\n", ret);
772 d = 1;
773 ret = p__Dscale(&d, 1);
774 ok(d == 2, "d = %f\n", d);
775 ok(ret == FP_NORMAL, "ret = %x\n", ret);
777 d = 1;
778 ret = p__Dscale(&d, -1);
779 ok(d == 0.5, "d = %f\n", d);
780 ok(ret == FP_NORMAL, "ret = %x\n", ret);
782 d = 1;
783 ret = p__Dscale(&d, -99999);
784 ok(d == 0, "d = %f\n", d);
785 ok(ret == FP_ZERO, "ret = %x\n", ret);
787 d = 1;
788 ret = p__Dscale(&d, 999999);
789 ok(d == INFINITY, "d = %f\n", d);
790 ok(ret == FP_INFINITE, "ret = %x\n", ret);
792 d = NAN;
793 ret = p__Dscale(&d, 1);
794 ok(ret == FP_NAN, "ret = %x\n", ret);
797 static void test__FExp(void)
799 float d;
800 short ret;
802 d = 0;
803 ret = p__FExp(&d, 0, 0);
804 ok(d == 0, "d = %f\n", d);
805 ok(ret == FP_ZERO, "ret = %x\n", ret);
807 d = 0;
808 ret = p__FExp(&d, 1, 0);
809 ok(d == 1.0, "d = %f\n", d);
810 ok(ret == FP_NORMAL, "ret = %x\n", ret);
812 d = 0;
813 ret = p__FExp(&d, 1, 1);
814 ok(d == 2.0, "d = %f\n", d);
815 ok(ret == FP_NORMAL, "ret = %x\n", ret);
817 d = 0;
818 ret = p__FExp(&d, 1, 2);
819 ok(d == 4.0, "d = %f\n", d);
820 ok(ret == FP_NORMAL, "ret = %x\n", ret);
822 d = 0;
823 ret = p__FExp(&d, 10, 0);
824 ok(d == 10.0, "d = %f\n", d);
825 ok(ret == FP_NORMAL, "ret = %x\n", ret);
827 d = 1;
828 ret = p__FExp(&d, 0, 0);
829 ok(d == 0, "d = %f\n", d);
830 ok(ret == FP_ZERO, "ret = %x\n", ret);
832 d = 1;
833 ret = p__FExp(&d, 1, 0);
834 ok(compare_float(d, 2.7182817, 4), "d = %f\n", d);
835 ok(ret == FP_NORMAL, "ret = %x\n", ret);
837 d = 9e20;
838 ret = p__FExp(&d, 0, 0);
839 ok(d == 0, "d = %f\n", d);
840 ok(ret == FP_ZERO, "ret = %x\n", ret);
842 d = 90;
843 ret = p__FExp(&d, 1, 0);
844 ok(ret == FP_INFINITE, "ret = %x\n", ret);
846 d = 90;
847 ret = p__FExp(&d, 1, -50);
848 ok(compare_float(d, 1.0839359e+024, 4), "d = %g\n", d);
849 ok(ret == FP_NORMAL, "ret = %x\n", ret);
852 static void test_tr2_sys__File_size(void)
854 ULONGLONG val;
855 HANDLE file;
856 LARGE_INTEGER file_size;
857 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
858 CreateDirectoryA("tr2_test_dir", NULL);
860 file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
861 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
862 file_size.QuadPart = 7;
863 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
864 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
865 CloseHandle(file);
866 val = p_tr2_sys__File_size("tr2_test_dir/f1");
867 ok(val == 7, "file_size is %s\n", debugstr_longlong(val));
868 val = p_tr2_sys__File_size_wchar(testW);
869 ok(val == 7, "file_size is %s\n", debugstr_longlong(val));
871 file = CreateFileA("tr2_test_dir/f2", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
872 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
873 CloseHandle(file);
874 val = p_tr2_sys__File_size("tr2_test_dir/f2");
875 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
877 val = p_tr2_sys__File_size("tr2_test_dir");
878 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
880 errno = 0xdeadbeef;
881 val = p_tr2_sys__File_size("tr2_test_dir/not_exists_file");
882 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
883 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
885 errno = 0xdeadbeef;
886 val = p_tr2_sys__File_size(NULL);
887 ok(val == 0, "file_size is %s\n", debugstr_longlong(val));
888 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
890 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
891 ok(DeleteFileA("tr2_test_dir/f2"), "expect tr2_test_dir/f2 to exist\n");
892 ok(p_tr2_sys__Remove_dir("tr2_test_dir"), "expect tr2_test_dir to exist\n");
895 static void test_tr2_sys__Equivalent(void)
897 int val, i;
898 HANDLE file;
899 char temp_path[MAX_PATH], current_path[MAX_PATH];
900 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
901 WCHAR testW2[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','2',0};
902 struct {
903 char const *path1;
904 char const *path2;
905 int equivalent;
906 } tests[] = {
907 { NULL, NULL, -1 },
908 { NULL, "f1", -1 },
909 { "f1", NULL, -1 },
910 { "f1", "tr2_test_dir", -1 },
911 { "tr2_test_dir", "f1", -1 },
912 { "tr2_test_dir", "tr2_test_dir", -1 },
913 { "tr2_test_dir/./f1", "tr2_test_dir/f2", 0 },
914 { "tr2_test_dir/f1" , "tr2_test_dir/f1", 1 },
915 { "not_exists_file" , "tr2_test_dir/f1", 0 },
916 { "tr2_test_dir\\f1" , "tr2_test_dir/./f1", 1 },
917 { "not_exists_file" , "not_exists_file", -1 },
918 { "tr2_test_dir/f1" , "not_exists_file", 0 },
919 { "tr2_test_dir/../tr2_test_dir/f1", "tr2_test_dir/f1", 1 }
922 memset(current_path, 0, MAX_PATH);
923 GetCurrentDirectoryA(MAX_PATH, current_path);
924 memset(temp_path, 0, MAX_PATH);
925 GetTempPathA(MAX_PATH, temp_path);
926 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
927 CreateDirectoryA("tr2_test_dir", NULL);
929 file = CreateFileA("tr2_test_dir/f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
930 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
931 CloseHandle(file);
932 file = CreateFileA("tr2_test_dir/f2", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
933 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
934 CloseHandle(file);
936 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
937 errno = 0xdeadbeef;
938 val = p_tr2_sys__Equivalent(tests[i].path1, tests[i].path2);
939 ok(tests[i].equivalent == val, "tr2_sys__Equivalent(): test %d expect: %d, got %d\n", i+1, tests[i].equivalent, val);
940 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
943 val = p_tr2_sys__Equivalent_wchar(testW, testW);
944 ok(val == 1, "tr2_sys__Equivalent(): expect: 1, got %d\n", val);
945 val = p_tr2_sys__Equivalent_wchar(testW, testW2);
946 ok(val == 0, "tr2_sys__Equivalent(): expect: 0, got %d\n", val);
948 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
949 ok(DeleteFileA("tr2_test_dir/f2"), "expect tr2_test_dir/f2 to exist\n");
950 ok(p_tr2_sys__Remove_dir("tr2_test_dir"), "expect tr2_test_dir to exist\n");
951 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
954 static void test_tr2_sys__Current_get(void)
956 char temp_path[MAX_PATH], current_path[MAX_PATH], origin_path[MAX_PATH];
957 char *temp;
958 WCHAR temp_path_wchar[MAX_PATH], current_path_wchar[MAX_PATH];
959 WCHAR *temp_wchar;
960 memset(origin_path, 0, MAX_PATH);
961 GetCurrentDirectoryA(MAX_PATH, origin_path);
962 memset(temp_path, 0, MAX_PATH);
963 GetTempPathA(MAX_PATH, temp_path);
965 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
966 memset(current_path, 0, MAX_PATH);
967 temp = p_tr2_sys__Current_get(current_path);
968 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
969 temp[strlen(temp)] = '\\';
970 ok(!strcmp(temp_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", temp_path, current_path);
972 GetTempPathW(MAX_PATH, temp_path_wchar);
973 ok(SetCurrentDirectoryW(temp_path_wchar), "SetCurrentDirectoryW to temp_path_wchar failed\n");
974 memset(current_path_wchar, 0, MAX_PATH);
975 temp_wchar = p_tr2_sys__Current_get_wchar(current_path_wchar);
976 ok(temp_wchar == current_path_wchar, "p_tr2_sys__Current_get_wchar returned different buffer\n");
977 temp_wchar[wcslen(temp_wchar)] = '\\';
978 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));
980 ok(SetCurrentDirectoryA(origin_path), "SetCurrentDirectoryA to origin_path failed\n");
981 memset(current_path, 0, MAX_PATH);
982 temp = p_tr2_sys__Current_get(current_path);
983 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
984 ok(!strcmp(origin_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", origin_path, current_path);
987 static void test_tr2_sys__Current_set(void)
989 char temp_path[MAX_PATH], current_path[MAX_PATH], origin_path[MAX_PATH];
990 char *temp;
991 WCHAR testW[] = {'.','/',0};
992 memset(temp_path, 0, MAX_PATH);
993 GetTempPathA(MAX_PATH, temp_path);
994 memset(origin_path, 0, MAX_PATH);
995 GetCurrentDirectoryA(MAX_PATH, origin_path);
996 temp = p_tr2_sys__Current_get(origin_path);
997 ok(temp == origin_path, "p_tr2_sys__Current_get returned different buffer\n");
999 ok(p_tr2_sys__Current_set(temp_path), "p_tr2_sys__Current_set to temp_path failed\n");
1000 memset(current_path, 0, MAX_PATH);
1001 temp = p_tr2_sys__Current_get(current_path);
1002 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1003 temp[strlen(temp)] = '\\';
1004 ok(!strcmp(temp_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", temp_path, current_path);
1006 ok(p_tr2_sys__Current_set_wchar(testW), "p_tr2_sys__Current_set_wchar to temp_path failed\n");
1007 memset(current_path, 0, MAX_PATH);
1008 temp = p_tr2_sys__Current_get(current_path);
1009 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1010 temp[strlen(temp)] = '\\';
1011 ok(!strcmp(temp_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", temp_path, current_path);
1013 errno = 0xdeadbeef;
1014 ok(!p_tr2_sys__Current_set("not_exisist_dir"), "p_tr2_sys__Current_set to not_exist_dir succeed\n");
1015 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
1017 errno = 0xdeadbeef;
1018 ok(!p_tr2_sys__Current_set("??invalid_name>>"), "p_tr2_sys__Current_set to ??invalid_name>> succeed\n");
1019 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
1021 ok(p_tr2_sys__Current_set(origin_path), "p_tr2_sys__Current_set to origin_path failed\n");
1022 memset(current_path, 0, MAX_PATH);
1023 temp = p_tr2_sys__Current_get(current_path);
1024 ok(temp == current_path, "p_tr2_sys__Current_get returned different buffer\n");
1025 ok(!strcmp(origin_path, current_path), "test_tr2_sys__Current_get(): expect: %s, got %s\n", origin_path, current_path);
1028 static void test_tr2_sys__Make_dir(void)
1030 int ret, i;
1031 WCHAR testW[] = {'w','d',0};
1032 struct {
1033 char const *path;
1034 int val;
1035 } tests[] = {
1036 { "tr2_test_dir", 1 },
1037 { "tr2_test_dir", 0 },
1038 { NULL, -1 },
1039 { "??invalid_name>>", -1 }
1042 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1043 errno = 0xdeadbeef;
1044 ret = p_tr2_sys__Make_dir(tests[i].path);
1045 ok(ret == tests[i].val, "tr2_sys__Make_dir(): test %d expect: %d, got %d\n", i+1, tests[i].val, ret);
1046 ok(errno == 0xdeadbeef, "tr2_sys__Make_dir(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1048 ret = p_tr2_sys__Make_dir_wchar(testW);
1049 ok(ret == 1, "tr2_sys__Make_dir(): expect: 1, got %d\n", ret);
1051 ok(p_tr2_sys__Remove_dir("tr2_test_dir"), "expect tr2_test_dir to exist\n");
1052 ok(p_tr2_sys__Remove_dir_wchar(testW), "expect wd to exist\n");
1055 static void test_tr2_sys__Remove_dir(void)
1057 MSVCP_bool ret;
1058 int i;
1059 struct {
1060 char const *path;
1061 MSVCP_bool val;
1062 } tests[] = {
1063 { "tr2_test_dir", TRUE },
1064 { "tr2_test_dir", FALSE },
1065 { NULL, FALSE },
1066 { "??invalid_name>>", FALSE }
1069 ok(p_tr2_sys__Make_dir("tr2_test_dir"), "tr2_sys__Make_dir() failed\n");
1071 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1072 errno = 0xdeadbeef;
1073 ret = p_tr2_sys__Remove_dir(tests[i].path);
1074 ok(ret == tests[i].val, "test_tr2_sys__Remove_dir(): test %d expect: %d, got %d\n", i+1, tests[i].val, ret);
1075 ok(errno == 0xdeadbeef, "test_tr2_sys__Remove_dir(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1079 static void test_tr2_sys__Copy_file(void)
1081 HANDLE file;
1082 int ret, i;
1083 LARGE_INTEGER file_size;
1084 WCHAR testW[] = {'f','1',0}, testW2[] = {'f','w',0};
1085 struct {
1086 char const *source;
1087 char const *dest;
1088 MSVCP_bool fail_if_exists;
1089 int last_error;
1090 int last_error2;
1091 MSVCP_bool is_todo;
1092 } tests[] = {
1093 { "f1", "f1_copy", TRUE, ERROR_SUCCESS, ERROR_SUCCESS, FALSE },
1094 { "f1", "tr2_test_dir\\f1_copy", TRUE, ERROR_SUCCESS, ERROR_SUCCESS, FALSE },
1095 { "f1", "tr2_test_dir\\f1_copy", TRUE, ERROR_FILE_EXISTS, ERROR_FILE_EXISTS, FALSE },
1096 { "f1", "tr2_test_dir\\f1_copy", FALSE, ERROR_SUCCESS, ERROR_SUCCESS, FALSE },
1097 { "tr2_test_dir", "f1", TRUE, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED, FALSE },
1098 { "tr2_test_dir", "tr2_test_dir_copy", TRUE, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED, FALSE },
1099 { NULL, "f1", TRUE, ERROR_INVALID_PARAMETER, ERROR_INVALID_PARAMETER, TRUE },
1100 { "f1", NULL, TRUE, ERROR_INVALID_PARAMETER, ERROR_INVALID_PARAMETER, TRUE },
1101 { "not_exist", "tr2_test_dir", TRUE, ERROR_FILE_NOT_FOUND, ERROR_FILE_NOT_FOUND, FALSE },
1102 { "f1", "not_exist_dir\\f1_copy", TRUE, ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND, FALSE },
1103 { "f1", "tr2_test_dir", TRUE, ERROR_ACCESS_DENIED, ERROR_FILE_EXISTS, FALSE }
1106 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1107 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1108 file = CreateFileA("f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1109 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1110 file_size.QuadPart = 7;
1111 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1112 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1113 CloseHandle(file);
1115 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1116 errno = 0xdeadbeef;
1117 ret = p_tr2_sys__Copy_file(tests[i].source, tests[i].dest, tests[i].fail_if_exists);
1118 todo_wine_if(tests[i].is_todo)
1119 ok(ret == tests[i].last_error || ret == tests[i].last_error2,
1120 "test_tr2_sys__Copy_file(): test %d expect: %d, got %d\n", i+1, tests[i].last_error, ret);
1121 ok(errno == 0xdeadbeef, "test_tr2_sys__Copy_file(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1122 if(ret == ERROR_SUCCESS)
1123 ok(p_tr2_sys__File_size(tests[i].source) == p_tr2_sys__File_size(tests[i].dest),
1124 "test_tr2_sys__Copy_file(): test %d failed, two files' size are not equal\n", i+1);
1126 ret = p_tr2_sys__Copy_file_wchar(testW, testW2, TRUE);
1127 ok(ret == ERROR_SUCCESS, "test_tr2_sys__Copy_file_wchar() expect ERROR_SUCCESS, got %d\n", ret);
1129 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1130 ok(DeleteFileW(testW2), "expect fw to exist\n");
1131 ok(DeleteFileA("f1_copy"), "expect f1_copy to exist\n");
1132 ok(DeleteFileA("tr2_test_dir/f1_copy"), "expect tr2_test_dir/f1 to exist\n");
1133 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1134 ok(ret == 1, "test_tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1137 static void test_tr2_sys__Rename(void)
1139 int ret, i;
1140 HANDLE file, h1, h2;
1141 BY_HANDLE_FILE_INFORMATION info1, info2;
1142 char temp_path[MAX_PATH], current_path[MAX_PATH];
1143 LARGE_INTEGER file_size;
1144 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
1145 WCHAR testW2[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','w',0};
1146 struct {
1147 char const *old_path;
1148 char const *new_path;
1149 int val;
1150 } tests[] = {
1151 { "tr2_test_dir\\f1", "tr2_test_dir\\f1_rename", ERROR_SUCCESS },
1152 { "tr2_test_dir\\f1", NULL, ERROR_INVALID_PARAMETER },
1153 { "tr2_test_dir\\f1", "tr2_test_dir\\f1_rename", ERROR_FILE_NOT_FOUND },
1154 { NULL, "tr2_test_dir\\NULL_rename", ERROR_INVALID_PARAMETER },
1155 { "tr2_test_dir\\f1_rename", "tr2_test_dir\\??invalid_name>>", ERROR_INVALID_NAME },
1156 { "tr2_test_dir\\not_exist_file", "tr2_test_dir\\not_exist_rename", ERROR_FILE_NOT_FOUND }
1159 memset(current_path, 0, MAX_PATH);
1160 GetCurrentDirectoryA(MAX_PATH, current_path);
1161 memset(temp_path, 0, MAX_PATH);
1162 GetTempPathA(MAX_PATH, temp_path);
1163 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
1164 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1166 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1167 file = CreateFileA("tr2_test_dir\\f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1168 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1169 CloseHandle(file);
1171 ret = p_tr2_sys__Rename("tr2_test_dir\\f1", "tr2_test_dir\\f1");
1172 todo_wine ok(ERROR_SUCCESS == ret, "test_tr2_sys__Rename(): expect: ERROR_SUCCESS, got %d\n", ret);
1173 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1174 errno = 0xdeadbeef;
1175 if(tests[i].val == ERROR_SUCCESS) {
1176 h1 = CreateFileA(tests[i].old_path, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1177 NULL, OPEN_EXISTING, 0, 0);
1178 ok(h1 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1179 ok(GetFileInformationByHandle(h1, &info1), "GetFileInformationByHandle failed\n");
1180 CloseHandle(h1);
1182 SetLastError(0xdeadbeef);
1183 ret = p_tr2_sys__Rename(tests[i].old_path, tests[i].new_path);
1184 ok(ret == tests[i].val, "test_tr2_sys__Rename(): test %d expect: %d, got %d\n", i+1, tests[i].val, ret);
1185 ok(errno == 0xdeadbeef, "test_tr2_sys__Rename(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1186 if(ret == ERROR_SUCCESS) {
1187 h2 = CreateFileA(tests[i].new_path, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1188 NULL, OPEN_EXISTING, 0, 0);
1189 ok(h2 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1190 ok(GetFileInformationByHandle(h2, &info2), "GetFileInformationByHandle failed\n");
1191 CloseHandle(h2);
1192 ok(info1.nFileIndexHigh == info2.nFileIndexHigh
1193 && info1.nFileIndexLow == info2.nFileIndexLow,
1194 "test_tr2_sys__Rename(): test %d expect two files equivalent\n", i+1);
1198 file = CreateFileA("tr2_test_dir\\f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1199 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1200 file_size.QuadPart = 7;
1201 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1202 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1203 CloseHandle(file);
1204 ret = p_tr2_sys__Rename("tr2_test_dir\\f1", "tr2_test_dir\\f1_rename");
1205 ok(ret == ERROR_ALREADY_EXISTS, "test_tr2_sys__Rename(): expect: ERROR_ALREADY_EXISTS, got %d\n", ret);
1206 ok(p_tr2_sys__File_size("tr2_test_dir\\f1") == 7, "test_tr2_sys__Rename(): expect: 7, got %s\n", debugstr_longlong(p_tr2_sys__File_size("tr2_test_dir\\f1")));
1207 ok(p_tr2_sys__File_size("tr2_test_dir\\f1_rename") == 0, "test_tr2_sys__Rename(): expect: 0, got %s\n",debugstr_longlong(p_tr2_sys__File_size("tr2_test_dir\\f1_rename")));
1208 ret = p_tr2_sys__Rename_wchar(testW, testW2);
1209 ok(ret == ERROR_SUCCESS, "tr2_sys__Rename_wchar(): expect: ERROR_SUCCESS, got %d\n", ret);
1211 ok(DeleteFileW(testW2), "expect fw to exist\n");
1212 ok(DeleteFileA("tr2_test_dir\\f1_rename"), "expect f1_rename to exist\n");
1213 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1214 ok(ret == 1, "test_tr2_sys__Remove_dir(): expect %d got %d\n", 1, ret);
1215 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
1218 static void test_tr2_sys__Statvfs(void)
1220 struct space_info info;
1221 char current_path[MAX_PATH];
1222 WCHAR current_path_wchar[MAX_PATH];
1223 memset(current_path, 0, MAX_PATH);
1224 p_tr2_sys__Current_get(current_path);
1225 memset(current_path_wchar, 0, MAX_PATH);
1226 p_tr2_sys__Current_get_wchar(current_path_wchar);
1228 p_tr2_sys__Statvfs(&info, current_path);
1229 ok(info.capacity >= info.free, "test_tr2_sys__Statvfs(): info.capacity < info.free\n");
1230 ok(info.free >= info.available, "test_tr2_sys__Statvfs(): info.free < info.available\n");
1232 p_tr2_sys__Statvfs_wchar(&info, current_path_wchar);
1233 ok(info.capacity >= info.free, "tr2_sys__Statvfs_wchar(): info.capacity < info.free\n");
1234 ok(info.free >= info.available, "tr2_sys__Statvfs_wchar(): info.free < info.available\n");
1236 p_tr2_sys__Statvfs(&info, NULL);
1237 ok(info.available == 0, "test_tr2_sys__Statvfs(): info.available expect: %d, got %s\n",
1238 0, debugstr_longlong(info.available));
1239 ok(info.capacity == 0, "test_tr2_sys__Statvfs(): info.capacity expect: %d, got %s\n",
1240 0, debugstr_longlong(info.capacity));
1241 ok(info.free == 0, "test_tr2_sys__Statvfs(): info.free expect: %d, got %s\n",
1242 0, debugstr_longlong(info.free));
1244 p_tr2_sys__Statvfs(&info, "not_exist");
1245 ok(info.available == 0, "test_tr2_sys__Statvfs(): info.available expect: %d, got %s\n",
1246 0, debugstr_longlong(info.available));
1247 ok(info.capacity == 0, "test_tr2_sys__Statvfs(): info.capacity expect: %d, got %s\n",
1248 0, debugstr_longlong(info.capacity));
1249 ok(info.free == 0, "test_tr2_sys__Statvfs(): info.free expect: %d, got %s\n",
1250 0, debugstr_longlong(info.free));
1253 static void test_tr2_sys__Stat(void)
1255 int i, err_code, ret;
1256 HANDLE file;
1257 enum file_type val;
1258 struct {
1259 char const *path;
1260 enum file_type ret;
1261 int err_code;
1262 int is_todo;
1263 } tests[] = {
1264 { NULL, status_unknown, ERROR_INVALID_PARAMETER, FALSE },
1265 { "tr2_test_dir", directory_file, ERROR_SUCCESS, FALSE },
1266 { "tr2_test_dir\\f1", regular_file, ERROR_SUCCESS, FALSE },
1267 { "tr2_test_dir\\not_exist_file ", file_not_found, ERROR_SUCCESS, FALSE },
1268 { "tr2_test_dir\\??invalid_name>>", file_not_found, ERROR_SUCCESS, FALSE },
1269 { "tr2_test_dir\\f1_link" , regular_file, ERROR_SUCCESS, TRUE },
1270 { "tr2_test_dir\\dir_link", directory_file, ERROR_SUCCESS, TRUE },
1272 WCHAR testW[] = {'t','r','2','_','t','e','s','t','_','d','i','r',0};
1273 WCHAR testW2[] = {'t','r','2','_','t','e','s','t','_','d','i','r','/','f','1',0};
1275 CreateDirectoryA("tr2_test_dir", NULL);
1276 file = CreateFileA("tr2_test_dir/f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1277 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1278 ok(CloseHandle(file), "CloseHandle\n");
1279 SetLastError(0xdeadbeef);
1280 ret = CreateSymbolicLinkA("tr2_test_dir/f1_link", "tr2_test_dir/f1", 0);
1281 if(!ret && (GetLastError()==ERROR_PRIVILEGE_NOT_HELD||GetLastError()==ERROR_INVALID_FUNCTION)) {
1282 tests[5].ret = tests[6].ret = file_not_found;
1283 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
1284 }else {
1285 ok(ret, "CreateSymbolicLinkA failed\n");
1286 ok(CreateSymbolicLinkA("tr2_test_dir/dir_link", "tr2_test_dir", 1), "CreateSymbolicLinkA failed\n");
1289 file = CreateNamedPipeA("\\\\.\\PiPe\\tests_pipe.c",
1290 PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024,
1291 NMPWAIT_USE_DEFAULT_WAIT, NULL);
1292 ok(file != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1293 err_code = 0xdeadbeef;
1294 val = p_tr2_sys__Stat("\\\\.\\PiPe\\tests_pipe.c", &err_code);
1295 todo_wine ok(regular_file == val, "tr2_sys__Stat(): expect: regular_file, got %d\n", val);
1296 todo_wine ok(ERROR_SUCCESS == err_code, "tr2_sys__Stat(): err_code expect: ERROR_SUCCESS, got %d\n", err_code);
1297 err_code = 0xdeadbeef;
1298 val = p_tr2_sys__Lstat("\\\\.\\PiPe\\tests_pipe.c", &err_code);
1299 ok(status_unknown == val, "tr2_sys__Lstat(): expect: status_unknown, got %d\n", val);
1300 todo_wine ok(ERROR_PIPE_BUSY == err_code, "tr2_sys__Lstat(): err_code expect: ERROR_PIPE_BUSY, got %d\n", err_code);
1301 ok(CloseHandle(file), "CloseHandle\n");
1302 file = CreateNamedPipeA("\\\\.\\PiPe\\tests_pipe.c",
1303 PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024,
1304 NMPWAIT_USE_DEFAULT_WAIT, NULL);
1305 ok(file != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1306 err_code = 0xdeadbeef;
1307 val = p_tr2_sys__Lstat("\\\\.\\PiPe\\tests_pipe.c", &err_code);
1308 todo_wine ok(regular_file == val, "tr2_sys__Lstat(): expect: regular_file, got %d\n", val);
1309 todo_wine ok(ERROR_SUCCESS == err_code, "tr2_sys__Lstat(): err_code expect: ERROR_SUCCESS, got %d\n", err_code);
1310 ok(CloseHandle(file), "CloseHandle\n");
1312 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1313 err_code = 0xdeadbeef;
1314 val = p_tr2_sys__Stat(tests[i].path, &err_code);
1315 todo_wine_if(tests[i].is_todo)
1316 ok(tests[i].ret == val, "tr2_sys__Stat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
1317 ok(tests[i].err_code == err_code, "tr2_sys__Stat(): test %d err_code expect: %d, got %d\n",
1318 i+1, tests[i].err_code, err_code);
1320 /* test tr2_sys__Lstat */
1321 err_code = 0xdeadbeef;
1322 val = p_tr2_sys__Lstat(tests[i].path, &err_code);
1323 todo_wine_if(tests[i].is_todo)
1324 ok(tests[i].ret == val, "tr2_sys__Lstat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
1325 ok(tests[i].err_code == err_code, "tr2_sys__Lstat(): test %d err_code expect: %d, got %d\n",
1326 i+1, tests[i].err_code, err_code);
1329 err_code = 0xdeadbeef;
1330 val = p_tr2_sys__Stat_wchar(testW, &err_code);
1331 ok(directory_file == val, "tr2_sys__Stat_wchar() expect directory_file, got %d\n", val);
1332 ok(ERROR_SUCCESS == err_code, "tr2_sys__Stat_wchar(): err_code expect ERROR_SUCCESS, got %d\n", err_code);
1333 err_code = 0xdeadbeef;
1334 val = p_tr2_sys__Lstat_wchar(testW2, &err_code);
1335 ok(regular_file == val, "tr2_sys__Lstat_wchar() expect regular_file, got %d\n", val);
1336 ok(ERROR_SUCCESS == err_code, "tr2_sys__Lstat_wchar(): err_code expect ERROR_SUCCESS, got %d\n", err_code);
1338 if(ret) {
1339 todo_wine ok(DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link to exist\n");
1340 todo_wine ok(RemoveDirectoryA("tr2_test_dir/dir_link"), "expect tr2_test_dir/dir_link to exist\n");
1342 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
1343 ok(RemoveDirectoryA("tr2_test_dir"), "expect tr2_test_dir to exist\n");
1346 static void test_tr2_sys__Last_write_time(void)
1348 HANDLE file;
1349 int ret;
1350 __int64 last_write_time, newtime;
1351 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1352 ok(ret == 1, "tr2_sys__Make_dir() expect 1 got %d\n", ret);
1354 file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1355 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1356 CloseHandle(file);
1358 last_write_time = p_tr2_sys__Last_write_time("tr2_test_dir/f1");
1359 newtime = last_write_time + 123456789;
1360 p_tr2_sys__Last_write_time_set("tr2_test_dir/f1", newtime);
1361 todo_wine ok(last_write_time == p_tr2_sys__Last_write_time("tr2_test_dir/f1"),
1362 "last_write_time before modfied should not equal to last_write_time %s\n",
1363 debugstr_longlong(last_write_time));
1365 errno = 0xdeadbeef;
1366 last_write_time = p_tr2_sys__Last_write_time("not_exist");
1367 ok(errno == 0xdeadbeef, "tr2_sys__Last_write_time(): errno expect 0xdeadbeef, got %d\n", errno);
1368 ok(last_write_time == 0, "expect 0 got %s\n", debugstr_longlong(last_write_time));
1369 last_write_time = p_tr2_sys__Last_write_time(NULL);
1370 ok(last_write_time == 0, "expect 0 got %s\n", debugstr_longlong(last_write_time));
1372 p_tr2_sys__Last_write_time_set("not_exist", newtime);
1373 errno = 0xdeadbeef;
1374 p_tr2_sys__Last_write_time_set(NULL, newtime);
1375 ok(errno == 0xdeadbeef, "tr2_sys__Last_write_time(): errno expect 0xdeadbeef, got %d\n", errno);
1377 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
1378 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1379 ok(ret == 1, "test_tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1382 static void test_tr2_sys__dir_operation(void)
1384 char *file_name, first_file_name[MAX_PATH], dest[MAX_PATH], longer_path[MAX_PATH];
1385 HANDLE file, result_handle;
1386 enum file_type type;
1387 int err, num_of_f1 = 0, num_of_f2 = 0, num_of_sub_dir = 0, num_of_other_files = 0;
1389 CreateDirectoryA("tr2_test_dir", NULL);
1390 file = CreateFileA("tr2_test_dir/f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1391 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1392 CloseHandle(file);
1393 file = CreateFileA("tr2_test_dir/f2", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1394 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1395 CloseHandle(file);
1396 CreateDirectoryA("tr2_test_dir/sub_dir", NULL);
1397 file = CreateFileA("tr2_test_dir/sub_dir/sub_f1", 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
1398 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1399 CloseHandle(file);
1401 memset(longer_path, 0, MAX_PATH);
1402 GetCurrentDirectoryA(MAX_PATH, longer_path);
1403 strcat(longer_path, "\\tr2_test_dir\\");
1404 while(lstrlenA(longer_path) < MAX_PATH-1)
1405 strcat(longer_path, "s");
1406 ok(lstrlenA(longer_path) == MAX_PATH-1, "tr2_sys__Open_dir(): expect MAX_PATH, got %d\n", lstrlenA(longer_path));
1407 memset(first_file_name, 0, MAX_PATH);
1408 type = err = 0xdeadbeef;
1409 result_handle = NULL;
1410 result_handle = p_tr2_sys__Open_dir(first_file_name, longer_path, &err, &type);
1411 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect NULL, got %p\n", result_handle);
1412 ok(!*first_file_name, "tr2_sys__Open_dir(): expect: 0, got %s\n", first_file_name);
1413 ok(err == ERROR_BAD_PATHNAME, "tr2_sys__Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err);
1414 ok((int)type == 0xdeadbeef, "tr2_sys__Open_dir(): expect 0xdeadbeef, got %d\n", type);
1416 memset(first_file_name, 0, MAX_PATH);
1417 memset(dest, 0, MAX_PATH);
1418 err = type = 0xdeadbeef;
1419 result_handle = NULL;
1420 result_handle = p_tr2_sys__Open_dir(first_file_name, "tr2_test_dir", &err, &type);
1421 ok(result_handle != NULL, "tr2_sys__Open_dir(): expect: not NULL, got %p\n", result_handle);
1422 ok(err == ERROR_SUCCESS, "tr2_sys__Open_dir(): expect: ERROR_SUCCESS, got %d\n", err);
1423 file_name = first_file_name;
1424 while(*file_name) {
1425 if (!strcmp(file_name, "f1")) {
1426 ++num_of_f1;
1427 ok(type == regular_file, "expect regular_file, got %d\n", type);
1428 }else if(!strcmp(file_name, "f2")) {
1429 ++num_of_f2;
1430 ok(type == regular_file, "expect regular_file, got %d\n", type);
1431 }else if(!strcmp(file_name, "sub_dir")) {
1432 ++num_of_sub_dir;
1433 ok(type == directory_file, "expect directory_file, got %d\n", type);
1434 }else {
1435 ++num_of_other_files;
1437 file_name = p_tr2_sys__Read_dir(dest, result_handle, &type);
1439 p_tr2_sys__Close_dir(result_handle);
1440 ok(result_handle != NULL, "tr2_sys__Open_dir(): expect: not NULL, got %p\n", result_handle);
1441 ok(num_of_f1 == 1, "found f1 %d times\n", num_of_f1);
1442 ok(num_of_f2 == 1, "found f2 %d times\n", num_of_f2);
1443 ok(num_of_sub_dir == 1, "found sub_dir %d times\n", num_of_sub_dir);
1444 ok(num_of_other_files == 0, "found %d other files\n", num_of_other_files);
1446 memset(first_file_name, 0, MAX_PATH);
1447 err = type = 0xdeadbeef;
1448 result_handle = file;
1449 result_handle = p_tr2_sys__Open_dir(first_file_name, "not_exist", &err, &type);
1450 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect: NULL, got %p\n", result_handle);
1451 todo_wine ok(err == ERROR_BAD_PATHNAME, "tr2_sys__Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err);
1452 ok((int)type == 0xdeadbeef, "tr2_sys__Open_dir(): expect: 0xdeadbeef, got %d\n", type);
1453 ok(!*first_file_name, "tr2_sys__Open_dir(): expect: 0, got %s\n", first_file_name);
1455 CreateDirectoryA("empty_dir", NULL);
1456 memset(first_file_name, 0, MAX_PATH);
1457 err = type = 0xdeadbeef;
1458 result_handle = file;
1459 result_handle = p_tr2_sys__Open_dir(first_file_name, "empty_dir", &err, &type);
1460 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect: NULL, got %p\n", result_handle);
1461 ok(err == ERROR_SUCCESS, "tr2_sys__Open_dir(): expect: ERROR_SUCCESS, got %d\n", err);
1462 ok(type == status_unknown, "tr2_sys__Open_dir(): expect: status_unknown, got %d\n", type);
1463 ok(!*first_file_name, "tr2_sys__Open_dir(): expect: 0, got %s\n", first_file_name);
1464 p_tr2_sys__Close_dir(result_handle);
1465 ok(result_handle == NULL, "tr2_sys__Open_dir(): expect: NULL, got %p\n", result_handle);
1467 ok(RemoveDirectoryA("empty_dir"), "expect empty_dir to exist\n");
1468 ok(DeleteFileA("tr2_test_dir/sub_dir/sub_f1"), "expect tr2_test_dir/sub_dir/sub_f1 to exist\n");
1469 ok(RemoveDirectoryA("tr2_test_dir/sub_dir"), "expect tr2_test_dir/sub_dir to exist\n");
1470 ok(DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 to exist\n");
1471 ok(DeleteFileA("tr2_test_dir/f2"), "expect tr2_test_dir/f2 to exist\n");
1472 ok(RemoveDirectoryA("tr2_test_dir"), "expect tr2_test_dir to exist\n");
1475 static void test_tr2_sys__Link(void)
1477 int ret, i;
1478 HANDLE file, h1, h2;
1479 BY_HANDLE_FILE_INFORMATION info1, info2;
1480 char temp_path[MAX_PATH], current_path[MAX_PATH];
1481 LARGE_INTEGER file_size;
1482 struct {
1483 char const *existing_path;
1484 char const *new_path;
1485 MSVCP_bool fail_if_exists;
1486 int last_error;
1487 } tests[] = {
1488 { "f1", "f1_link", TRUE, ERROR_SUCCESS },
1489 { "f1", "tr2_test_dir\\f1_link", TRUE, ERROR_SUCCESS },
1490 { "tr2_test_dir\\f1_link", "tr2_test_dir\\f1_link_link", TRUE, ERROR_SUCCESS },
1491 { "tr2_test_dir", "dir_link", TRUE, ERROR_ACCESS_DENIED },
1492 { NULL, "NULL_link", TRUE, ERROR_INVALID_PARAMETER },
1493 { "f1", NULL, TRUE, ERROR_INVALID_PARAMETER },
1494 { "not_exist", "not_exist_link", TRUE, ERROR_FILE_NOT_FOUND },
1495 { "f1", "not_exist_dir\\f1_link", TRUE, ERROR_PATH_NOT_FOUND }
1498 memset(current_path, 0, MAX_PATH);
1499 GetCurrentDirectoryA(MAX_PATH, current_path);
1500 memset(temp_path, 0, MAX_PATH);
1501 GetTempPathA(MAX_PATH, temp_path);
1502 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
1504 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1505 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1506 file = CreateFileA("f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1507 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1508 file_size.QuadPart = 7;
1509 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1510 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1511 CloseHandle(file);
1513 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1514 errno = 0xdeadbeef;
1515 ret = p_tr2_sys__Link(tests[i].existing_path, tests[i].new_path);
1516 ok(ret == tests[i].last_error, "tr2_sys__Link(): test %d expect: %d, got %d\n",
1517 i+1, tests[i].last_error, ret);
1518 ok(errno == 0xdeadbeef, "tr2_sys__Link(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1519 if(ret == ERROR_SUCCESS)
1520 ok(p_tr2_sys__File_size(tests[i].existing_path) == p_tr2_sys__File_size(tests[i].new_path),
1521 "tr2_sys__Link(): test %d failed, two files' size are not equal\n", i+1);
1524 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1525 ok(p_tr2_sys__File_size("f1_link") == p_tr2_sys__File_size("tr2_test_dir/f1_link") &&
1526 p_tr2_sys__File_size("tr2_test_dir/f1_link") == p_tr2_sys__File_size("tr2_test_dir/f1_link_link"),
1527 "tr2_sys__Link(): expect links' size are equal, got %s\n", debugstr_longlong(p_tr2_sys__File_size("tr2_test_dir/f1_link_link")));
1528 ok(p_tr2_sys__File_size("f1_link") == 7, "tr2_sys__Link(): expect f1_link's size equals to 7, got %s\n", debugstr_longlong(p_tr2_sys__File_size("f1_link")));
1530 file = CreateFileA("f1_link", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1531 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1532 file_size.QuadPart = 20;
1533 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1534 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1535 CloseHandle(file);
1536 h1 = CreateFileA("f1_link", 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1537 NULL, OPEN_EXISTING, 0, 0);
1538 ok(h1 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1539 ok(GetFileInformationByHandle(h1, &info1), "GetFileInformationByHandle failed\n");
1540 CloseHandle(h1);
1541 h2 = CreateFileA("tr2_test_dir/f1_link", 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1542 NULL, OPEN_EXISTING, 0, 0);
1543 ok(h2 != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1544 ok(GetFileInformationByHandle(h2, &info2), "GetFileInformationByHandle failed\n");
1545 CloseHandle(h2);
1546 ok(info1.nFileIndexHigh == info2.nFileIndexHigh
1547 && info1.nFileIndexLow == info2.nFileIndexLow,
1548 "tr2_sys__Link(): test %d expect two files equivalent\n", i+1);
1549 ok(p_tr2_sys__File_size("f1_link") == 20, "tr2_sys__Link(): expect f1_link's size equals to 20, got %s\n", debugstr_longlong(p_tr2_sys__File_size("f1_link")));
1551 ok(DeleteFileA("f1_link"), "expect f1_link to exist\n");
1552 ok(DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link to exist\n");
1553 ok(DeleteFileA("tr2_test_dir/f1_link_link"), "expect tr2_test_dir/f1_link_link to exist\n");
1554 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1555 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1556 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
1559 static void test_tr2_sys__Symlink(void)
1561 int ret, i;
1562 HANDLE file;
1563 LARGE_INTEGER file_size;
1564 struct {
1565 char const *existing_path;
1566 char const *new_path;
1567 int last_error;
1568 MSVCP_bool is_todo;
1569 } tests[] = {
1570 { "f1", "f1_link", ERROR_SUCCESS, FALSE },
1571 { "f1", "tr2_test_dir\\f1_link", ERROR_SUCCESS, FALSE },
1572 { "tr2_test_dir\\f1_link", "tr2_test_dir\\f1_link_link", ERROR_SUCCESS, FALSE },
1573 { "tr2_test_dir", "dir_link", ERROR_SUCCESS, FALSE },
1574 { NULL, "NULL_link", ERROR_INVALID_PARAMETER, FALSE },
1575 { "f1", NULL, ERROR_INVALID_PARAMETER, FALSE },
1576 { "not_exist", "not_exist_link", ERROR_SUCCESS, FALSE },
1577 { "f1", "not_exist_dir\\f1_link", ERROR_PATH_NOT_FOUND, TRUE }
1580 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1581 ok(ret == 1, "test_tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1582 file = CreateFileA("f1", 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 = 7;
1585 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1586 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1587 CloseHandle(file);
1589 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1590 errno = 0xdeadbeef;
1591 SetLastError(0xdeadbeef);
1592 ret = p_tr2_sys__Symlink(tests[i].existing_path, tests[i].new_path);
1593 if(!i && (ret==ERROR_PRIVILEGE_NOT_HELD || ret==ERROR_INVALID_FUNCTION)) {
1594 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
1595 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1596 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1597 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1598 return;
1601 ok(errno == 0xdeadbeef, "tr2_sys__Symlink(): test %d errno expect 0xdeadbeef, got %d\n", i+1, errno);
1602 todo_wine_if(tests[i].is_todo)
1603 ok(ret == tests[i].last_error, "tr2_sys__Symlink(): test %d expect: %d, got %d\n", i+1, tests[i].last_error, ret);
1604 if(ret == ERROR_SUCCESS)
1605 ok(p_tr2_sys__File_size(tests[i].new_path) == 0, "tr2_sys__Symlink(): expect 0, got %s\n", debugstr_longlong(p_tr2_sys__File_size(tests[i].new_path)));
1608 ok(DeleteFileA("f1"), "expect f1 to exist\n");
1609 todo_wine ok(DeleteFileA("f1_link"), "expect f1_link to exist\n");
1610 todo_wine ok(DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link to exist\n");
1611 todo_wine ok(DeleteFileA("tr2_test_dir/f1_link_link"), "expect tr2_test_dir/f1_link_link to exist\n");
1612 todo_wine ok(DeleteFileA("not_exist_link"), "expect not_exist_link to exist\n");
1613 todo_wine ok(DeleteFileA("dir_link"), "expect dir_link to exist\n");
1614 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1615 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1618 static void test_tr2_sys__Unlink(void)
1620 char temp_path[MAX_PATH], current_path[MAX_PATH];
1621 int ret, i;
1622 HANDLE file;
1623 LARGE_INTEGER file_size;
1624 struct {
1625 char const *path;
1626 int last_error;
1627 MSVCP_bool is_todo;
1628 } tests[] = {
1629 { "tr2_test_dir\\f1_symlink", ERROR_SUCCESS, TRUE },
1630 { "tr2_test_dir\\f1_link", ERROR_SUCCESS, FALSE },
1631 { "tr2_test_dir\\f1", ERROR_SUCCESS, FALSE },
1632 { "tr2_test_dir", ERROR_ACCESS_DENIED, FALSE },
1633 { "not_exist", ERROR_FILE_NOT_FOUND, FALSE },
1634 { "not_exist_dir\\not_exist_file", ERROR_PATH_NOT_FOUND, FALSE },
1635 { NULL, ERROR_PATH_NOT_FOUND, FALSE }
1638 GetCurrentDirectoryA(MAX_PATH, current_path);
1639 GetTempPathA(MAX_PATH, temp_path);
1640 ok(SetCurrentDirectoryA(temp_path), "SetCurrentDirectoryA to temp_path failed\n");
1642 ret = p_tr2_sys__Make_dir("tr2_test_dir");
1643 ok(ret == 1, "tr2_sys__Make_dir(): expect 1 got %d\n", ret);
1644 file = CreateFileA("tr2_test_dir/f1", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1645 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
1646 file_size.QuadPart = 7;
1647 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
1648 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
1649 CloseHandle(file);
1651 ret = p_tr2_sys__Symlink("tr2_test_dir/f1", "tr2_test_dir/f1_symlink");
1652 if(ret==ERROR_PRIVILEGE_NOT_HELD || ret==ERROR_INVALID_FUNCTION) {
1653 tests[0].last_error = ERROR_FILE_NOT_FOUND;
1654 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
1655 }else {
1656 ok(ret == ERROR_SUCCESS, "tr2_sys__Symlink(): expect: ERROR_SUCCESS, got %d\n", ret);
1658 ret = p_tr2_sys__Link("tr2_test_dir/f1", "tr2_test_dir/f1_link");
1659 ok(ret == ERROR_SUCCESS, "tr2_sys__Link(): expect: ERROR_SUCCESS, got %d\n", ret);
1661 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
1662 errno = 0xdeadbeef;
1663 ret = p_tr2_sys__Unlink(tests[i].path);
1664 todo_wine_if(tests[i].is_todo)
1665 ok(ret == tests[i].last_error, "tr2_sys__Unlink(): test %d expect: %d, got %d\n",
1666 i+1, tests[i].last_error, ret);
1667 ok(errno == 0xdeadbeef, "tr2_sys__Unlink(): test %d errno expect: 0xdeadbeef, got %d\n", i+1, ret);
1670 ok(!DeleteFileA("tr2_test_dir/f1"), "expect tr2_test_dir/f1 not to exist\n");
1671 ok(!DeleteFileA("tr2_test_dir/f1_link"), "expect tr2_test_dir/f1_link not to exist\n");
1672 ok(!DeleteFileA("tr2_test_dir/f1_symlink"), "expect tr2_test_dir/f1_symlink not to exist\n");
1673 ret = p_tr2_sys__Remove_dir("tr2_test_dir");
1674 ok(ret == 1, "tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
1676 ok(SetCurrentDirectoryA(current_path), "SetCurrentDirectoryA failed\n");
1679 static int __cdecl thrd_thread(void *arg)
1681 _Thrd_t *thr = arg;
1683 if(thr)
1684 *thr = p__Thrd_current();
1685 return 0x42;
1688 static void test_thrd(void)
1690 int ret, i, r;
1691 struct test {
1692 _Thrd_t a;
1693 _Thrd_t b;
1694 int r;
1696 const HANDLE hnd1 = (HANDLE)0xcccccccc;
1697 const HANDLE hnd2 = (HANDLE)0xdeadbeef;
1698 xtime xt, before, after;
1699 MSVCRT_long diff;
1700 _Thrd_t ta, tb;
1702 struct test testeq[] = {
1703 { {0, 0}, {0, 0}, 1 },
1704 { {0, 1}, {0, 0}, 0 },
1705 { {hnd1, 0}, {hnd1, 1}, 0 },
1706 { {hnd1, 0}, {hnd2, 0}, 1 }
1709 struct test testlt[] = {
1710 { {0, 0}, {0, 0}, 0 },
1711 { {0, 0}, {0, 1}, 1 },
1712 { {0, 1}, {0, 0}, 0 },
1713 { {hnd1, 0}, {hnd2, 0}, 0 },
1714 { {hnd1, 0}, {hnd2, 1}, 1 }
1717 /* test for equal */
1718 for(i=0; i<sizeof(testeq)/sizeof(testeq[0]); i++) {
1719 ret = p__Thrd_equal(testeq[i].a, testeq[i].b);
1720 ok(ret == testeq[i].r, "(%p %u) = (%p %u) expected %d, got %d\n",
1721 testeq[i].a.hnd, testeq[i].a.id, testeq[i].b.hnd, testeq[i].b.id, testeq[i].r, ret);
1724 /* test for less than */
1725 for(i=0; i<sizeof(testlt)/sizeof(testlt[0]); i++) {
1726 ret = p__Thrd_lt(testlt[i].a, testlt[i].b);
1727 ok(ret == testlt[i].r, "(%p %u) < (%p %u) expected %d, got %d\n",
1728 testlt[i].a.hnd, testlt[i].a.id, testlt[i].b.hnd, testlt[i].b.id, testlt[i].r, ret);
1731 /* test for sleep */
1732 if (0) /* crash on Windows */
1733 p__Thrd_sleep(NULL);
1734 p_xtime_get(&xt, 1);
1735 xt.sec += 2;
1736 p_xtime_get(&before, 1);
1737 p__Thrd_sleep(&xt);
1738 p_xtime_get(&after, 1);
1739 diff = p__Xtime_diff_to_millis2(&after, &before);
1740 ok(diff > 2000 - TIMEDELTA, "got %d\n", diff);
1742 /* test for current */
1743 ta = p__Thrd_current();
1744 tb = p__Thrd_current();
1745 ok(ta.id == tb.id, "got a %d b %d\n", ta.id, tb.id);
1746 ok(ta.id == GetCurrentThreadId(), "expected %d, got %d\n", GetCurrentThreadId(), ta.id);
1747 /* these can be different if new threads are created at same time */
1748 ok(ta.hnd == tb.hnd, "got a %p b %p\n", ta.hnd, tb.hnd);
1749 ok(!CloseHandle(ta.hnd), "handle %p not closed\n", ta.hnd);
1750 ok(!CloseHandle(tb.hnd), "handle %p not closed\n", tb.hnd);
1752 /* test for create/join */
1753 if (0) /* crash on Windows */
1755 p__Thrd_create(NULL, thrd_thread, NULL);
1756 p__Thrd_create(&ta, NULL, NULL);
1758 r = -1;
1759 ret = p__Thrd_create(&ta, thrd_thread, (void*)&tb);
1760 ok(!ret, "failed to create thread, got %d\n", ret);
1761 ret = p__Thrd_join(ta, &r);
1762 ok(!ret, "failed to join thread, got %d\n", ret);
1763 ok(ta.id == tb.id, "expected %d, got %d\n", ta.id, tb.id);
1764 ok(ta.hnd != tb.hnd, "same handles, got %p\n", ta.hnd);
1765 ok(r == 0x42, "expected 0x42, got %d\n", r);
1766 ret = p__Thrd_detach(ta);
1767 ok(ret == 4, "_Thrd_detach should have failed with error 4, got %d\n", ret);
1769 ret = p__Thrd_create(&ta, thrd_thread, NULL);
1770 ok(!ret, "failed to create thread, got %d\n", ret);
1771 ret = p__Thrd_detach(ta);
1772 ok(!ret, "_Thrd_detach failed, got %d\n", ret);
1776 #define NUM_THREADS 10
1777 struct cndmtx
1779 HANDLE initialized;
1780 int started;
1781 int thread_no;
1783 _Cnd_t cnd;
1784 _Mtx_t mtx;
1785 BOOL timed_wait;
1788 static int __cdecl cnd_wait_thread(void *arg)
1790 struct cndmtx *cm = arg;
1791 int r;
1793 p__Mtx_lock(&cm->mtx);
1795 if(InterlockedIncrement(&cm->started) == cm->thread_no)
1796 SetEvent(cm->initialized);
1798 if(cm->timed_wait) {
1799 xtime xt;
1801 p_xtime_get(&xt, 1);
1802 xt.sec += 2;
1803 r = p__Cnd_timedwait(&cm->cnd, &cm->mtx, &xt);
1804 ok(!r, "timed wait failed\n");
1805 } else {
1806 r = p__Cnd_wait(&cm->cnd, &cm->mtx);
1807 ok(!r, "wait failed\n");
1810 p__Mtx_unlock(&cm->mtx);
1811 return 0;
1814 static void test_cnd(void)
1816 _Thrd_t threads[NUM_THREADS];
1817 xtime xt, before, after;
1818 MSVCRT_long diff;
1819 struct cndmtx cm;
1820 _Cnd_t cnd;
1821 _Mtx_t mtx;
1822 int r, i;
1824 r = p__Cnd_init(&cnd);
1825 ok(!r, "failed to init cnd\n");
1827 r = p__Mtx_init(&mtx, 0);
1828 ok(!r, "failed to init mtx\n");
1830 if (0) /* crash on Windows */
1832 p__Cnd_init(NULL);
1833 p__Cnd_wait(NULL, &mtx);
1834 p__Cnd_wait(&cnd, NULL);
1835 p__Cnd_timedwait(NULL, &mtx, &xt);
1836 p__Cnd_timedwait(&cnd, &mtx, &xt);
1838 p__Cnd_destroy(NULL);
1840 /* test _Cnd_signal/_Cnd_wait */
1841 cm.initialized = CreateEventW(NULL, FALSE, FALSE, NULL);
1842 cm.started = 0;
1843 cm.thread_no = 1;
1844 cm.cnd = cnd;
1845 cm.mtx = mtx;
1846 cm.timed_wait = FALSE;
1847 p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
1849 WaitForSingleObject(cm.initialized, INFINITE);
1850 p__Mtx_lock(&mtx);
1851 p__Mtx_unlock(&mtx);
1853 r = p__Cnd_signal(&cm.cnd);
1854 ok(!r, "failed to signal\n");
1855 p__Thrd_join(threads[0], NULL);
1857 /* test _Cnd_timedwait time out */
1858 p__Mtx_lock(&mtx);
1859 p_xtime_get(&before, 1);
1860 xt = before;
1861 xt.sec += 1;
1862 r = p__Cnd_timedwait(&cnd, &mtx, &xt);
1863 p_xtime_get(&after, 1);
1864 p__Mtx_unlock(&mtx);
1866 diff = p__Xtime_diff_to_millis2(&after, &before);
1867 ok(r == 2, "should have timed out\n");
1868 ok(diff > 1000 - TIMEDELTA, "got %d\n", diff);
1870 /* test _Cnd_timedwait */
1871 cm.started = 0;
1872 cm.timed_wait = TRUE;
1873 p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
1875 WaitForSingleObject(cm.initialized, INFINITE);
1876 p__Mtx_lock(&mtx);
1877 p__Mtx_unlock(&mtx);
1879 r = p__Cnd_signal(&cm.cnd);
1880 ok(!r, "failed to signal\n");
1881 p__Thrd_join(threads[0], NULL);
1883 /* test _Cnd_broadcast */
1884 cm.started = 0;
1885 cm.thread_no = NUM_THREADS;
1886 cm.timed_wait = FALSE;
1888 for(i = 0; i < cm.thread_no; i++)
1889 p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
1891 WaitForSingleObject(cm.initialized, INFINITE);
1892 p__Mtx_lock(&mtx);
1893 p__Mtx_unlock(&mtx);
1895 r = p__Cnd_broadcast(&cnd);
1896 ok(!r, "failed to broadcast\n");
1897 for(i = 0; i < cm.thread_no; i++)
1898 p__Thrd_join(threads[i], NULL);
1900 /* test broadcast with _Cnd_destroy */
1901 cm.started = 0;
1902 for(i = 0; i < cm.thread_no; i++)
1903 p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
1905 WaitForSingleObject(cm.initialized, INFINITE);
1906 p__Mtx_lock(&mtx);
1907 p__Mtx_unlock(&mtx);
1909 p__Cnd_destroy(&cnd);
1910 for(i = 0; i < cm.thread_no; i++)
1911 p__Thrd_join(threads[i], NULL);
1913 p__Mtx_destroy(&mtx);
1914 CloseHandle(cm.initialized);
1917 static struct {
1918 int value[2];
1919 const char* export_name;
1920 } vbtable_size_exports_list[] = {
1921 {{0x20, 0x20}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_istream@DU?$char_traits@D@std@@@1@@"},
1922 {{0x10, 0x10}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_ostream@DU?$char_traits@D@std@@@1@@"},
1923 {{0x20, 0x20}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_istream@GU?$char_traits@G@std@@@1@@"},
1924 {{0x10, 0x10}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_ostream@GU?$char_traits@G@std@@@1@@"},
1925 {{0x20, 0x20}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_istream@_WU?$char_traits@_W@std@@@1@@"},
1926 {{0x10, 0x10}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_ostream@_WU?$char_traits@_W@std@@@1@@"},
1927 {{0x18, 0x18}, "??_8?$basic_istream@DU?$char_traits@D@std@@@std@@7B@"},
1928 {{0x18, 0x18}, "??_8?$basic_istream@GU?$char_traits@G@std@@@std@@7B@"},
1929 {{0x18, 0x18}, "??_8?$basic_istream@_WU?$char_traits@_W@std@@@std@@7B@"},
1930 {{ 0x8, 0x10}, "??_8?$basic_ostream@DU?$char_traits@D@std@@@std@@7B@"},
1931 {{ 0x8, 0x10}, "??_8?$basic_ostream@GU?$char_traits@G@std@@@std@@7B@"},
1932 {{ 0x8, 0x10}, "??_8?$basic_ostream@_WU?$char_traits@_W@std@@@std@@7B@"},
1933 {{ 0x0, 0x0}, 0}
1936 static void test_vbtable_size_exports(void)
1938 int i;
1939 const int *p_vbtable;
1940 int arch_idx = (sizeof(void*) == 8);
1942 for (i = 0; vbtable_size_exports_list[i].export_name; i++)
1944 SET(p_vbtable, vbtable_size_exports_list[i].export_name);
1946 ok(p_vbtable[0] == 0, "vbtable[0] wrong, got 0x%x\n", p_vbtable[0]);
1947 ok(p_vbtable[1] == vbtable_size_exports_list[i].value[arch_idx],
1948 "%d: %s[1] wrong, got 0x%x\n", i, vbtable_size_exports_list[i].export_name, p_vbtable[1]);
1952 HANDLE _Pad__Launch_returned;
1953 _Pad pad;
1954 #ifdef __i386__
1955 /* TODO: this should be a __thiscall function */
1956 static unsigned int __stdcall vtbl_func__Go(void)
1957 #else
1958 static unsigned int __cdecl vtbl_func__Go(_Pad *this)
1959 #endif
1961 DWORD ret;
1963 ret = WaitForSingleObject(_Pad__Launch_returned, 100);
1964 ok(ret == WAIT_TIMEOUT, "WiatForSingleObject returned %x\n", ret);
1965 ok(!pad.mtx->count, "pad.mtx.count = %d\n", pad.mtx->count);
1966 ok(!pad.launched, "pad.launched = %x\n", pad.launched);
1967 call_func1(p__Pad__Release, &pad);
1968 ok(pad.launched, "pad.launched = %x\n", pad.launched);
1969 ret = WaitForSingleObject(_Pad__Launch_returned, 100);
1970 ok(ret == WAIT_OBJECT_0, "WiatForSingleObject returned %x\n", ret);
1971 ok(pad.mtx->count == 1, "pad.mtx.count = %d\n", pad.mtx->count);
1972 return 0;
1975 static void test__Pad(void)
1977 _Pad pad_copy;
1978 _Thrd_t thrd;
1979 vtable_ptr pfunc = (vtable_ptr)&vtbl_func__Go;
1981 _Pad__Launch_returned = CreateEventW(NULL, FALSE, FALSE, NULL);
1983 pad.vtable = (void*)1;
1984 pad.cnd = (void*)2;
1985 pad.mtx = (void*)3;
1986 pad.launched = TRUE;
1987 memset(&pad_copy, 0, sizeof(pad_copy));
1988 call_func2(p__Pad_copy_ctor, &pad_copy, &pad);
1989 ok(pad_copy.vtable != (void*)1, "pad_copy.vtable was not set\n");
1990 ok(pad_copy.cnd == (void*)2, "pad_copy.cnd = %p\n", pad_copy.cnd);
1991 ok(pad_copy.mtx == (void*)3, "pad_copy.mtx = %p\n", pad_copy.mtx);
1992 ok(pad_copy.launched, "pad_copy.launched = %x\n", pad_copy.launched);
1994 memset(&pad_copy, 0xde, sizeof(pad_copy));
1995 pad_copy.vtable = (void*)4;
1996 pad_copy.cnd = (void*)5;
1997 pad_copy.mtx = (void*)6;
1998 pad_copy.launched = FALSE;
1999 call_func2(p__Pad_op_assign, &pad_copy, &pad);
2000 ok(pad_copy.vtable == (void*)4, "pad_copy.vtable was set\n");
2001 ok(pad_copy.cnd == (void*)2, "pad_copy.cnd = %p\n", pad_copy.cnd);
2002 ok(pad_copy.mtx == (void*)3, "pad_copy.mtx = %p\n", pad_copy.mtx);
2003 ok(pad_copy.launched, "pad_copy.launched = %x\n", pad_copy.launched);
2005 call_func1(p__Pad_ctor, &pad);
2006 call_func2(p__Pad_copy_ctor, &pad_copy, &pad);
2007 ok(pad.vtable == pad_copy.vtable, "pad.vtable = %p, pad_copy.vtable = %p\n", pad.vtable, pad_copy.vtable);
2008 ok(pad.cnd == pad_copy.cnd, "pad.cnd = %p, pad_copy.cnd = %p\n", pad.cnd, pad_copy.cnd);
2009 ok(pad.mtx == pad_copy.mtx, "pad.mtx = %p, pad_copy.mtx = %p\n", pad.mtx, pad_copy.mtx);
2010 ok(pad.launched == pad_copy.launched, "pad.launched = %x, pad_copy.launched = %x\n", pad.launched, pad_copy.launched);
2011 call_func1(p__Pad_dtor, &pad);
2012 /* call_func1(p__Pad_dtor, &pad_copy); - copy constructor is broken, this causes a crash */
2014 memset(&pad, 0xfe, sizeof(pad));
2015 call_func1(p__Pad_ctor, &pad);
2016 ok(!pad.launched, "pad.launched = %x\n", pad.launched);
2017 ok(pad.mtx->count == 1, "pad.mtx.count = %d\n", pad.mtx->count);
2019 pad.vtable = &pfunc;
2020 call_func2(p__Pad__Launch, &pad, &thrd);
2021 SetEvent(_Pad__Launch_returned);
2022 ok(!p__Thrd_join(thrd, NULL), "_Thrd_join failed\n");
2024 call_func1(p__Pad_dtor, &pad);
2025 CloseHandle(_Pad__Launch_returned);
2028 START_TEST(msvcp120)
2030 if(!init()) return;
2031 test__Xtime_diff_to_millis2();
2032 test_xtime_get();
2033 test__Getcvt();
2034 test__Call_once();
2035 test__Do_call();
2036 test__Dtest();
2037 test__Dscale();
2038 test__FExp();
2040 test_tr2_sys__File_size();
2041 test_tr2_sys__Equivalent();
2042 test_tr2_sys__Current_get();
2043 test_tr2_sys__Current_set();
2044 test_tr2_sys__Make_dir();
2045 test_tr2_sys__Remove_dir();
2046 test_tr2_sys__Copy_file();
2047 test_tr2_sys__Rename();
2048 test_tr2_sys__Statvfs();
2049 test_tr2_sys__Stat();
2050 test_tr2_sys__Last_write_time();
2051 test_tr2_sys__dir_operation();
2052 test_tr2_sys__Link();
2053 test_tr2_sys__Symlink();
2054 test_tr2_sys__Unlink();
2056 test_thrd();
2057 test_cnd();
2058 test__Pad();
2060 test_vbtable_size_exports();
2062 FreeLibrary(msvcp);