2 * Copyright 2016 Daniel Lehman
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
26 #include "wine/test.h"
29 #define SECSPERDAY 86400
30 /* 1601 to 1970 is 369 years plus 89 leap days */
31 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
32 #define TICKSPERSEC 10000000
33 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
35 #define DEFINE_EXPECT(func) \
36 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
38 #define SET_EXPECT(func) \
40 expect_ ## func = TRUE; \
44 #define CHECK_EXPECT2(func) \
46 ok(expect_ ##func, "unexpected call " #func "\n"); \
47 called_ ## func = TRUE; \
50 #define CHECK_EXPECT(func) \
52 CHECK_EXPECT2(func); \
53 expect_ ## func = FALSE; \
56 #define CHECK_CALLED(func) \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = FALSE; \
63 DEFINE_EXPECT(function_do_call
);
64 DEFINE_EXPECT(function_do_clean
);
69 #define __thiscall __stdcall
71 #define __thiscall __cdecl
74 /* Emulate a __thiscall */
80 BYTE pop_eax
; /* popl %eax (ret addr) */
81 BYTE pop_edx
; /* popl %edx (func) */
82 BYTE pop_ecx
; /* popl %ecx (this) */
83 BYTE push_eax
; /* pushl %eax */
84 WORD jmp_edx
; /* jmp *%edx */
88 static void * (WINAPI
*call_thiscall_func1
)( void *func
, void *this );
89 static void * (WINAPI
*call_thiscall_func2
)( void *func
, void *this, const void *a
);
91 static void init_thiscall_thunk(void)
93 struct thiscall_thunk
*thunk
= VirtualAlloc( NULL
, sizeof(*thunk
),
94 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
95 thunk
->pop_eax
= 0x58; /* popl %eax */
96 thunk
->pop_edx
= 0x5a; /* popl %edx */
97 thunk
->pop_ecx
= 0x59; /* popl %ecx */
98 thunk
->push_eax
= 0x50; /* pushl %eax */
99 thunk
->jmp_edx
= 0xe2ff; /* jmp *%edx */
100 call_thiscall_func1
= (void *)thunk
;
101 call_thiscall_func2
= (void *)thunk
;
104 #define call_func1(func,_this) call_thiscall_func1(func,_this)
105 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,a)
109 #define init_thiscall_thunk()
110 #define call_func1(func,_this) func(_this)
111 #define call_func2(func,_this,a) func(_this,a)
113 #endif /* __i386__ */
114 typedef unsigned char MSVCP_bool
;
119 } task_continuation_context
;
127 void (__cdecl
*func
)(void);
131 } function_void_cdecl_void
;
135 MSVCP_bool scheduled
;
141 void (__cdecl
*callback
)(void*);
151 typedef struct cs_queue
154 struct cs_queue
*next
;
176 typedef void *_Cnd_t
;
183 typedef int (__cdecl
*_Thrd_start_t
)(void*);
198 static unsigned int (__cdecl
*p__Thrd_id
)(void);
199 static MSVCP_bool (__cdecl
*p__Task_impl_base__IsNonBlockingThread
)(void);
200 static task_continuation_context
* (__thiscall
*p_task_continuation_context_ctor
)(task_continuation_context
*);
201 static void (__thiscall
*p__ContextCallback__Assign
)(_ContextCallback
*, void*);
202 static void (__thiscall
*p__ContextCallback__CallInContext
)(const _ContextCallback
*, function_void_cdecl_void
, MSVCP_bool
);
203 static void (__thiscall
*p__ContextCallback__Capture
)(_ContextCallback
*);
204 static void (__thiscall
*p__ContextCallback__Reset
)(_ContextCallback
*);
205 static MSVCP_bool (__cdecl
*p__ContextCallback__IsCurrentOriginSTA
)(_ContextCallback
*);
206 static void (__thiscall
*p__TaskEventLogger__LogCancelTask
)(_TaskEventLogger
*);
207 static void (__thiscall
*p__TaskEventLogger__LogScheduleTask
)(_TaskEventLogger
*, MSVCP_bool
);
208 static void (__thiscall
*p__TaskEventLogger__LogTaskCompleted
)(_TaskEventLogger
*);
209 static void (__thiscall
*p__TaskEventLogger__LogTaskExecutionCompleted
)(_TaskEventLogger
*);
210 static void (__thiscall
*p__TaskEventLogger__LogWorkItemCompleted
)(_TaskEventLogger
*);
211 static void (__thiscall
*p__TaskEventLogger__LogWorkItemStarted
)(_TaskEventLogger
*);
212 static int (__cdecl
*p__Schedule_chore
)(_Threadpool_chore
*);
213 static int (__cdecl
*p__Reschedule_chore
)(const _Threadpool_chore
*);
214 static void (__cdecl
*p__Release_chore
)(_Threadpool_chore
*);
215 static int (__cdecl
*p__Mtx_init
)(_Mtx_t
*, int);
216 static void (__cdecl
*p__Mtx_destroy
)(_Mtx_t
);
217 static int (__cdecl
*p__Mtx_lock
)(_Mtx_t
);
218 static int (__cdecl
*p__Mtx_unlock
)(_Mtx_t
);
219 static int (__cdecl
*p__Cnd_init
)(_Cnd_t
*);
220 static void (__cdecl
*p__Cnd_destroy
)(_Cnd_t
);
221 static int (__cdecl
*p__Cnd_wait
)(_Cnd_t
, _Mtx_t
);
222 static int (__cdecl
*p__Cnd_timedwait
)(_Cnd_t
, _Mtx_t
, const xtime
*);
223 static int (__cdecl
*p__Cnd_broadcast
)(_Cnd_t
);
224 static int (__cdecl
*p__Cnd_signal
)(_Cnd_t
);
225 static int (__cdecl
*p__Thrd_create
)(_Thrd_t
*, _Thrd_start_t
, void*);
226 static int (__cdecl
*p__Thrd_join
)(_Thrd_t
, int*);
227 static int (__cdecl
*p__Xtime_diff_to_millis2
)(const xtime
*, const xtime
*);
228 static int (__cdecl
*p_xtime_get
)(xtime
*, int);
230 static void (__cdecl
*p_Close_dir
)(void*);
231 static DWORD (__cdecl
*p_Copy_file
)(WCHAR
const *, WCHAR
const *);
232 static MSVCP_bool (__cdecl
*p_Current_get
)(WCHAR
*);
233 static MSVCP_bool (__cdecl
*p_Current_set
)(WCHAR
const *);
234 static int (__cdecl
*p_Equivalent
)(WCHAR
const*, WCHAR
const*);
235 static ULONGLONG (__cdecl
*p_File_size
)(WCHAR
const *);
236 static int (__cdecl
*p_Resize
)(const WCHAR
*, UINT64
);
237 static __int64 (__cdecl
*p_Last_write_time
)(WCHAR
const*);
238 static void (__cdecl
*p_Set_last_write_time
)(WCHAR
const*, __int64
);
239 static int (__cdecl
*p_Link
)(WCHAR
const*, WCHAR
const*);
240 static enum file_type (__cdecl
*p_Lstat
)(WCHAR
const *, int *);
241 static int (__cdecl
*p_Make_dir
)(WCHAR
const*);
242 static void* (__cdecl
*p_Open_dir
)(WCHAR
*, WCHAR
const*, int *, enum file_type
*);
243 static WCHAR
* (__cdecl
*p_Read_dir
)(WCHAR
*, void*, enum file_type
*);
244 static MSVCP_bool (__cdecl
*p_Remove_dir
)(WCHAR
const*);
245 static int (__cdecl
*p_Rename
)(WCHAR
const*, WCHAR
const*);
246 static enum file_type (__cdecl
*p_Stat
)(WCHAR
const *, int *);
247 static int (__cdecl
*p_Symlink
)(WCHAR
const*, WCHAR
const*);
248 static WCHAR
* (__cdecl
*p_Temp_get
)(WCHAR
*);
249 static int (__cdecl
*p_To_byte
)(const WCHAR
*src
, char *dst
);
250 static int (__cdecl
*p_To_wide
)(const char *src
, WCHAR
*dst
);
251 static int (__cdecl
*p_Unlink
)(WCHAR
const*);
252 static ULONG (__cdecl
*p__Winerror_message
)(ULONG
, char*, ULONG
);
253 static int (__cdecl
*p__Winerror_map
)(int);
254 static const char* (__cdecl
*p__Syserror_map
)(int err
);
256 static BOOLEAN (WINAPI
*pCreateSymbolicLinkW
)(const WCHAR
*, const WCHAR
*, DWORD
);
258 static HMODULE msvcp
;
259 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
260 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
261 static BOOL
init(void)
265 msvcp
= LoadLibraryA("msvcp140.dll");
268 win_skip("msvcp140.dll not installed\n");
272 SET(p__Thrd_id
, "_Thrd_id");
273 SET(p__Task_impl_base__IsNonBlockingThread
, "?_IsNonBlockingThread@_Task_impl_base@details@Concurrency@@SA_NXZ");
274 SET(p__ContextCallback__IsCurrentOriginSTA
, "?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ");
275 SET(p__Winerror_map
, "?_Winerror_map@std@@YAHH@Z");
277 if(sizeof(void*) == 8) { /* 64-bit initialization */
278 SET(p_task_continuation_context_ctor
, "??0task_continuation_context@Concurrency@@AEAA@XZ");
279 SET(p__ContextCallback__Assign
, "?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z");
280 SET(p__ContextCallback__CallInContext
, "?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z");
281 SET(p__ContextCallback__Capture
, "?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ");
282 SET(p__ContextCallback__Reset
, "?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ");
283 SET(p__TaskEventLogger__LogCancelTask
, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
284 SET(p__TaskEventLogger__LogScheduleTask
, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z");
285 SET(p__TaskEventLogger__LogTaskCompleted
, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
286 SET(p__TaskEventLogger__LogTaskExecutionCompleted
, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
287 SET(p__TaskEventLogger__LogWorkItemCompleted
, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
288 SET(p__TaskEventLogger__LogWorkItemStarted
, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
289 SET(p__Schedule_chore
, "?_Schedule_chore@details@Concurrency@@YAHPEAU_Threadpool_chore@12@@Z");
290 SET(p__Reschedule_chore
, "?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z");
291 SET(p__Release_chore
, "?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z");
292 SET(p__Winerror_message
, "?_Winerror_message@std@@YAKKPEADK@Z");
293 SET(p__Syserror_map
, "?_Syserror_map@std@@YAPEBDH@Z");
296 SET(p_task_continuation_context_ctor
, "??0task_continuation_context@Concurrency@@AAA@XZ");
297 SET(p__ContextCallback__Assign
, "?_Assign@_ContextCallback@details@Concurrency@@AAAXPAX@Z");
298 SET(p__ContextCallback__CallInContext
, "?_CallInContext@_ContextCallback@details@Concurrency@@QBAXV?$function@$$A6AXXZ@std@@_N@Z");
299 SET(p__ContextCallback__Capture
, "?_Capture@_ContextCallback@details@Concurrency@@AAAXXZ");
300 SET(p__ContextCallback__Reset
, "?_Reset@_ContextCallback@details@Concurrency@@AAAXXZ");
301 SET(p__TaskEventLogger__LogCancelTask
, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAAXXZ");
302 SET(p__TaskEventLogger__LogScheduleTask
, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAAX_N@Z@Z");
303 SET(p__TaskEventLogger__LogTaskCompleted
, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
304 SET(p__TaskEventLogger__LogTaskExecutionCompleted
, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
305 SET(p__TaskEventLogger__LogWorkItemCompleted
, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
306 SET(p__TaskEventLogger__LogWorkItemStarted
, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
308 SET(p_task_continuation_context_ctor
, "??0task_continuation_context@Concurrency@@AAE@XZ");
309 SET(p__ContextCallback__Assign
, "?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z");
310 SET(p__ContextCallback__CallInContext
, "?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z");
311 SET(p__ContextCallback__Capture
, "?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ");
312 SET(p__ContextCallback__Reset
, "?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ");
313 SET(p__TaskEventLogger__LogCancelTask
, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ");
314 SET(p__TaskEventLogger__LogScheduleTask
, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z");
315 SET(p__TaskEventLogger__LogTaskCompleted
, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
316 SET(p__TaskEventLogger__LogTaskExecutionCompleted
, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
317 SET(p__TaskEventLogger__LogWorkItemCompleted
, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
318 SET(p__TaskEventLogger__LogWorkItemStarted
, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
320 SET(p__Schedule_chore
, "?_Schedule_chore@details@Concurrency@@YAHPAU_Threadpool_chore@12@@Z");
321 SET(p__Reschedule_chore
, "?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z");
322 SET(p__Release_chore
, "?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z");
323 SET(p__Winerror_message
, "?_Winerror_message@std@@YAKKPADK@Z");
324 SET(p__Syserror_map
, "?_Syserror_map@std@@YAPBDH@Z");
327 SET(p__Mtx_init
, "_Mtx_init");
328 SET(p__Mtx_destroy
, "_Mtx_destroy");
329 SET(p__Mtx_lock
, "_Mtx_lock");
330 SET(p__Mtx_unlock
, "_Mtx_unlock");
331 SET(p__Cnd_init
, "_Cnd_init");
332 SET(p__Cnd_destroy
, "_Cnd_destroy");
333 SET(p__Cnd_wait
, "_Cnd_wait");
334 SET(p__Cnd_timedwait
, "_Cnd_timedwait");
335 SET(p__Cnd_broadcast
, "_Cnd_broadcast");
336 SET(p__Cnd_signal
, "_Cnd_signal");
337 SET(p__Thrd_create
, "_Thrd_create");
338 SET(p__Thrd_join
, "_Thrd_join");
339 SET(p__Xtime_diff_to_millis2
, "_Xtime_diff_to_millis2");
340 SET(p_xtime_get
, "xtime_get");
342 SET(p_Close_dir
, "_Close_dir");
343 SET(p_Copy_file
, "_Copy_file");
344 SET(p_Current_get
, "_Current_get");
345 SET(p_Current_set
, "_Current_set");
346 SET(p_Equivalent
, "_Equivalent");
347 SET(p_File_size
, "_File_size");
348 SET(p_Resize
, "_Resize");
349 SET(p_Last_write_time
, "_Last_write_time");
350 SET(p_Set_last_write_time
, "_Set_last_write_time");
351 SET(p_Link
, "_Link");
352 SET(p_Lstat
, "_Lstat");
353 SET(p_Make_dir
, "_Make_dir");
354 SET(p_Open_dir
, "_Open_dir");
355 SET(p_Read_dir
, "_Read_dir");
356 SET(p_Remove_dir
, "_Remove_dir");
357 SET(p_Rename
, "_Rename");
358 SET(p_Stat
, "_Stat");
359 SET(p_Symlink
, "_Symlink");
360 SET(p_Temp_get
, "_Temp_get");
361 SET(p_To_byte
, "_To_byte");
362 SET(p_To_wide
, "_To_wide");
363 SET(p_Unlink
, "_Unlink");
365 hdll
= GetModuleHandleA("kernel32.dll");
366 pCreateSymbolicLinkW
= (void*)GetProcAddress(hdll
, "CreateSymbolicLinkW");
368 init_thiscall_thunk();
372 static void test_thrd(void)
374 ok(p__Thrd_id() == GetCurrentThreadId(),
375 "expected same id, got _Thrd_id %u GetCurrentThreadId %lu\n",
376 p__Thrd_id(), GetCurrentThreadId());
379 static void test__Task_impl_base__IsNonBlockingThread(void)
381 ok(!p__Task_impl_base__IsNonBlockingThread(), "_IsNonBlockingThread() returned true\n");
386 const char* export_name
;
387 } vbtable_size_exports_list
[] = {
388 {{0x20, 0x20}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_istream@DU?$char_traits@D@std@@@1@@"},
389 {{0x10, 0x10}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_ostream@DU?$char_traits@D@std@@@1@@"},
390 {{0x20, 0x20}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_istream@GU?$char_traits@G@std@@@1@@"},
391 {{0x10, 0x10}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_ostream@GU?$char_traits@G@std@@@1@@"},
392 {{0x20, 0x20}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_istream@_WU?$char_traits@_W@std@@@1@@"},
393 {{0x10, 0x10}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_ostream@_WU?$char_traits@_W@std@@@1@@"},
394 {{0x18, 0x18}, "??_8?$basic_istream@DU?$char_traits@D@std@@@std@@7B@"},
395 {{0x18, 0x18}, "??_8?$basic_istream@GU?$char_traits@G@std@@@std@@7B@"},
396 {{0x18, 0x18}, "??_8?$basic_istream@_WU?$char_traits@_W@std@@@std@@7B@"},
397 {{ 0x8, 0x10}, "??_8?$basic_ostream@DU?$char_traits@D@std@@@std@@7B@"},
398 {{ 0x8, 0x10}, "??_8?$basic_ostream@GU?$char_traits@G@std@@@std@@7B@"},
399 {{ 0x8, 0x10}, "??_8?$basic_ostream@_WU?$char_traits@_W@std@@@std@@7B@"},
403 static void test_vbtable_size_exports(void)
406 const int *p_vbtable
;
407 int arch_idx
= (sizeof(void*) == 8);
409 for (i
= 0; vbtable_size_exports_list
[i
].export_name
; i
++)
411 SET(p_vbtable
, vbtable_size_exports_list
[i
].export_name
);
413 ok(p_vbtable
[0] == 0, "vbtable[0] wrong, got 0x%x\n", p_vbtable
[0]);
414 ok(p_vbtable
[1] == vbtable_size_exports_list
[i
].value
[arch_idx
],
415 "%d: %s[1] wrong, got 0x%x\n", i
, vbtable_size_exports_list
[i
].export_name
, p_vbtable
[1]);
419 static void test_task_continuation_context(void)
421 task_continuation_context tcc
;
423 memset(&tcc
, 0xff, sizeof(tcc
));
424 call_func1(p_task_continuation_context_ctor
, &tcc
);
425 ok(!tcc
.unk0
, "tcc.unk0 != NULL (%p)\n", tcc
.unk0
);
426 ok(!tcc
.unk1
, "tcc.unk1 != 0 (%x)\n", tcc
.unk1
);
430 static void __cdecl
function_do_call(void *this)
432 CHECK_EXPECT(function_do_call
);
435 static void __cdecl
function_do_clean(void *this, MSVCP_bool b
)
437 CHECK_EXPECT(function_do_clean
);
438 ok(b
, "b == FALSE\n");
442 static void test__ContextCallback(void)
444 _ContextCallback cc
= {0};
445 void *v
= (void*)0xdeadbeef;
447 void* function_vtbl
[] = {
450 (void*)function_do_call
,
452 (void*)function_do_clean
,
455 function_void_cdecl_void function
= { function_vtbl
, NULL
, {0}, {NULL
}, &function
};
456 function_void_cdecl_void function2
= { NULL
, NULL
, {0}, {NULL
}, &function
};
459 call_func2(p__ContextCallback__Assign
, &cc
, v
);
460 ok(!cc
.unused
, "cc.unused = %p\n", cc
.unused
);
461 call_func1(p__ContextCallback__Reset
, &cc
);
462 ok(!cc
.unused
, "cc.unused = %p\n", cc
.unused
);
463 call_func1(p__ContextCallback__Capture
, &cc
);
464 ok(!cc
.unused
, "cc.unused = %p\n", cc
.unused
);
465 ok(!p__ContextCallback__IsCurrentOriginSTA(&cc
), "IsCurrentOriginSTA returned TRUE\n");
468 call_func2(p__ContextCallback__Assign
, &cc
, NULL
);
469 ok(cc
.unused
== v
, "cc.unused = %p\n", cc
.unused
);
470 call_func1(p__ContextCallback__Reset
, &cc
);
471 ok(cc
.unused
== v
, "cc.unused = %p\n", cc
.unused
);
472 call_func1(p__ContextCallback__Capture
, &cc
);
473 ok(cc
.unused
== v
, "cc.unused = %p\n", cc
.unused
);
474 ok(!p__ContextCallback__IsCurrentOriginSTA(&cc
), "IsCurrentOriginSTA returned TRUE\n");
475 ok(cc
.unused
== v
, "cc.unused = %p\n", cc
.unused
);
478 SET_EXPECT(function_do_call
);
479 SET_EXPECT(function_do_clean
);
480 p__ContextCallback__CallInContext(&cc
, function
, FALSE
);
481 CHECK_CALLED(function_do_call
);
482 CHECK_CALLED(function_do_clean
);
484 SET_EXPECT(function_do_call
);
485 SET_EXPECT(function_do_clean
);
486 p__ContextCallback__CallInContext(&cc
, function
, TRUE
);
487 CHECK_CALLED(function_do_call
);
488 CHECK_CALLED(function_do_clean
);
490 SET_EXPECT(function_do_call
);
491 SET_EXPECT(function_do_clean
);
492 p__ContextCallback__CallInContext(&cc
, function2
, FALSE
);
493 CHECK_CALLED(function_do_call
);
494 CHECK_CALLED(function_do_clean
);
496 SET_EXPECT(function_do_call
);
497 SET_EXPECT(function_do_clean
);
498 p__ContextCallback__CallInContext(&cc
, function2
, TRUE
);
499 CHECK_CALLED(function_do_call
);
500 CHECK_CALLED(function_do_clean
);
504 static void test__TaskEventLogger(void)
506 _TaskEventLogger logger
;
507 memset(&logger
, 0, sizeof(logger
));
509 call_func1(p__TaskEventLogger__LogCancelTask
, &logger
);
510 ok(!logger
.task
, "logger.task = %p\n", logger
.task
);
511 ok(!logger
.scheduled
, "logger.scheduled = %x\n", logger
.scheduled
);
512 ok(!logger
.started
, "logger.started = %x\n", logger
.started
);
514 call_func2(p__TaskEventLogger__LogScheduleTask
, &logger
, FALSE
);
515 ok(!logger
.task
, "logger.task = %p\n", logger
.task
);
516 ok(!logger
.scheduled
, "logger.scheduled = %x\n", logger
.scheduled
);
517 ok(!logger
.started
, "logger.started = %x\n", logger
.started
);
519 call_func1(p__TaskEventLogger__LogTaskCompleted
, &logger
);
520 ok(!logger
.task
, "logger.task = %p\n", logger
.task
);
521 ok(!logger
.scheduled
, "logger.scheduled = %x\n", logger
.scheduled
);
522 ok(!logger
.started
, "logger.started = %x\n", logger
.started
);
524 call_func1(p__TaskEventLogger__LogTaskExecutionCompleted
, &logger
);
525 ok(!logger
.task
, "logger.task = %p\n", logger
.task
);
526 ok(!logger
.scheduled
, "logger.scheduled = %x\n", logger
.scheduled
);
527 ok(!logger
.started
, "logger.started = %x\n", logger
.started
);
529 call_func1(p__TaskEventLogger__LogWorkItemCompleted
, &logger
);
530 ok(!logger
.task
, "logger.task = %p\n", logger
.task
);
531 ok(!logger
.scheduled
, "logger.scheduled = %x\n", logger
.scheduled
);
532 ok(!logger
.started
, "logger.started = %x\n", logger
.started
);
534 call_func1(p__TaskEventLogger__LogWorkItemStarted
, &logger
);
535 ok(!logger
.task
, "logger.task = %p\n", logger
.task
);
536 ok(!logger
.scheduled
, "logger.scheduled = %x\n", logger
.scheduled
);
537 ok(!logger
.started
, "logger.started = %x\n", logger
.started
);
539 logger
.task
= (void*)0xdeadbeef;
540 logger
.scheduled
= TRUE
;
541 logger
.started
= TRUE
;
543 call_func1(p__TaskEventLogger__LogCancelTask
, &logger
);
544 ok(logger
.task
== (void*)0xdeadbeef, "logger.task = %p\n", logger
.task
);
545 ok(logger
.scheduled
, "logger.scheduled = FALSE\n");
546 ok(logger
.started
, "logger.started = FALSE\n");
548 call_func2(p__TaskEventLogger__LogScheduleTask
, &logger
, FALSE
);
549 ok(logger
.task
== (void*)0xdeadbeef, "logger.task = %p\n", logger
.task
);
550 ok(logger
.scheduled
, "logger.scheduled = FALSE\n");
551 ok(logger
.started
, "logger.started = FALSE\n");
553 call_func1(p__TaskEventLogger__LogTaskCompleted
, &logger
);
554 ok(logger
.task
== (void*)0xdeadbeef, "logger.task = %p\n", logger
.task
);
555 ok(logger
.scheduled
, "logger.scheduled = FALSE\n");
556 ok(logger
.started
, "logger.started = FALSE\n");
558 call_func1(p__TaskEventLogger__LogTaskExecutionCompleted
, &logger
);
559 ok(logger
.task
== (void*)0xdeadbeef, "logger.task = %p\n", logger
.task
);
560 ok(logger
.scheduled
, "logger.scheduled = FALSE\n");
561 ok(logger
.started
, "logger.started = FALSE\n");
563 call_func1(p__TaskEventLogger__LogWorkItemCompleted
, &logger
);
564 ok(logger
.task
== (void*)0xdeadbeef, "logger.task = %p\n", logger
.task
);
565 ok(logger
.scheduled
, "logger.scheduled = FALSE\n");
566 ok(logger
.started
, "logger.started = FALSE\n");
568 call_func1(p__TaskEventLogger__LogWorkItemStarted
, &logger
);
569 ok(logger
.task
== (void*)0xdeadbeef, "logger.task = %p\n", logger
.task
);
570 ok(logger
.scheduled
, "logger.scheduled = FALSE\n");
571 ok(logger
.started
, "logger.started = FALSE\n");
574 static void __cdecl
chore_callback(void *arg
)
580 static void test_chore(void)
582 HANDLE event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
583 _Threadpool_chore chore
, old_chore
;
587 memset(&chore
, 0, sizeof(chore
));
588 ret
= p__Schedule_chore(&chore
);
589 ok(!ret
, "_Schedule_chore returned %d\n", ret
);
590 ok(chore
.work
!= NULL
, "chore.work == NULL\n");
591 ok(!chore
.callback
, "chore.callback != NULL\n");
592 p__Release_chore(&chore
);
595 chore
.callback
= chore_callback
;
597 ret
= p__Schedule_chore(&chore
);
598 ok(!ret
, "_Schedule_chore returned %d\n", ret
);
599 ok(chore
.work
!= NULL
, "chore.work == NULL\n");
600 ok(chore
.callback
== chore_callback
, "chore.callback = %p, expected %p\n", chore
.callback
, chore_callback
);
601 ok(chore
.arg
== event
, "chore.arg = %p, expected %p\n", chore
.arg
, event
);
602 wait
= WaitForSingleObject(event
, 500);
603 ok(wait
== WAIT_OBJECT_0
, "WaitForSingleObject returned %ld\n", wait
);
605 if(!GetProcAddress(GetModuleHandleA("kernel32"), "CreateThreadpoolWork"))
607 win_skip("_Reschedule_chore not supported\n");
608 p__Release_chore(&chore
);
614 ret
= p__Schedule_chore(&chore
);
615 ok(!ret
, "_Schedule_chore returned %d\n", ret
);
616 ok(old_chore
.work
!= chore
.work
, "new threadpool work was not created\n");
617 p__Release_chore(&old_chore
);
618 wait
= WaitForSingleObject(event
, 500);
619 ok(wait
== WAIT_OBJECT_0
, "WaitForSingleObject returned %ld\n", wait
);
621 ret
= p__Reschedule_chore(&chore
);
622 ok(!ret
, "_Reschedule_chore returned %d\n", ret
);
623 wait
= WaitForSingleObject(event
, 500);
624 ok(wait
== WAIT_OBJECT_0
, "WaitForSingleObject returned %ld\n", wait
);
626 p__Release_chore(&chore
);
627 ok(!chore
.work
, "chore.work != NULL\n");
628 ok(chore
.callback
== chore_callback
, "chore.callback = %p, expected %p\n", chore
.callback
, chore_callback
);
629 ok(chore
.arg
== event
, "chore.arg = %p, expected %p\n", chore
.arg
, event
);
630 p__Release_chore(&chore
);
635 static void test_to_byte(void)
637 static const WCHAR
*tests
[] = {L
"TEST", L
"\x9580\x9581\x9582\x9583"};
639 char dst
[MAX_PATH
+ 4] = "ABC\0XXXXXXX";
640 char compare
[MAX_PATH
+ 4] = "ABC\0XXXXXXX";
643 WCHAR longstr
[MAX_PATH
+ 3];
645 ret
= p_To_byte(NULL
, NULL
);
646 ok(!ret
, "Got unexpected result %d\n", ret
);
647 ret
= p_To_byte(tests
[0], NULL
);
648 ok(!ret
, "Got unexpected result %d\n", ret
);
649 ret
= p_To_byte(NULL
, dst
);
650 ok(!ret
, "Got unexpected result %d\n", ret
);
652 ok(!memcmp(dst
, compare
, sizeof(compare
)), "Destination was modified: %s\n", dst
);
654 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
656 ret
= p_To_byte(tests
[i
], dst
);
657 expected
= WideCharToMultiByte(CP_ACP
, 0, tests
[i
], -1, compare
, ARRAY_SIZE(compare
), NULL
, NULL
);
658 ok(ret
== expected
, "Got unexpected result %d, expected %d, test case %u\n", ret
, expected
, i
);
659 ok(!memcmp(dst
, compare
, sizeof(compare
)), "Got unexpected output %s, test case %u\n", dst
, i
);
662 /* Output length is limited to MAX_PATH.*/
663 for (i
= MAX_PATH
- 2; i
< MAX_PATH
+ 2; ++i
)
665 for (j
= 0; j
< i
; j
++)
668 memset(dst
, 0xff, sizeof(dst
));
669 memset(compare
, 0xff, sizeof(compare
));
671 ret
= p_To_byte(longstr
, dst
);
672 expected
= WideCharToMultiByte(CP_ACP
, 0, longstr
, -1, compare
, MAX_PATH
, NULL
, NULL
);
673 ok(ret
== expected
, "Got unexpected result %d, expected %d, length %u\n", ret
, expected
, i
);
674 ok(!memcmp(dst
, compare
, sizeof(compare
)), "Got unexpected output %s, length %u\n", dst
, i
);
678 static void test_to_wide(void)
680 /* öäü߀Ÿ.A.B in cp1252, the two . are an undefined value and delete.
681 * With a different system codepage it will produce different results, so do not hardcode the
682 * expected output but convert it with MultiByteToWideChar. */
683 static const char special_input
[] = {0xf6, 0xe4, 0xfc, 0xdf, 0x80, 0x9f, 0x81, 0x41, 0x7f, 0x42, 0};
684 static const char *tests
[] = {"Testtest", special_input
};
685 WCHAR dst
[MAX_PATH
+ 4] = {'A', 'B', 'C', 0, 'X', 'X', 'X', 'X', 'X', 'X', 'X'};
686 WCHAR compare
[MAX_PATH
+ 4] = {'A', 'B', 'C', 0, 'X', 'X', 'X', 'X', 'X', 'X', 'X'};
689 char longstr
[MAX_PATH
+ 3];
691 ret
= p_To_wide(NULL
, NULL
);
692 ok(!ret
, "Got unexpected result %d\n", ret
);
693 ret
= p_To_wide(tests
[0], NULL
);
694 ok(!ret
, "Got unexpected result %d\n", ret
);
695 ret
= p_To_wide(NULL
, dst
);
696 ok(!ret
, "Got unexpected result %d\n", ret
);
697 ok(!memcmp(dst
, compare
, sizeof(compare
)), "Destination was modified: %s\n", wine_dbgstr_w(dst
));
699 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
701 ret
= p_To_wide(tests
[i
], dst
);
702 expected
= MultiByteToWideChar(CP_ACP
, 0, tests
[i
], -1, compare
, ARRAY_SIZE(compare
));
703 ok(ret
== expected
, "Got unexpected result %d, expected %d, test case %u\n", ret
, expected
, i
);
704 ok(!memcmp(dst
, compare
, sizeof(compare
)), "Got unexpected output %s, test case %u\n",
705 wine_dbgstr_w(dst
), i
);
708 /* Output length is limited to MAX_PATH.*/
709 for (i
= MAX_PATH
- 2; i
< MAX_PATH
+ 2; ++i
)
711 memset(longstr
, 'A', sizeof(longstr
));
713 memset(dst
, 0xff, sizeof(dst
));
714 memset(compare
, 0xff, sizeof(compare
));
716 ret
= p_To_wide(longstr
, dst
);
717 expected
= MultiByteToWideChar(CP_ACP
, 0, longstr
, -1, compare
, MAX_PATH
);
718 ok(ret
== expected
, "Got unexpected result %d, expected %d, length %u\n", ret
, expected
, i
);
719 ok(!memcmp(dst
, compare
, sizeof(compare
)), "Got unexpected output %s, length %u\n",
720 wine_dbgstr_w(dst
), i
);
724 static void test_File_size(void)
728 LARGE_INTEGER file_size
;
729 WCHAR temp_path
[MAX_PATH
], origin_path
[MAX_PATH
];
732 GetCurrentDirectoryW(MAX_PATH
, origin_path
);
733 GetTempPathW(MAX_PATH
, temp_path
);
734 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
736 CreateDirectoryW(L
"wine_test_dir", NULL
);
738 file
= CreateFileW(L
"wine_test_dir/f1", GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
739 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
740 file_size
.QuadPart
= 7;
741 ok(SetFilePointerEx(file
, file_size
, NULL
, FILE_BEGIN
), "SetFilePointerEx failed\n");
742 ok(SetEndOfFile(file
), "SetEndOfFile failed\n");
744 val
= p_File_size(L
"wine_test_dir/f1");
745 ok(val
== 7, "file_size is %s\n", wine_dbgstr_longlong(val
));
747 file
= CreateFileW(L
"wine_test_dir/f2", GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
748 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
750 val
= p_File_size(L
"wine_test_dir/f2");
751 ok(val
== 0, "file_size is %s\n", wine_dbgstr_longlong(val
));
753 val
= p_File_size(L
"wine_test_dir");
754 ok(val
== 0, "file_size is %s\n", wine_dbgstr_longlong(val
));
757 val
= p_File_size(L
"wine_test_dir/ne");
758 ok(val
== ~(ULONGLONG
)0, "file_size is %s\n", wine_dbgstr_longlong(val
));
759 ok(errno
== 0xdeadbeef, "errno = %d\n", errno
);
762 val
= p_File_size(NULL
);
763 ok(val
== ~(ULONGLONG
)0, "file_size is %s\n", wine_dbgstr_longlong(val
));
764 ok(errno
== 0xdeadbeef, "errno = %d\n", errno
);
766 r
= p_Resize(L
"wine_test_dir/f1", 1000);
767 ok(!r
, "p_Resize returned %d\n", r
);
768 val
= p_File_size(L
"wine_test_dir/f1");
769 ok(val
== 1000, "file_size is %s\n", wine_dbgstr_longlong(val
));
771 r
= p_Resize(L
"wine_test_dir/f1", 100);
772 ok(!r
, "p_Resize returned %d\n", r
);
773 val
= p_File_size(L
"wine_test_dir/f1");
774 ok(val
== 100, "file_size is %s\n", wine_dbgstr_longlong(val
));
776 r
= p_Resize(L
"wine_test_dir/f1", 0);
777 ok(!r
, "p_Resize returned %d\n", r
);
778 val
= p_File_size(L
"wine_test_dir/f1");
779 ok(val
== 0, "file_size is %s\n", wine_dbgstr_longlong(val
));
781 ok(DeleteFileW(L
"wine_test_dir/f1"), "expect wine_test_dir/f1 to exist\n");
783 r
= p_Resize(L
"wine_test_dir/f1", 0);
784 ok(r
== ERROR_FILE_NOT_FOUND
, "p_Resize returned %d\n", r
);
786 ok(DeleteFileW(L
"wine_test_dir/f2"), "expect wine_test_dir/f2 to exist\n");
787 ok(RemoveDirectoryW(L
"wine_test_dir"), "expect wine_test_dir to exist\n");
788 ok(SetCurrentDirectoryW(origin_path
), "SetCurrentDirectoryW to origin_path failed\n");
791 static void test_Current_get(void)
793 WCHAR temp_path
[MAX_PATH
], current_path
[MAX_PATH
], origin_path
[MAX_PATH
];
796 GetCurrentDirectoryW(MAX_PATH
, origin_path
);
797 GetTempPathW(MAX_PATH
, temp_path
);
799 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
800 ret
= p_Current_get(current_path
);
801 ok(ret
== TRUE
, "p_Current_get returned %u\n", ret
);
802 wcscat(current_path
, L
"\\");
803 ok(!wcscmp(temp_path
, current_path
), "p_Current_get(): expect: %s, got %s\n",
804 wine_dbgstr_w(temp_path
), wine_dbgstr_w(current_path
));
806 ok(SetCurrentDirectoryW(origin_path
), "SetCurrentDirectoryW to origin_path failed\n");
807 ret
= p_Current_get(current_path
);
808 ok(ret
== TRUE
, "p_Current_get returned %u\n", ret
);
809 ok(!wcscmp(origin_path
, current_path
), "p_Current_get(): expect: %s, got %s\n",
810 wine_dbgstr_w(origin_path
), wine_dbgstr_w(current_path
));
813 static void test_Current_set(void)
815 WCHAR temp_path
[MAX_PATH
], current_path
[MAX_PATH
], origin_path
[MAX_PATH
];
818 GetTempPathW(MAX_PATH
, temp_path
);
819 GetCurrentDirectoryW(MAX_PATH
, origin_path
);
821 ok(p_Current_set(temp_path
), "p_Current_set to temp_path failed\n");
822 ret
= p_Current_get(current_path
);
823 ok(ret
== TRUE
, "p_Current_get returned %u\n", ret
);
824 wcscat(current_path
, L
"\\");
825 ok(!wcscmp(temp_path
, current_path
), "p_Current_get(): expect: %s, got %s\n",
826 wine_dbgstr_w(temp_path
), wine_dbgstr_w(current_path
));
828 ok(p_Current_set(L
"./"), "p_Current_set to temp_path failed\n");
829 ret
= p_Current_get(current_path
);
830 ok(ret
== TRUE
, "p_Current_get returned %u\n", ret
);
831 wcscat(current_path
, L
"\\");
832 ok(!wcscmp(temp_path
, current_path
), "p_Current_get(): expect: %s, got %s\n",
833 wine_dbgstr_w(temp_path
), wine_dbgstr_w(current_path
));
836 ok(!p_Current_set(L
"not_exist_dir"), "p_Current_set to not_exist_dir succeed\n");
837 ok(errno
== 0xdeadbeef, "errno = %d\n", errno
);
840 ok(!p_Current_set(L
"??invalid_name>>"), "p_Current_set to ??invalid_name>> succeed\n");
841 ok(errno
== 0xdeadbeef, "errno = %d\n", errno
);
843 ok(p_Current_set(origin_path
), "p_Current_set to origin_path failed\n");
844 ret
= p_Current_get(current_path
);
845 ok(ret
== TRUE
, "p_Current_get returned %u\n", ret
);
846 ok(!wcscmp(origin_path
, current_path
), "p_Current_get(): expect: %s, got %s\n",
847 wine_dbgstr_w(origin_path
), wine_dbgstr_w(current_path
));
850 static void test_Stat(void)
852 int i
, perms
, expected_perms
, ret
;
856 WCHAR sys_path
[MAX_PATH
], origin_path
[MAX_PATH
], temp_path
[MAX_PATH
];
863 { NULL
, file_not_found
, 0xdeadbeef, FALSE
},
864 { L
"wine_test_dir", directory_file
, 0777, FALSE
},
865 { L
"wine_test_dir/f1", regular_file
, 0777, FALSE
},
866 { L
"wine_test_dir/f2", regular_file
, 0555, FALSE
},
867 { L
"wine_test_dir/ne", file_not_found
, 0xdeadbeef, FALSE
},
868 { L
"wine_test_dir\\??invalid_name>>", file_not_found
, 0xdeadbeef, FALSE
},
869 { L
"wine_test_dir\\f1_link", regular_file
, 0777, TRUE
},
870 { L
"wine_test_dir\\dir_link", directory_file
, 0777, TRUE
},
873 GetCurrentDirectoryW(MAX_PATH
, origin_path
);
874 GetTempPathW(MAX_PATH
, temp_path
);
875 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
877 CreateDirectoryW(L
"wine_test_dir", NULL
);
879 file
= CreateFileW(L
"wine_test_dir/f1", 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
880 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
881 ok(CloseHandle(file
), "CloseHandle\n");
883 file
= CreateFileW(L
"wine_test_dir/f2", 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
884 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
885 ok(CloseHandle(file
), "CloseHandle\n");
886 SetFileAttributesW(L
"wine_test_dir/f2", FILE_ATTRIBUTE_READONLY
);
888 SetLastError(0xdeadbeef);
889 ret
= pCreateSymbolicLinkW
&& pCreateSymbolicLinkW(
890 L
"wine_test_dir\\f1_link", L
"wine_test_dir/f1", 0);
891 if(!ret
&& (!pCreateSymbolicLinkW
|| GetLastError()==ERROR_PRIVILEGE_NOT_HELD
892 || GetLastError()==ERROR_INVALID_FUNCTION
)) {
893 tests
[6].ret
= tests
[7].ret
= file_not_found
;
894 tests
[6].perms
= tests
[7].perms
= 0xdeadbeef;
895 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
897 ok(ret
, "CreateSymbolicLinkW failed\n");
898 ok(pCreateSymbolicLinkW(L
"wine_test_dir\\dir_link", L
"wine_test_dir", 1),
899 "CreateSymbolicLinkW failed\n");
902 file
= CreateNamedPipeW(L
"\\\\.\\PiPe\\tests_pipe.c",
903 PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
, 2, 1024, 1024,
904 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
905 ok(file
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
907 val
= p_Stat(L
"\\\\.\\PiPe\\tests_pipe.c", &perms
);
908 todo_wine
ok(regular_file
== val
, "_Stat(): expect: regular, got %d\n", val
);
909 todo_wine
ok(0777 == perms
, "_Stat(): perms expect: 0777, got 0%o\n", perms
);
911 val
= p_Lstat(L
"\\\\.\\PiPe\\tests_pipe.c", &perms
);
912 ok(status_unknown
== val
, "_Lstat(): expect: unknown, got %d\n", val
);
913 ok(0xdeadbeef == perms
, "_Lstat(): perms expect: 0xdeadbeef, got %x\n", perms
);
914 ok(CloseHandle(file
), "CloseHandle\n");
915 file
= CreateNamedPipeW(L
"\\\\.\\PiPe\\tests_pipe.c",
916 PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
, 2, 1024, 1024,
917 NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
918 ok(file
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
920 val
= p_Lstat(L
"\\\\.\\PiPe\\tests_pipe.c", &perms
);
921 todo_wine
ok(regular_file
== val
, "_Lstat(): expect: regular, got %d\n", val
);
922 todo_wine
ok(0777 == perms
, "_Lstat(): perms expect: 0777, got 0%o\n", perms
);
923 ok(CloseHandle(file
), "CloseHandle\n");
925 for(i
=0; i
<ARRAY_SIZE(tests
); i
++) {
927 val
= p_Stat(tests
[i
].path
, &perms
);
928 todo_wine_if(tests
[i
].is_todo
) {
929 ok(tests
[i
].ret
== val
, "_Stat(): test %d expect: %d, got %d\n", i
+1, tests
[i
].ret
, val
);
930 ok(tests
[i
].perms
== perms
, "_Stat(): test %d perms expect: 0%o, got 0%o\n",
931 i
+1, tests
[i
].perms
, perms
);
933 val
= p_Stat(tests
[i
].path
, NULL
);
934 todo_wine_if(tests
[i
].is_todo
)
935 ok(tests
[i
].ret
== val
, "_Stat(): test %d expect: %d, got %d\n", i
+1, tests
[i
].ret
, val
);
939 val
= p_Lstat(tests
[i
].path
, &perms
);
940 todo_wine_if(tests
[i
].is_todo
) {
941 ok(tests
[i
].ret
== val
, "_Lstat(): test %d expect: %d, got %d\n", i
+1, tests
[i
].ret
, val
);
942 ok(tests
[i
].perms
== perms
, "_Lstat(): test %d perms expect: 0%o, got 0%o\n",
943 i
+1, tests
[i
].perms
, perms
);
945 val
= p_Lstat(tests
[i
].path
, NULL
);
946 todo_wine_if(tests
[i
].is_todo
)
947 ok(tests
[i
].ret
== val
, "_Lstat(): test %d expect: %d, got %d\n", i
+1, tests
[i
].ret
, val
);
950 GetSystemDirectoryW(sys_path
, MAX_PATH
);
951 attr
= GetFileAttributesW(sys_path
);
952 expected_perms
= (attr
& FILE_ATTRIBUTE_READONLY
) ? 0555 : 0777;
954 val
= p_Stat(sys_path
, &perms
);
955 ok(directory_file
== val
, "_Stat(): expect: regular, got %d\n", val
);
956 ok(perms
== expected_perms
, "_Stat(): perms expect: 0%o, got 0%o\n", expected_perms
, perms
);
959 todo_wine
ok(DeleteFileW(L
"wine_test_dir\\f1_link"),
960 "expect wine_test_dir/f1_link to exist\n");
961 todo_wine
ok(RemoveDirectoryW(L
"wine_test_dir\\dir_link"),
962 "expect wine_test_dir/dir_link to exist\n");
964 ok(DeleteFileW(L
"wine_test_dir/f1"), "expect wine_test_dir/f1 to exist\n");
965 SetFileAttributesW(L
"wine_test_dir/f2", FILE_ATTRIBUTE_NORMAL
);
966 ok(DeleteFileW(L
"wine_test_dir/f2"), "expect wine_test_dir/f2 to exist\n");
967 ok(RemoveDirectoryW(L
"wine_test_dir"), "expect wine_test_dir to exist\n");
969 ok(SetCurrentDirectoryW(origin_path
), "SetCurrentDirectoryW to origin_path failed\n");
972 static void test_dir_operation(void)
974 WCHAR
*file_name
, first_file_name
[MAX_PATH
], dest
[MAX_PATH
], longer_path
[MAX_PATH
];
975 WCHAR origin_path
[MAX_PATH
], temp_path
[MAX_PATH
];
976 HANDLE file
, result_handle
;
978 int err
, num_of_f1
= 0, num_of_f2
= 0, num_of_sub_dir
= 0, num_of_other_files
= 0;
980 GetCurrentDirectoryW(MAX_PATH
, origin_path
);
981 GetTempPathW(MAX_PATH
, temp_path
);
982 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
984 CreateDirectoryW(L
"wine_test_dir", NULL
);
985 file
= CreateFileW(L
"wine_test_dir/f1", 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
986 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
988 file
= CreateFileW(L
"wine_test_dir/f2", 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
989 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
991 CreateDirectoryW(L
"wine_test_dir/sub_dir", NULL
);
992 file
= CreateFileW(L
"wine_test_dir/sub_dir/f1", 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
993 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
996 memcpy(longer_path
, temp_path
, sizeof(longer_path
));
997 wcscat(longer_path
, L
"\\wine_test_dir\\");
998 while(lstrlenW(longer_path
) < MAX_PATH
-1)
999 wcscat(longer_path
, L
"s");
1000 memset(first_file_name
, 0xff, sizeof(first_file_name
));
1001 type
= err
= 0xdeadbeef;
1002 result_handle
= NULL
;
1003 result_handle
= p_Open_dir(first_file_name
, longer_path
, &err
, &type
);
1004 ok(result_handle
== NULL
, "_Open_dir(): expect NULL, got %p\n", result_handle
);
1005 ok(!*first_file_name
, "_Open_dir(): expect: 0, got %s\n", wine_dbgstr_w(first_file_name
));
1006 ok(err
== ERROR_BAD_PATHNAME
, "_Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err
);
1007 ok((int)type
== 0xdeadbeef, "_Open_dir(): expect 0xdeadbeef, got %d\n", type
);
1009 memset(first_file_name
, 0xff, sizeof(first_file_name
));
1010 memset(dest
, 0, sizeof(dest
));
1011 err
= type
= 0xdeadbeef;
1012 result_handle
= NULL
;
1013 result_handle
= p_Open_dir(first_file_name
, L
"wine_test_dir", &err
, &type
);
1014 ok(result_handle
!= NULL
, "_Open_dir(): expect: not NULL, got %p\n", result_handle
);
1015 ok(err
== ERROR_SUCCESS
, "_Open_dir(): expect: ERROR_SUCCESS, got %d\n", err
);
1016 file_name
= first_file_name
;
1018 if (!wcscmp(file_name
, L
"f1")) {
1020 ok(type
== regular_file
, "expect regular_file, got %d\n", type
);
1021 }else if(!wcscmp(file_name
, L
"f2")) {
1023 ok(type
== regular_file
, "expect regular_file, got %d\n", type
);
1024 }else if(!wcscmp(file_name
, L
"sub_dir")) {
1026 ok(type
== directory_file
, "expect directory_file, got %d\n", type
);
1028 ++num_of_other_files
;
1030 file_name
= p_Read_dir(dest
, result_handle
, &type
);
1032 ok(type
== status_unknown
, "_Read_dir(): expect: status_unknown, got %d\n", type
);
1033 p_Close_dir(result_handle
);
1034 ok(result_handle
!= NULL
, "_Open_dir(): expect: not NULL, got %p\n", result_handle
);
1035 ok(num_of_f1
== 1, "found f1 %d times\n", num_of_f1
);
1036 ok(num_of_f2
== 1, "found f2 %d times\n", num_of_f2
);
1037 ok(num_of_sub_dir
== 1, "found sub_dir %d times\n", num_of_sub_dir
);
1038 ok(num_of_other_files
== 0, "found %d other files\n", num_of_other_files
);
1040 memset(first_file_name
, 0xff, sizeof(first_file_name
));
1041 err
= type
= 0xdeadbeef;
1042 result_handle
= file
;
1043 result_handle
= p_Open_dir(first_file_name
, L
"not_exist", &err
, &type
);
1044 ok(result_handle
== NULL
, "_Open_dir(): expect: NULL, got %p\n", result_handle
);
1045 ok(err
== ERROR_BAD_PATHNAME
, "_Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err
);
1046 ok((int)type
== 0xdeadbeef, "_Open_dir(): expect: 0xdeadbeef, got %d\n", type
);
1047 ok(!*first_file_name
, "_Open_dir(): expect: 0, got %s\n", wine_dbgstr_w(first_file_name
));
1049 CreateDirectoryW(L
"empty_dir", NULL
);
1050 memset(first_file_name
, 0xff, sizeof(first_file_name
));
1051 err
= type
= 0xdeadbeef;
1052 result_handle
= file
;
1053 result_handle
= p_Open_dir(first_file_name
, L
"empty_dir", &err
, &type
);
1054 ok(result_handle
== NULL
, "_Open_dir(): expect: NULL, got %p\n", result_handle
);
1055 ok(err
== ERROR_SUCCESS
, "_Open_dir(): expect: ERROR_SUCCESS, got %d\n", err
);
1056 ok(type
== status_unknown
, "_Open_dir(): expect: status_unknown, got %d\n", type
);
1057 ok(!*first_file_name
, "_Open_dir(): expect: 0, got %s\n", wine_dbgstr_w(first_file_name
));
1058 p_Close_dir(result_handle
);
1059 ok(result_handle
== NULL
, "_Open_dir(): expect: NULL, got %p\n", result_handle
);
1061 ok(RemoveDirectoryW(L
"empty_dir"), "expect empty_dir to exist\n");
1062 ok(DeleteFileW(L
"wine_test_dir/sub_dir/f1"), "expect wine_test_dir/sub_dir/sub_f1 to exist\n");
1063 ok(RemoveDirectoryW(L
"wine_test_dir/sub_dir"), "expect wine_test_dir/sub_dir to exist\n");
1064 ok(DeleteFileW(L
"wine_test_dir/f1"), "expect wine_test_dir/f1 to exist\n");
1065 ok(DeleteFileW(L
"wine_test_dir/f2"), "expect wine_test_dir/f2 to exist\n");
1066 ok(RemoveDirectoryW(L
"wine_test_dir"), "expect wine_test_dir to exist\n");
1068 ok(SetCurrentDirectoryW(origin_path
), "SetCurrentDirectoryW to origin_path failed\n");
1071 static void test_Unlink(void)
1073 WCHAR temp_path
[MAX_PATH
], current_path
[MAX_PATH
];
1076 LARGE_INTEGER file_size
;
1082 { L
"wine_test_dir\\f1_symlink", ERROR_SUCCESS
, TRUE
},
1083 { L
"wine_test_dir\\f1_link", ERROR_SUCCESS
, FALSE
},
1084 { L
"wine_test_dir\\f1", ERROR_SUCCESS
, FALSE
},
1085 { L
"wine_test_dir", ERROR_ACCESS_DENIED
, FALSE
},
1086 { L
"not_exist", ERROR_FILE_NOT_FOUND
, FALSE
},
1087 { L
"not_exist_dir\\not_exist_file", ERROR_PATH_NOT_FOUND
, FALSE
},
1088 { NULL
, ERROR_PATH_NOT_FOUND
, FALSE
}
1091 GetCurrentDirectoryW(MAX_PATH
, current_path
);
1092 GetTempPathW(MAX_PATH
, temp_path
);
1093 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
1095 ret
= p_Make_dir(L
"wine_test_dir");
1096 ok(ret
== 1, "_Make_dir(): expect 1 got %d\n", ret
);
1097 file
= CreateFileW(L
"wine_test_dir\\f1", GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
1098 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1099 file_size
.QuadPart
= 7;
1100 ok(SetFilePointerEx(file
, file_size
, NULL
, FILE_BEGIN
), "SetFilePointerEx failed\n");
1101 ok(SetEndOfFile(file
), "SetEndOfFile failed\n");
1104 ret
= p_Symlink(L
"wine_test_dir\\f1", L
"wine_test_dir\\f1_symlink");
1105 if(ret
==ERROR_PRIVILEGE_NOT_HELD
|| ret
==ERROR_INVALID_FUNCTION
|| ret
==ERROR_CALL_NOT_IMPLEMENTED
) {
1106 tests
[0].last_error
= ERROR_FILE_NOT_FOUND
;
1107 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
1109 ok(ret
== ERROR_SUCCESS
, "_Symlink(): expect: ERROR_SUCCESS, got %d\n", ret
);
1111 ret
= p_Link(L
"wine_test_dir\\f1", L
"wine_test_dir\\f1_link");
1112 ok(ret
== ERROR_SUCCESS
, "_Link(): expect: ERROR_SUCCESS, got %d\n", ret
);
1114 for(i
=0; i
<ARRAY_SIZE(tests
); i
++) {
1116 ret
= p_Unlink(tests
[i
].path
);
1117 todo_wine_if(tests
[i
].is_todo
)
1118 ok(ret
== tests
[i
].last_error
, "_Unlink(): test %d expect: %d, got %d\n",
1119 i
+1, tests
[i
].last_error
, ret
);
1120 ok(errno
== 0xdeadbeef, "_Unlink(): test %d errno expect: 0xdeadbeef, got %d\n", i
+1, ret
);
1123 ok(!DeleteFileW(L
"wine_test_dir\\f1"), "expect wine_test_dir/f1 not to exist\n");
1124 ok(!DeleteFileW(L
"wine_test_dir\\f1_link"), "expect wine_test_dir/f1_link not to exist\n");
1125 ok(!DeleteFileW(L
"wine_test_dir\\f1_symlink"), "expect wine_test_dir/f1_symlink not to exist\n");
1126 ret
= p_Remove_dir(L
"wine_test_dir");
1127 ok(ret
== 1, "_Remove_dir(): expect 1 got %d\n", ret
);
1129 ok(SetCurrentDirectoryW(current_path
), "SetCurrentDirectoryW failed\n");
1132 static void test_Temp_get(void)
1134 WCHAR path
[MAX_PATH
+ 1], temp_path
[MAX_PATH
];
1138 GetTempPathW(ARRAY_SIZE(temp_path
), temp_path
);
1140 /* This crashes on Windows, the input pointer is not validated. */
1143 retval
= p_Temp_get(NULL
);
1144 ok(!retval
, "_Temp_get(): Got %p\n", retval
);
1147 memset(path
, 0xaa, sizeof(path
));
1148 retval
= p_Temp_get(path
);
1149 ok(retval
== path
, "_Temp_get(): Got %p, expected %p\n", retval
, path
);
1150 ok(!wcscmp(path
, temp_path
), "Expected path %s, got %s\n", wine_dbgstr_w(temp_path
), wine_dbgstr_w(path
));
1152 todo_wine
ok(path
[len
+ 1] == 0xaaaa, "Too many bytes were zeroed - %x\n", path
[len
+ 1]);
1155 static void test_Rename(void)
1158 HANDLE file
, h1
, h2
;
1159 BY_HANDLE_FILE_INFORMATION info1
, info2
;
1160 WCHAR temp_path
[MAX_PATH
], current_path
[MAX_PATH
];
1161 LARGE_INTEGER file_size
;
1162 static const struct {
1163 const WCHAR
*old_path
;
1164 const WCHAR
*new_path
;
1167 { L
"wine_test_dir\\f1", L
"wine_test_dir\\f1_rename", ERROR_SUCCESS
},
1168 { L
"wine_test_dir\\f1", NULL
, ERROR_FILE_NOT_FOUND
},
1169 { L
"wine_test_dir\\f1", L
"wine_test_dir\\f1_rename", ERROR_FILE_NOT_FOUND
},
1170 { NULL
, L
"wine_test_dir\\f1_rename2", ERROR_PATH_NOT_FOUND
},
1171 { L
"wine_test_dir\\f1_rename", L
"wine_test_dir\\??invalid>", ERROR_INVALID_NAME
},
1172 { L
"wine_test_dir\\not_exist2", L
"wine_test_dir\\not_exist2", ERROR_FILE_NOT_FOUND
},
1173 { L
"wine_test_dir\\not_exist2", L
"wine_test_dir\\??invalid>", ERROR_FILE_NOT_FOUND
}
1176 GetCurrentDirectoryW(MAX_PATH
, current_path
);
1177 GetTempPathW(MAX_PATH
, temp_path
);
1178 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
1179 ret
= p_Make_dir(L
"wine_test_dir");
1181 ok(ret
== 1, "_Make_dir(): expect 1 got %d\n", ret
);
1182 file
= CreateFileW(L
"wine_test_dir\\f1", GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
1183 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1186 ret
= p_Rename(L
"wine_test_dir\\f1", L
"wine_test_dir\\f1");
1187 ok(ERROR_SUCCESS
== ret
, "_Rename(): expect: ERROR_SUCCESS, got %d\n", ret
);
1188 for(i
=0; i
<ARRAY_SIZE(tests
); i
++) {
1190 if(tests
[i
].val
== ERROR_SUCCESS
) {
1191 h1
= CreateFileW(tests
[i
].old_path
, 0, FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1192 NULL
, OPEN_EXISTING
, 0, 0);
1193 ok(h1
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1194 ok(GetFileInformationByHandle(h1
, &info1
), "GetFileInformationByHandle failed\n");
1197 SetLastError(0xdeadbeef);
1198 ret
= p_Rename(tests
[i
].old_path
, tests
[i
].new_path
);
1199 ok(ret
== tests
[i
].val
, "_Rename(): test %d expect: %d, got %d\n", i
+1, tests
[i
].val
, ret
);
1200 ok(errno
== 0xdeadbeef, "_Rename(): test %d errno expect 0xdeadbeef, got %d\n", i
+1, errno
);
1201 if(ret
== ERROR_SUCCESS
) {
1202 h2
= CreateFileW(tests
[i
].new_path
, 0, FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1203 NULL
, OPEN_EXISTING
, 0, 0);
1204 ok(h2
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1205 ok(GetFileInformationByHandle(h2
, &info2
), "GetFileInformationByHandle failed\n");
1207 ok(info1
.nFileIndexHigh
== info2
.nFileIndexHigh
1208 && info1
.nFileIndexLow
== info2
.nFileIndexLow
,
1209 "_Rename(): test %d expect two files equivalent\n", i
+1);
1213 file
= CreateFileW(L
"wine_test_dir\\f1", GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
1214 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1215 file_size
.QuadPart
= 7;
1216 ok(SetFilePointerEx(file
, file_size
, NULL
, FILE_BEGIN
), "SetFilePointerEx failed\n");
1217 ok(SetEndOfFile(file
), "SetEndOfFile failed\n");
1219 ret
= p_Rename(L
"wine_test_dir\\f1", L
"wine_test_dir\\f1_rename");
1220 ok(ret
== ERROR_ALREADY_EXISTS
, "_Rename(): expect: ERROR_ALREADY_EXISTS, got %d\n", ret
);
1221 ok(p_File_size(L
"wine_test_dir\\f1") == 7, "_Rename(): expect: 7, got %s\n",
1222 wine_dbgstr_longlong(p_File_size(L
"wine_test_dir\\f1")));
1223 ok(p_File_size(L
"wine_test_dir\\f1_rename") == 0, "_Rename(): expect: 0, got %s\n",
1224 wine_dbgstr_longlong(p_File_size(L
"wine_test_dir\\f1_rename")));
1226 ok(DeleteFileW(L
"wine_test_dir\\f1_rename"), "expect f1_rename to exist\n");
1227 ok(DeleteFileW(L
"wine_test_dir\\f1"), "expect f1 to exist\n");
1228 ret
= p_Remove_dir(L
"wine_test_dir");
1229 ok(ret
== 1, "_Remove_dir(): expect %d got %d\n", 1, ret
);
1230 ok(SetCurrentDirectoryW(current_path
), "SetCurrentDirectoryW failed\n");
1233 static void test_Last_write_time(void)
1238 __int64 last_write_time
, newtime
, margin_of_error
= 10 * TICKSPERSEC
;
1239 WCHAR temp_path
[MAX_PATH
], origin_path
[MAX_PATH
];
1241 GetCurrentDirectoryW(ARRAY_SIZE(origin_path
), origin_path
);
1242 GetTempPathW(ARRAY_SIZE(temp_path
), temp_path
);
1243 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
1245 ret
= p_Make_dir(L
"wine_test_dir");
1246 ok(ret
== 1, "_Make_dir() expect 1 got %d\n", ret
);
1248 file
= CreateFileW(L
"wine_test_dir\\f1", GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
1249 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1252 last_write_time
= p_Last_write_time(L
"wine_test_dir\\f1");
1253 newtime
= last_write_time
+ 222222;
1254 p_Set_last_write_time(L
"wine_test_dir\\f1", newtime
);
1255 ok(last_write_time
!= p_Last_write_time(L
"wine_test_dir\\f1"),
1256 "last_write_time should have changed: %s\n",
1257 wine_dbgstr_longlong(last_write_time
));
1259 /* test the formula */
1260 file
= CreateFileW(L
"wine_test_dir\\f1", 0, FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1261 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
1262 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1263 ok(GetFileTime(file
, 0, 0, &lwt
), "GetFileTime failed\n");
1265 last_write_time
= (((__int64
)lwt
.dwHighDateTime
)<< 32) + lwt
.dwLowDateTime
;
1266 last_write_time
-= TICKS_1601_TO_1970
;
1267 ok(newtime
-margin_of_error
<=last_write_time
&& last_write_time
<=newtime
+margin_of_error
,
1268 "don't fit the formula, last_write_time is %s expected %s\n",
1269 wine_dbgstr_longlong(newtime
), wine_dbgstr_longlong(last_write_time
));
1272 p_Set_last_write_time(L
"wine_test_dir\\f1", newtime
);
1273 newtime
= p_Last_write_time(L
"wine_test_dir\\f1");
1274 file
= CreateFileW(L
"wine_test_dir\\f1", 0, FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1275 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
1276 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1277 ok(GetFileTime(file
, 0, 0, &lwt
), "GetFileTime failed\n");
1279 last_write_time
= (((__int64
)lwt
.dwHighDateTime
)<< 32) + lwt
.dwLowDateTime
;
1280 last_write_time
-= TICKS_1601_TO_1970
;
1281 ok(newtime
-margin_of_error
<=last_write_time
&& last_write_time
<=newtime
+margin_of_error
,
1282 "don't fit the formula, last_write_time is %s expected %s\n",
1283 wine_dbgstr_longlong(newtime
), wine_dbgstr_longlong(last_write_time
));
1285 newtime
= 123456789;
1286 p_Set_last_write_time(L
"wine_test_dir\\f1", newtime
);
1287 newtime
= p_Last_write_time(L
"wine_test_dir\\f1");
1288 file
= CreateFileW(L
"wine_test_dir\\f1", 0, FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1289 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
1290 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1291 ok(GetFileTime(file
, 0, 0, &lwt
), "GetFileTime failed\n");
1293 last_write_time
= (((__int64
)lwt
.dwHighDateTime
)<< 32) + lwt
.dwLowDateTime
;
1294 last_write_time
-= TICKS_1601_TO_1970
;
1295 ok(newtime
-margin_of_error
<=last_write_time
&& last_write_time
<=newtime
+margin_of_error
,
1296 "don't fit the formula, last_write_time is %s expected %s\n",
1297 wine_dbgstr_longlong(newtime
), wine_dbgstr_longlong(last_write_time
));
1300 last_write_time
= p_Last_write_time(L
"wine_test_dir\\not_exist");
1301 ok(errno
== 0xdeadbeef, "_Set_last_write_time(): errno expect 0xdeadbeef, got %d\n", errno
);
1302 ok(last_write_time
== -1, "expect -1 got %s\n", wine_dbgstr_longlong(last_write_time
));
1303 last_write_time
= p_Last_write_time(NULL
);
1304 ok(last_write_time
== -1, "expect -1 got %s\n", wine_dbgstr_longlong(last_write_time
));
1307 p_Set_last_write_time(L
"wine_test_dir\\not_exist", newtime
);
1308 ok(errno
== 0xdeadbeef, "_Set_last_write_time(): errno expect 0xdeadbeef, got %d\n", errno
);
1309 p_Set_last_write_time(NULL
, newtime
);
1310 ok(errno
== 0xdeadbeef, "_Set_last_write_time(): errno expect 0xdeadbeef, got %d\n", errno
);
1312 ok(DeleteFileW(L
"wine_test_dir\\f1"), "expect wine_test_dir/f1 to exist\n");
1313 ret
= p_Remove_dir(L
"wine_test_dir");
1314 ok(ret
== 1, "p_Remove_dir(): expect 1 got %d\n", ret
);
1315 ok(SetCurrentDirectoryW(origin_path
), "SetCurrentDirectoryW to origin_path failed\n");
1318 static void test__Winerror_message(void)
1320 char buf
[256], buf_fm
[256];
1323 ret_fm
= FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
1324 NULL
, 0, 0, buf_fm
, sizeof(buf_fm
), NULL
);
1326 memset(buf
, 'a', sizeof(buf
));
1327 ret
= p__Winerror_message(0, buf
, sizeof(buf
));
1328 ok(ret
== ret_fm
|| (ret_fm
> 2 && buf_fm
[ret_fm
- 1] == '\n' &&
1329 buf_fm
[ret_fm
- 2] == '\r' && ret
+ 2 == ret_fm
),
1330 "ret = %lu, expected %lu\n", ret
, ret_fm
);
1331 ok(!strncmp(buf
, buf_fm
, ret
), "buf = %s, expected %s\n", buf
, buf_fm
);
1333 memset(buf
, 'a', sizeof(buf
));
1334 ret
= p__Winerror_message(0, buf
, 2);
1335 ok(!ret
, "ret = %lu\n", ret
);
1336 ok(buf
[0] == 'a', "buf = %s\n", buf
);
1339 static void test__Winerror_map(void)
1346 {ERROR_INVALID_FUNCTION
, ENOSYS
}, {ERROR_FILE_NOT_FOUND
, ENOENT
},
1347 {ERROR_PATH_NOT_FOUND
, ENOENT
}, {ERROR_TOO_MANY_OPEN_FILES
, EMFILE
},
1348 {ERROR_ACCESS_DENIED
, EACCES
}, {ERROR_INVALID_HANDLE
, EINVAL
},
1349 {ERROR_NOT_ENOUGH_MEMORY
, ENOMEM
}, {ERROR_INVALID_ACCESS
, EACCES
},
1350 {ERROR_OUTOFMEMORY
, ENOMEM
}, {ERROR_INVALID_DRIVE
, ENODEV
},
1351 {ERROR_CURRENT_DIRECTORY
, EACCES
}, {ERROR_NOT_SAME_DEVICE
, EXDEV
},
1352 {ERROR_WRITE_PROTECT
, EACCES
}, {ERROR_BAD_UNIT
, ENODEV
},
1353 {ERROR_NOT_READY
, EAGAIN
}, {ERROR_SEEK
, EIO
}, {ERROR_WRITE_FAULT
, EIO
},
1354 {ERROR_READ_FAULT
, EIO
}, {ERROR_SHARING_VIOLATION
, EACCES
},
1355 {ERROR_LOCK_VIOLATION
, ENOLCK
}, {ERROR_HANDLE_DISK_FULL
, ENOSPC
},
1356 {ERROR_NOT_SUPPORTED
, ENOTSUP
, TRUE
}, {ERROR_DEV_NOT_EXIST
, ENODEV
},
1357 {ERROR_FILE_EXISTS
, EEXIST
}, {ERROR_CANNOT_MAKE
, EACCES
},
1358 {ERROR_INVALID_PARAMETER
, EINVAL
, TRUE
}, {ERROR_OPEN_FAILED
, EIO
},
1359 {ERROR_BUFFER_OVERFLOW
, ENAMETOOLONG
}, {ERROR_DISK_FULL
, ENOSPC
},
1360 {ERROR_INVALID_NAME
, ENOENT
, TRUE
, EINVAL
}, {ERROR_NEGATIVE_SEEK
, EINVAL
},
1361 {ERROR_BUSY_DRIVE
, EBUSY
}, {ERROR_DIR_NOT_EMPTY
, ENOTEMPTY
},
1362 {ERROR_BUSY
, EBUSY
}, {ERROR_ALREADY_EXISTS
, EEXIST
},
1363 {ERROR_LOCKED
, ENOLCK
}, {ERROR_DIRECTORY
, EINVAL
},
1364 {ERROR_OPERATION_ABORTED
, ECANCELED
}, {ERROR_NOACCESS
, EACCES
},
1365 {ERROR_CANTOPEN
, EIO
}, {ERROR_CANTREAD
, EIO
}, {ERROR_CANTWRITE
, EIO
},
1366 {ERROR_RETRY
, EAGAIN
}, {ERROR_OPEN_FILES
, EBUSY
},
1367 {ERROR_DEVICE_IN_USE
, EBUSY
}, {ERROR_REPARSE_TAG_INVALID
, EINVAL
, TRUE
},
1368 {WSAEINTR
, EINTR
}, {WSAEBADF
, EBADF
}, {WSAEACCES
, EACCES
},
1369 {WSAEFAULT
, EFAULT
}, {WSAEINVAL
, EINVAL
}, {WSAEMFILE
, EMFILE
},
1370 {WSAEWOULDBLOCK
, EWOULDBLOCK
}, {WSAEINPROGRESS
, EINPROGRESS
},
1371 {WSAEALREADY
, EALREADY
}, {WSAENOTSOCK
, ENOTSOCK
},
1372 {WSAEDESTADDRREQ
, EDESTADDRREQ
}, {WSAEMSGSIZE
, EMSGSIZE
},
1373 {WSAEPROTOTYPE
, EPROTOTYPE
}, {WSAENOPROTOOPT
, ENOPROTOOPT
},
1374 {WSAEPROTONOSUPPORT
, EPROTONOSUPPORT
}, {WSAEOPNOTSUPP
, EOPNOTSUPP
},
1375 {WSAEAFNOSUPPORT
, EAFNOSUPPORT
}, {WSAEADDRINUSE
, EADDRINUSE
},
1376 {WSAEADDRNOTAVAIL
, EADDRNOTAVAIL
}, {WSAENETDOWN
, ENETDOWN
},
1377 {WSAENETUNREACH
, ENETUNREACH
}, {WSAENETRESET
, ENETRESET
},
1378 {WSAECONNABORTED
, ECONNABORTED
}, {WSAECONNRESET
, ECONNRESET
},
1379 {WSAENOBUFS
, ENOBUFS
}, {WSAEISCONN
, EISCONN
}, {WSAENOTCONN
, ENOTCONN
},
1380 {WSAETIMEDOUT
, ETIMEDOUT
}, {WSAECONNREFUSED
, ECONNREFUSED
},
1381 {WSAENAMETOOLONG
, ENAMETOOLONG
}, {WSAEHOSTUNREACH
, EHOSTUNREACH
}
1385 for(i
=0; i
<ARRAY_SIZE(tests
); i
++)
1387 ret
= p__Winerror_map(tests
[i
].winerr
);
1388 ok(ret
== tests
[i
].doserr
|| broken(tests
[i
].broken
&& ret
== tests
[i
].broken_doserr
),
1389 "_Winerror_map(%d) returned %d, expected %d\n",
1390 tests
[i
].winerr
, ret
, tests
[i
].doserr
);
1394 static void test__Syserror_map(void)
1396 const char *r1
, *r2
;
1398 r1
= p__Syserror_map(0);
1399 ok(r1
!= NULL
, "_Syserror_map(0) returned NULL\n");
1400 r1
= p__Syserror_map(1233);
1401 ok(r1
!= NULL
, "_Syserror_map(1233) returned NULL\n");
1402 r2
= p__Syserror_map(1234);
1403 ok(r2
!= NULL
, "_Syserror_map(1234) returned NULL\n");
1404 ok(r1
== r2
, "r1 = %p(%s), r2 = %p(%s)\n", r1
, r1
, r2
, r2
);
1407 static void test_Equivalent(void)
1411 WCHAR temp_path
[MAX_PATH
], current_path
[MAX_PATH
];
1412 static const struct {
1418 { NULL
, L
"wine_test_dir/f1", 0 },
1419 { L
"wine_test_dir/f1", NULL
, 0 },
1420 { L
"wine_test_dir/f1", L
"wine_test_dir", 0 },
1421 { L
"wine_test_dir", L
"wine_test_dir/f1", 0 },
1422 { L
"wine_test_dir/./f1", L
"wine_test_dir/f2", 0 },
1423 { L
"wine_test_dir/f1", L
"wine_test_dir/f1", 1 },
1424 { L
"not_exists_file", L
"wine_test_dir/f1", 0 },
1425 { L
"wine_test_dir\\f1", L
"wine_test_dir/./f1", 1 },
1426 { L
"not_exists_file", L
"not_exists_file", -1 },
1427 { L
"wine_test_dir/f1", L
"not_exists_file", 0 },
1428 { L
"wine_test_dir/../wine_test_dir/f1", L
"wine_test_dir/f1", 1 }
1431 GetCurrentDirectoryW(MAX_PATH
, current_path
);
1432 GetTempPathW(MAX_PATH
, temp_path
);
1433 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
1434 CreateDirectoryW(L
"wine_test_dir", NULL
);
1436 file
= CreateFileW(L
"wine_test_dir/f1", 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
1437 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1439 file
= CreateFileW(L
"wine_test_dir/f2", 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
1440 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1443 for(i
=0; i
<ARRAY_SIZE(tests
); i
++) {
1445 val
= p_Equivalent(tests
[i
].path1
, tests
[i
].path2
);
1446 ok(tests
[i
].equivalent
== val
, "_Equivalent(): test %d expect: %d, got %d\n", i
+1, tests
[i
].equivalent
, val
);
1447 ok(errno
== 0xdeadbeef, "errno = %d\n", errno
);
1451 val
= p_Equivalent(L
"wine_test_dir", L
"wine_test_dir");
1452 ok(val
== 1 || broken(val
== -1), "_Equivalent() returned %d, expected %d\n", val
, 1);
1453 ok(errno
== 0xdeadbeef, "errno = %d\n", errno
);
1455 ok(DeleteFileW(L
"wine_test_dir/f1"), "expect wine_test_dir/f1 to exist\n");
1456 ok(DeleteFileW(L
"wine_test_dir/f2"), "expect wine_test_dir/f2 to exist\n");
1457 ok(p_Remove_dir(L
"wine_test_dir"), "expect wine_test_dir to exist\n");
1458 ok(SetCurrentDirectoryW(current_path
), "SetCurrentDirectoryW failed\n");
1461 #define NUM_THREADS 10
1462 #define TIMEDELTA 250 /* 250 ms uncertainty allowed */
1474 static int __cdecl
cnd_wait_thread(void *arg
)
1476 struct cndmtx
*cm
= arg
;
1479 p__Mtx_lock(cm
->mtx
);
1481 if(InterlockedIncrement(&cm
->started
) == cm
->thread_no
)
1482 SetEvent(cm
->initialized
);
1484 if(cm
->timed_wait
) {
1487 p_xtime_get(&xt
, 1);
1489 r
= p__Cnd_timedwait(cm
->cnd
, cm
->mtx
, &xt
);
1490 ok(!r
, "timed wait failed\n");
1492 r
= p__Cnd_wait(cm
->cnd
, cm
->mtx
);
1493 ok(!r
, "wait failed\n");
1496 p__Mtx_unlock(cm
->mtx
);
1500 static void test_cnd(void)
1502 _Thrd_t threads
[NUM_THREADS
];
1503 xtime xt
, before
, after
;
1509 r
= p__Cnd_init(&cnd
);
1510 ok(!r
, "failed to init cnd\n");
1512 r
= p__Mtx_init(&mtx
, 0);
1513 ok(!r
, "failed to init mtx\n");
1515 p__Cnd_destroy(NULL
);
1517 /* test _Cnd_signal/_Cnd_wait */
1518 cm
.initialized
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1523 cm
.timed_wait
= FALSE
;
1524 p__Thrd_create(&threads
[0], cnd_wait_thread
, (void*)&cm
);
1526 WaitForSingleObject(cm
.initialized
, INFINITE
);
1530 r
= p__Cnd_signal(cm
.cnd
);
1531 ok(!r
, "failed to signal\n");
1532 p__Thrd_join(threads
[0], NULL
);
1534 /* test _Cnd_timedwait time out */
1536 p_xtime_get(&before
, 1);
1539 /* try to avoid failures on spurious wakeup */
1540 p__Cnd_timedwait(cnd
, mtx
, &xt
);
1541 r
= p__Cnd_timedwait(cnd
, mtx
, &xt
);
1542 p_xtime_get(&after
, 1);
1545 diff
= p__Xtime_diff_to_millis2(&after
, &before
);
1546 ok(r
== 2, "should have timed out\n");
1547 ok(diff
> 1000 - TIMEDELTA
, "got %d\n", diff
);
1549 /* test _Cnd_timedwait */
1551 cm
.timed_wait
= TRUE
;
1552 p__Thrd_create(&threads
[0], cnd_wait_thread
, (void*)&cm
);
1554 WaitForSingleObject(cm
.initialized
, INFINITE
);
1558 r
= p__Cnd_signal(cm
.cnd
);
1559 ok(!r
, "failed to signal\n");
1560 p__Thrd_join(threads
[0], NULL
);
1562 /* test _Cnd_broadcast */
1564 cm
.thread_no
= NUM_THREADS
;
1566 for(i
= 0; i
< cm
.thread_no
; i
++)
1567 p__Thrd_create(&threads
[i
], cnd_wait_thread
, (void*)&cm
);
1569 WaitForSingleObject(cm
.initialized
, INFINITE
);
1573 r
= p__Cnd_broadcast(cnd
);
1574 ok(!r
, "failed to broadcast\n");
1575 for(i
= 0; i
< cm
.thread_no
; i
++)
1576 p__Thrd_join(threads
[i
], NULL
);
1578 p__Cnd_destroy(cnd
);
1579 p__Mtx_destroy(mtx
);
1580 CloseHandle(cm
.initialized
);
1583 static void test_Copy_file(void)
1585 WCHAR origin_path
[MAX_PATH
], temp_path
[MAX_PATH
];
1589 GetCurrentDirectoryW(MAX_PATH
, origin_path
);
1590 GetTempPathW(MAX_PATH
, temp_path
);
1591 ok(SetCurrentDirectoryW(temp_path
), "SetCurrentDirectoryW to temp_path failed\n");
1593 CreateDirectoryW(L
"wine_test_dir", NULL
);
1595 file
= CreateFileW(L
"wine_test_dir/f1", 0, 0, NULL
, CREATE_NEW
, 0, NULL
);
1596 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1597 ok(CloseHandle(file
), "CloseHandle\n");
1599 file
= CreateFileW(L
"wine_test_dir/f2", 0, 0, NULL
, CREATE_NEW
, 0, NULL
);
1600 ok(file
!= INVALID_HANDLE_VALUE
, "create file failed: INVALID_HANDLE_VALUE\n");
1601 ok(CloseHandle(file
), "CloseHandle\n");
1602 SetFileAttributesW(L
"wine_test_dir/f2", FILE_ATTRIBUTE_READONLY
);
1604 ok(CreateDirectoryW(L
"wine_test_dir/d1", NULL
) || GetLastError() == ERROR_ALREADY_EXISTS
,
1605 "CreateDirectoryW failed.\n");
1607 SetLastError(0xdeadbeef);
1608 ret
= p_Copy_file(L
"wine_test_dir/f1", L
"wine_test_dir/d1");
1609 ok(ret
== ERROR_ACCESS_DENIED
, "Got unexpected ret %lu.\n", ret
);
1610 ok(GetLastError() == ret
, "Got unexpected err %lu.\n", GetLastError());
1612 SetLastError(0xdeadbeef);
1613 ret
= p_Copy_file(L
"wine_test_dir/f1", L
"wine_test_dir/f2");
1614 ok(ret
== ERROR_ACCESS_DENIED
, "Got unexpected ret %lu.\n", ret
);
1615 ok(GetLastError() == ret
, "Got unexpected err %lu.\n", GetLastError());
1617 SetLastError(0xdeadbeef);
1618 ret
= p_Copy_file(L
"wine_test_dir/f1", L
"wine_test_dir/f3");
1619 ok(ret
== ERROR_SUCCESS
, "Got unexpected ret %lu.\n", ret
);
1620 ok(GetLastError() == ret
|| broken(GetLastError() == ERROR_INVALID_PARAMETER
) /* some win8 machines */,
1621 "Got unexpected err %lu.\n", GetLastError());
1623 SetLastError(0xdeadbeef);
1624 ret
= p_Copy_file(L
"wine_test_dir/f1", L
"wine_test_dir/f3");
1625 ok(ret
== ERROR_SUCCESS
, "Got unexpected ret %lu.\n", ret
);
1626 ok(GetLastError() == ret
|| broken(GetLastError() == ERROR_INVALID_PARAMETER
) /* some win8 machines */,
1627 "Got unexpected err %lu.\n", GetLastError());
1629 SetLastError(0xdeadbeef);
1630 ret
= p_Copy_file(L
"wine_test_dir/missing", L
"wine_test_dir/f3");
1631 ok(ret
== ERROR_FILE_NOT_FOUND
, "Got unexpected ret %lu.\n", ret
);
1632 ok(GetLastError() == ret
, "Got unexpected err %lu.\n", GetLastError());
1634 ok(RemoveDirectoryW(L
"wine_test_dir/d1"), "expect wine_test_dir to exist\n");
1635 ok(DeleteFileW(L
"wine_test_dir/f1"), "expect wine_test_dir/f1 to exist\n");
1636 SetFileAttributesW(L
"wine_test_dir/f2", FILE_ATTRIBUTE_NORMAL
);
1637 ok(DeleteFileW(L
"wine_test_dir/f2"), "expect wine_test_dir/f2 to exist\n");
1638 ok(DeleteFileW(L
"wine_test_dir/f3"), "expect wine_test_dir/f3 to exist\n");
1639 ok(RemoveDirectoryW(L
"wine_test_dir"), "expect wine_test_dir to exist\n");
1641 ok(SetCurrentDirectoryW(origin_path
), "SetCurrentDirectoryW to origin_path failed\n");
1644 static void test__Mtx(void)
1649 r
= p__Mtx_init(&mtx
, 0);
1650 ok(!r
, "failed to init mtx\n");
1652 ok(mtx
->thread_id
== -1, "mtx.thread_id = %lx\n", mtx
->thread_id
);
1653 ok(mtx
->count
== 0, "mtx.count = %lx\n", mtx
->count
);
1655 ok(mtx
->thread_id
== GetCurrentThreadId(), "mtx.thread_id = %lx\n", mtx
->thread_id
);
1656 ok(mtx
->count
== 1, "mtx.count = %lx\n", mtx
->count
);
1658 ok(mtx
->thread_id
== GetCurrentThreadId(), "mtx.thread_id = %lx\n", mtx
->thread_id
);
1659 ok(mtx
->count
== 1, "mtx.count = %lx\n", mtx
->count
);
1661 ok(mtx
->thread_id
== -1, "mtx.thread_id = %lx\n", mtx
->thread_id
);
1662 ok(mtx
->count
== 0, "mtx.count = %lx\n", mtx
->count
);
1664 ok(mtx
->thread_id
== -1, "mtx.thread_id = %lx\n", mtx
->thread_id
);
1665 ok(mtx
->count
== -1, "mtx.count = %lx\n", mtx
->count
);
1667 ok(mtx
->thread_id
== -1, "mtx.thread_id = %lx\n", mtx
->thread_id
);
1668 ok(mtx
->count
== -2, "mtx.count = %lx\n", mtx
->count
);
1670 p__Mtx_destroy(mtx
);
1673 START_TEST(msvcp140
)
1677 test__Task_impl_base__IsNonBlockingThread();
1678 test_vbtable_size_exports();
1679 test_task_continuation_context();
1680 test__ContextCallback();
1681 test__TaskEventLogger();
1689 test_dir_operation();
1693 test_Last_write_time();
1694 test__Winerror_message();
1695 test__Winerror_map();
1696 test__Syserror_map();