msvcp140/tests: Port test_dir_operation to msvcp140.
[wine.git] / dlls / msvcp140 / tests / msvcp140.c
blob94f87dcbdc43563accef0bcdf80dc224aee77a25
1 /*
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
19 #include <stdio.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
25 #include "wine/test.h"
26 #include "winbase.h"
28 #define DEFINE_EXPECT(func) \
29 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
31 #define SET_EXPECT(func) \
32 do { \
33 expect_ ## func = TRUE; \
34 errno = 0xdeadbeef; \
35 }while(0)
37 #define CHECK_EXPECT2(func) \
38 do { \
39 ok(expect_ ##func, "unexpected call " #func "\n"); \
40 called_ ## func = TRUE; \
41 }while(0)
43 #define CHECK_EXPECT(func) \
44 do { \
45 CHECK_EXPECT2(func); \
46 expect_ ## func = FALSE; \
47 }while(0)
49 #define CHECK_CALLED(func) \
50 do { \
51 ok(called_ ## func, "expected " #func "\n"); \
52 expect_ ## func = called_ ## func = FALSE; \
53 }while(0)
55 #ifdef _WIN64
56 DEFINE_EXPECT(function_do_call);
57 DEFINE_EXPECT(function_do_clean);
58 #endif
60 #undef __thiscall
61 #ifdef __i386__
62 #define __thiscall __stdcall
63 #else
64 #define __thiscall __cdecl
65 #endif
67 /* Emulate a __thiscall */
68 #ifdef __i386__
70 #include "pshpack1.h"
71 struct thiscall_thunk
73 BYTE pop_eax; /* popl %eax (ret addr) */
74 BYTE pop_edx; /* popl %edx (func) */
75 BYTE pop_ecx; /* popl %ecx (this) */
76 BYTE push_eax; /* pushl %eax */
77 WORD jmp_edx; /* jmp *%edx */
79 #include "poppack.h"
81 static void * (WINAPI *call_thiscall_func1)( void *func, void *this );
82 static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
84 static void init_thiscall_thunk(void)
86 struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
87 MEM_COMMIT, PAGE_EXECUTE_READWRITE );
88 thunk->pop_eax = 0x58; /* popl %eax */
89 thunk->pop_edx = 0x5a; /* popl %edx */
90 thunk->pop_ecx = 0x59; /* popl %ecx */
91 thunk->push_eax = 0x50; /* pushl %eax */
92 thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
93 call_thiscall_func1 = (void *)thunk;
94 call_thiscall_func2 = (void *)thunk;
97 #define call_func1(func,_this) call_thiscall_func1(func,_this)
98 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,a)
100 #else
102 #define init_thiscall_thunk()
103 #define call_func1(func,_this) func(_this)
104 #define call_func2(func,_this,a) func(_this,a)
106 #endif /* __i386__ */
107 typedef unsigned char MSVCP_bool;
109 typedef struct {
110 void *unk0;
111 BYTE unk1;
112 } task_continuation_context;
114 typedef struct {
115 void *unused;
116 } _ContextCallback;
118 typedef struct {
119 const void *vtable;
120 void (__cdecl *func)(void);
121 int unk[4];
122 void *unk2[3];
123 void *this;
124 } function_void_cdecl_void;
126 typedef struct {
127 void *task;
128 MSVCP_bool scheduled;
129 MSVCP_bool started;
130 } _TaskEventLogger;
132 typedef struct {
133 PTP_WORK work;
134 void (__cdecl *callback)(void*);
135 void *arg;
136 } _Threadpool_chore;
138 enum file_type {
139 file_not_found = -1,
140 none_file,
141 regular_file,
142 directory_file,
143 symlink_file,
144 block_file,
145 character_file,
146 fifo_file,
147 socket_file,
148 status_unknown
151 static unsigned int (__cdecl *p__Thrd_id)(void);
152 static task_continuation_context* (__thiscall *p_task_continuation_context_ctor)(task_continuation_context*);
153 static void (__thiscall *p__ContextCallback__Assign)(_ContextCallback*, void*);
154 static void (__thiscall *p__ContextCallback__CallInContext)(const _ContextCallback*, function_void_cdecl_void, MSVCP_bool);
155 static void (__thiscall *p__ContextCallback__Capture)(_ContextCallback*);
156 static void (__thiscall *p__ContextCallback__Reset)(_ContextCallback*);
157 static MSVCP_bool (__cdecl *p__ContextCallback__IsCurrentOriginSTA)(_ContextCallback*);
158 static void (__thiscall *p__TaskEventLogger__LogCancelTask)(_TaskEventLogger*);
159 static void (__thiscall *p__TaskEventLogger__LogScheduleTask)(_TaskEventLogger*, MSVCP_bool);
160 static void (__thiscall *p__TaskEventLogger__LogTaskCompleted)(_TaskEventLogger*);
161 static void (__thiscall *p__TaskEventLogger__LogTaskExecutionCompleted)(_TaskEventLogger*);
162 static void (__thiscall *p__TaskEventLogger__LogWorkItemCompleted)(_TaskEventLogger*);
163 static void (__thiscall *p__TaskEventLogger__LogWorkItemStarted)(_TaskEventLogger*);
164 static int (__cdecl *p__Schedule_chore)(_Threadpool_chore*);
165 static int (__cdecl *p__Reschedule_chore)(const _Threadpool_chore*);
166 static void (__cdecl *p__Release_chore)(_Threadpool_chore*);
168 static void (__cdecl *p_Close_dir)(void*);
169 static MSVCP_bool (__cdecl *p_Current_get)(WCHAR *);
170 static MSVCP_bool (__cdecl *p_Current_set)(WCHAR const *);
171 static ULONGLONG (__cdecl *p_File_size)(WCHAR const *);
172 static enum file_type (__cdecl *p_Lstat)(WCHAR const *, int *);
173 static void* (__cdecl *p_Open_dir)(WCHAR*, WCHAR const*, int *, enum file_type*);
174 static WCHAR* (__cdecl *p_Read_dir)(WCHAR*, void*, enum file_type*);
175 static enum file_type (__cdecl *p_Stat)(WCHAR const *, int *);
176 static int (__cdecl *p_To_byte)(const WCHAR *src, char *dst);
177 static int (__cdecl *p_To_wide)(const char *src, WCHAR *dst);
179 static BOOLEAN (WINAPI *pCreateSymbolicLinkW)(const WCHAR *, const WCHAR *, DWORD);
181 static HMODULE msvcp;
182 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
183 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
184 static BOOL init(void)
186 HANDLE hdll;
188 msvcp = LoadLibraryA("msvcp140.dll");
189 if(!msvcp)
191 win_skip("msvcp140.dll not installed\n");
192 return FALSE;
195 SET(p__Thrd_id, "_Thrd_id");
196 SET(p__ContextCallback__IsCurrentOriginSTA, "?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ");
198 if(sizeof(void*) == 8) { /* 64-bit initialization */
199 SET(p_task_continuation_context_ctor, "??0task_continuation_context@Concurrency@@AEAA@XZ");
200 SET(p__ContextCallback__Assign, "?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z");
201 SET(p__ContextCallback__CallInContext, "?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z");
202 SET(p__ContextCallback__Capture, "?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ");
203 SET(p__ContextCallback__Reset, "?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ");
204 SET(p__TaskEventLogger__LogCancelTask, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
205 SET(p__TaskEventLogger__LogScheduleTask, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z");
206 SET(p__TaskEventLogger__LogTaskCompleted, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
207 SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
208 SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
209 SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ");
210 SET(p__Schedule_chore, "?_Schedule_chore@details@Concurrency@@YAHPEAU_Threadpool_chore@12@@Z");
211 SET(p__Reschedule_chore, "?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z");
212 SET(p__Release_chore, "?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z");
213 } else {
214 #ifdef __arm__
215 SET(p_task_continuation_context_ctor, "??0task_continuation_context@Concurrency@@AAA@XZ");
216 SET(p__ContextCallback__Assign, "?_Assign@_ContextCallback@details@Concurrency@@AAAXPAX@Z");
217 SET(p__ContextCallback__CallInContext, "?_CallInContext@_ContextCallback@details@Concurrency@@QBAXV?$function@$$A6AXXZ@std@@_N@Z");
218 SET(p__ContextCallback__Capture, "?_Capture@_ContextCallback@details@Concurrency@@AAAXXZ");
219 SET(p__ContextCallback__Reset, "?_Reset@_ContextCallback@details@Concurrency@@AAAXXZ");
220 SET(p__TaskEventLogger__LogCancelTask, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAAXXZ");
221 SET(p__TaskEventLogger__LogScheduleTask, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z");
222 SET(p__TaskEventLogger__LogTaskCompleted, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
223 SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
224 SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
225 SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAAXXZ");
226 #else
227 SET(p_task_continuation_context_ctor, "??0task_continuation_context@Concurrency@@AAE@XZ");
228 SET(p__ContextCallback__Assign, "?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z");
229 SET(p__ContextCallback__CallInContext, "?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z");
230 SET(p__ContextCallback__Capture, "?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ");
231 SET(p__ContextCallback__Reset, "?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ");
232 SET(p__TaskEventLogger__LogCancelTask, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ");
233 SET(p__TaskEventLogger__LogScheduleTask, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z");
234 SET(p__TaskEventLogger__LogTaskCompleted, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
235 SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
236 SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
237 SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ");
238 #endif
239 SET(p__Schedule_chore, "?_Schedule_chore@details@Concurrency@@YAHPAU_Threadpool_chore@12@@Z");
240 SET(p__Reschedule_chore, "?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z");
241 SET(p__Release_chore, "?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z");
244 SET(p_Close_dir, "_Close_dir");
245 SET(p_Current_get, "_Current_get");
246 SET(p_Current_set, "_Current_set");
247 SET(p_File_size, "_File_size");
248 SET(p_Lstat, "_Lstat");
249 SET(p_Open_dir, "_Open_dir");
250 SET(p_Read_dir, "_Read_dir");
251 SET(p_Stat, "_Stat");
252 SET(p_To_byte, "_To_byte");
253 SET(p_To_wide, "_To_wide");
255 hdll = GetModuleHandleA("kernel32.dll");
256 pCreateSymbolicLinkW = (void*)GetProcAddress(hdll, "CreateSymbolicLinkW");
258 init_thiscall_thunk();
259 return TRUE;
262 static void test_thrd(void)
264 ok(p__Thrd_id() == GetCurrentThreadId(),
265 "expected same id, got _Thrd_id %u GetCurrentThreadId %u\n",
266 p__Thrd_id(), GetCurrentThreadId());
269 static struct {
270 int value[2];
271 const char* export_name;
272 } vbtable_size_exports_list[] = {
273 {{0x20, 0x20}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_istream@DU?$char_traits@D@std@@@1@@"},
274 {{0x10, 0x10}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_ostream@DU?$char_traits@D@std@@@1@@"},
275 {{0x20, 0x20}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_istream@GU?$char_traits@G@std@@@1@@"},
276 {{0x10, 0x10}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_ostream@GU?$char_traits@G@std@@@1@@"},
277 {{0x20, 0x20}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_istream@_WU?$char_traits@_W@std@@@1@@"},
278 {{0x10, 0x10}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_ostream@_WU?$char_traits@_W@std@@@1@@"},
279 {{0x18, 0x18}, "??_8?$basic_istream@DU?$char_traits@D@std@@@std@@7B@"},
280 {{0x18, 0x18}, "??_8?$basic_istream@GU?$char_traits@G@std@@@std@@7B@"},
281 {{0x18, 0x18}, "??_8?$basic_istream@_WU?$char_traits@_W@std@@@std@@7B@"},
282 {{ 0x8, 0x10}, "??_8?$basic_ostream@DU?$char_traits@D@std@@@std@@7B@"},
283 {{ 0x8, 0x10}, "??_8?$basic_ostream@GU?$char_traits@G@std@@@std@@7B@"},
284 {{ 0x8, 0x10}, "??_8?$basic_ostream@_WU?$char_traits@_W@std@@@std@@7B@"},
285 {{ 0x0, 0x0}, 0}
288 static void test_vbtable_size_exports(void)
290 int i;
291 const int *p_vbtable;
292 int arch_idx = (sizeof(void*) == 8);
294 for (i = 0; vbtable_size_exports_list[i].export_name; i++)
296 SET(p_vbtable, vbtable_size_exports_list[i].export_name);
298 ok(p_vbtable[0] == 0, "vbtable[0] wrong, got 0x%x\n", p_vbtable[0]);
299 ok(p_vbtable[1] == vbtable_size_exports_list[i].value[arch_idx],
300 "%d: %s[1] wrong, got 0x%x\n", i, vbtable_size_exports_list[i].export_name, p_vbtable[1]);
304 static void test_task_continuation_context(void)
306 task_continuation_context tcc;
308 memset(&tcc, 0xff, sizeof(tcc));
309 call_func1(p_task_continuation_context_ctor, &tcc);
310 ok(!tcc.unk0, "tcc.unk0 != NULL (%p)\n", tcc.unk0);
311 ok(!tcc.unk1, "tcc.unk1 != 0 (%x)\n", tcc.unk1);
314 #ifdef _WIN64
315 static void __cdecl function_do_call(void *this)
317 CHECK_EXPECT(function_do_call);
320 static void __cdecl function_do_clean(void *this, MSVCP_bool b)
322 CHECK_EXPECT(function_do_clean);
323 ok(b, "b == FALSE\n");
325 #endif
327 static void test__ContextCallback(void)
329 _ContextCallback cc = {0};
330 void *v = (void*)0xdeadbeef;
331 #ifdef _WIN64
332 void* function_vtbl[] = {
333 NULL,
334 NULL,
335 (void*)function_do_call,
336 NULL,
337 (void*)function_do_clean,
338 NULL
340 function_void_cdecl_void function = { function_vtbl, NULL, {0}, {NULL}, &function };
341 function_void_cdecl_void function2 = { NULL, NULL, {0}, {NULL}, &function };
342 #endif
344 call_func2(p__ContextCallback__Assign, &cc, v);
345 ok(!cc.unused, "cc.unused = %p\n", cc.unused);
346 call_func1(p__ContextCallback__Reset, &cc);
347 ok(!cc.unused, "cc.unused = %p\n", cc.unused);
348 call_func1(p__ContextCallback__Capture, &cc);
349 ok(!cc.unused, "cc.unused = %p\n", cc.unused);
350 ok(!p__ContextCallback__IsCurrentOriginSTA(&cc), "IsCurrentOriginSTA returned TRUE\n");
352 cc.unused = v;
353 call_func2(p__ContextCallback__Assign, &cc, NULL);
354 ok(cc.unused == v, "cc.unused = %p\n", cc.unused);
355 call_func1(p__ContextCallback__Reset, &cc);
356 ok(cc.unused == v, "cc.unused = %p\n", cc.unused);
357 call_func1(p__ContextCallback__Capture, &cc);
358 ok(cc.unused == v, "cc.unused = %p\n", cc.unused);
359 ok(!p__ContextCallback__IsCurrentOriginSTA(&cc), "IsCurrentOriginSTA returned TRUE\n");
360 ok(cc.unused == v, "cc.unused = %p\n", cc.unused);
362 #ifdef _WIN64
363 SET_EXPECT(function_do_call);
364 SET_EXPECT(function_do_clean);
365 p__ContextCallback__CallInContext(&cc, function, FALSE);
366 CHECK_CALLED(function_do_call);
367 CHECK_CALLED(function_do_clean);
369 SET_EXPECT(function_do_call);
370 SET_EXPECT(function_do_clean);
371 p__ContextCallback__CallInContext(&cc, function, TRUE);
372 CHECK_CALLED(function_do_call);
373 CHECK_CALLED(function_do_clean);
375 SET_EXPECT(function_do_call);
376 SET_EXPECT(function_do_clean);
377 p__ContextCallback__CallInContext(&cc, function2, FALSE);
378 CHECK_CALLED(function_do_call);
379 CHECK_CALLED(function_do_clean);
381 SET_EXPECT(function_do_call);
382 SET_EXPECT(function_do_clean);
383 p__ContextCallback__CallInContext(&cc, function2, TRUE);
384 CHECK_CALLED(function_do_call);
385 CHECK_CALLED(function_do_clean);
386 #endif
389 static void test__TaskEventLogger(void)
391 _TaskEventLogger logger;
392 memset(&logger, 0, sizeof(logger));
394 call_func1(p__TaskEventLogger__LogCancelTask, &logger);
395 ok(!logger.task, "logger.task = %p\n", logger.task);
396 ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled);
397 ok(!logger.started, "logger.started = %x\n", logger.started);
399 call_func2(p__TaskEventLogger__LogScheduleTask, &logger, FALSE);
400 ok(!logger.task, "logger.task = %p\n", logger.task);
401 ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled);
402 ok(!logger.started, "logger.started = %x\n", logger.started);
404 call_func1(p__TaskEventLogger__LogTaskCompleted, &logger);
405 ok(!logger.task, "logger.task = %p\n", logger.task);
406 ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled);
407 ok(!logger.started, "logger.started = %x\n", logger.started);
409 call_func1(p__TaskEventLogger__LogTaskExecutionCompleted, &logger);
410 ok(!logger.task, "logger.task = %p\n", logger.task);
411 ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled);
412 ok(!logger.started, "logger.started = %x\n", logger.started);
414 call_func1(p__TaskEventLogger__LogWorkItemCompleted, &logger);
415 ok(!logger.task, "logger.task = %p\n", logger.task);
416 ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled);
417 ok(!logger.started, "logger.started = %x\n", logger.started);
419 call_func1(p__TaskEventLogger__LogWorkItemStarted, &logger);
420 ok(!logger.task, "logger.task = %p\n", logger.task);
421 ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled);
422 ok(!logger.started, "logger.started = %x\n", logger.started);
424 logger.task = (void*)0xdeadbeef;
425 logger.scheduled = TRUE;
426 logger.started = TRUE;
428 call_func1(p__TaskEventLogger__LogCancelTask, &logger);
429 ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task);
430 ok(logger.scheduled, "logger.scheduled = FALSE\n");
431 ok(logger.started, "logger.started = FALSE\n");
433 call_func2(p__TaskEventLogger__LogScheduleTask, &logger, FALSE);
434 ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task);
435 ok(logger.scheduled, "logger.scheduled = FALSE\n");
436 ok(logger.started, "logger.started = FALSE\n");
438 call_func1(p__TaskEventLogger__LogTaskCompleted, &logger);
439 ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task);
440 ok(logger.scheduled, "logger.scheduled = FALSE\n");
441 ok(logger.started, "logger.started = FALSE\n");
443 call_func1(p__TaskEventLogger__LogTaskExecutionCompleted, &logger);
444 ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task);
445 ok(logger.scheduled, "logger.scheduled = FALSE\n");
446 ok(logger.started, "logger.started = FALSE\n");
448 call_func1(p__TaskEventLogger__LogWorkItemCompleted, &logger);
449 ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task);
450 ok(logger.scheduled, "logger.scheduled = FALSE\n");
451 ok(logger.started, "logger.started = FALSE\n");
453 call_func1(p__TaskEventLogger__LogWorkItemStarted, &logger);
454 ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task);
455 ok(logger.scheduled, "logger.scheduled = FALSE\n");
456 ok(logger.started, "logger.started = FALSE\n");
459 static void __cdecl chore_callback(void *arg)
461 HANDLE event = arg;
462 SetEvent(event);
465 static void test_chore(void)
467 HANDLE event = CreateEventW(NULL, FALSE, FALSE, NULL);
468 _Threadpool_chore chore, old_chore;
469 DWORD wait;
470 int ret;
472 memset(&chore, 0, sizeof(chore));
473 ret = p__Schedule_chore(&chore);
474 ok(!ret, "_Schedule_chore returned %d\n", ret);
475 ok(chore.work != NULL, "chore.work == NULL\n");
476 ok(!chore.callback, "chore.callback != NULL\n");
477 p__Release_chore(&chore);
479 chore.work = NULL;
480 chore.callback = chore_callback;
481 chore.arg = event;
482 ret = p__Schedule_chore(&chore);
483 ok(!ret, "_Schedule_chore returned %d\n", ret);
484 ok(chore.work != NULL, "chore.work == NULL\n");
485 ok(chore.callback == chore_callback, "chore.callback = %p, expected %p\n", chore.callback, chore_callback);
486 ok(chore.arg == event, "chore.arg = %p, expected %p\n", chore.arg, event);
487 wait = WaitForSingleObject(event, 500);
488 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", wait);
490 old_chore = chore;
491 ret = p__Schedule_chore(&chore);
492 ok(!ret, "_Schedule_chore returned %d\n", ret);
493 ok(old_chore.work != chore.work, "new threadpool work was not created\n");
494 p__Release_chore(&old_chore);
495 wait = WaitForSingleObject(event, 500);
496 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", wait);
498 ret = p__Reschedule_chore(&chore);
499 ok(!ret, "_Reschedule_chore returned %d\n", ret);
500 wait = WaitForSingleObject(event, 500);
501 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", wait);
503 p__Release_chore(&chore);
504 ok(!chore.work, "chore.work != NULL\n");
505 ok(chore.callback == chore_callback, "chore.callback = %p, expected %p\n", chore.callback, chore_callback);
506 ok(chore.arg == event, "chore.arg = %p, expected %p\n", chore.arg, event);
507 p__Release_chore(&chore);
510 static void test_to_byte(void)
512 static const WCHAR test_1[] = {'T', 'E', 'S', 'T', 0};
513 static const WCHAR test_2[] = {0x9580, 0x9581, 0x9582, 0x9583, 0}; /* some CJK characters */
514 static const WCHAR *tests[] = {test_1, test_2};
516 char dst[MAX_PATH + 4] = "ABC\0XXXXXXX";
517 char compare[MAX_PATH + 4] = "ABC\0XXXXXXX";
518 int ret,expected;
519 unsigned int i, j;
520 WCHAR longstr[MAX_PATH + 3];
522 ret = p_To_byte(NULL, NULL);
523 ok(!ret, "Got unexpected result %d\n", ret);
524 ret = p_To_byte(tests[0], NULL);
525 ok(!ret, "Got unexpected result %d\n", ret);
526 ret = p_To_byte(NULL, dst);
527 ok(!ret, "Got unexpected result %d\n", ret);
529 ok(!memcmp(dst, compare, sizeof(compare)), "Destination was modified: %s\n", dst);
531 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
533 ret = p_To_byte(tests[i], dst);
534 expected = WideCharToMultiByte(CP_ACP, 0, tests[i], -1, compare, sizeof(compare) / sizeof(*compare),
535 NULL, NULL);
536 ok(ret == expected, "Got unexpected result %d, expected %d, test case %u\n", ret, expected, i);
537 ok(!memcmp(dst, compare, sizeof(compare)), "Got unexpected output %s, test case %u\n", dst, i);
540 /* Output length is limited to MAX_PATH.*/
541 for (i = MAX_PATH - 2; i < MAX_PATH + 2; ++i)
543 for (j = 0; j < i; j++)
544 longstr[j] = 'A';
545 longstr[i] = 0;
546 memset(dst, 0xff, sizeof(dst));
547 memset(compare, 0xff, sizeof(compare));
549 ret = p_To_byte(longstr, dst);
550 expected = WideCharToMultiByte(CP_ACP, 0, longstr, -1, compare, MAX_PATH, NULL, NULL);
551 ok(ret == expected, "Got unexpected result %d, expected %d, length %u\n", ret, expected, i);
552 ok(!memcmp(dst, compare, sizeof(compare)), "Got unexpected output %s, length %u\n", dst, i);
556 static void test_to_wide(void)
558 /* öäü߀Ÿ.A.B in cp1252, the two . are an undefined value and delete.
559 * With a different system codepage it will produce different results, so do not hardcode the
560 * expected output but convert it with MultiByteToWideChar. */
561 static const char special_input[] = {0xf6, 0xe4, 0xfc, 0xdf, 0x80, 0x9f, 0x81, 0x41, 0x7f, 0x42, 0};
562 static const char *tests[] = {"Testtest", special_input};
563 WCHAR dst[MAX_PATH + 4] = {'A', 'B', 'C', 0, 'X', 'X', 'X', 'X', 'X', 'X', 'X'};
564 WCHAR compare[MAX_PATH + 4] = {'A', 'B', 'C', 0, 'X', 'X', 'X', 'X', 'X', 'X', 'X'};
565 int ret, expected;
566 unsigned int i;
567 char longstr[MAX_PATH + 3];
569 ret = p_To_wide(NULL, NULL);
570 ok(!ret, "Got unexpected result %d\n", ret);
571 ret = p_To_wide(tests[0], NULL);
572 ok(!ret, "Got unexpected result %d\n", ret);
573 ret = p_To_wide(NULL, dst);
574 ok(!ret, "Got unexpected result %d\n", ret);
575 ok(!memcmp(dst, compare, sizeof(compare)), "Destination was modified: %s\n", wine_dbgstr_w(dst));
577 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
579 ret = p_To_wide(tests[i], dst);
580 expected = MultiByteToWideChar(CP_ACP, 0, tests[i], -1, compare, sizeof(compare) / sizeof(*compare));
581 ok(ret == expected, "Got unexpected result %d, expected %d, test case %u\n", ret, expected, i);
582 ok(!memcmp(dst, compare, sizeof(compare)), "Got unexpected output %s, test case %u\n",
583 wine_dbgstr_w(dst), i);
586 /* Output length is limited to MAX_PATH.*/
587 for (i = MAX_PATH - 2; i < MAX_PATH + 2; ++i)
589 memset(longstr, 'A', sizeof(longstr));
590 longstr[i] = 0;
591 memset(dst, 0xff, sizeof(dst));
592 memset(compare, 0xff, sizeof(compare));
594 ret = p_To_wide(longstr, dst);
595 expected = MultiByteToWideChar(CP_ACP, 0, longstr, -1, compare, MAX_PATH);
596 ok(ret == expected, "Got unexpected result %d, expected %d, length %u\n", ret, expected, i);
597 ok(!memcmp(dst, compare, sizeof(compare)), "Got unexpected output %s, length %u\n",
598 wine_dbgstr_w(dst), i);
602 static void test_File_size(void)
604 ULONGLONG val;
605 HANDLE file;
606 LARGE_INTEGER file_size;
607 WCHAR test_f1_W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','f','1',0};
608 WCHAR test_f2_W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','f','2',0};
609 WCHAR test_dir_W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r',0};
610 WCHAR test_ne_W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','n','e',0};
611 WCHAR temp_path[MAX_PATH], origin_path[MAX_PATH];
613 memset(origin_path, 0, sizeof(origin_path));
614 memset(origin_path, 0, sizeof(temp_path));
615 GetCurrentDirectoryW(MAX_PATH, origin_path);
616 GetTempPathW(MAX_PATH, temp_path);
617 ok(SetCurrentDirectoryW(temp_path), "SetCurrentDirectoryW to temp_path failed\n");
619 CreateDirectoryW(test_dir_W, NULL);
621 file = CreateFileW(test_f1_W, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
622 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
623 file_size.QuadPart = 7;
624 ok(SetFilePointerEx(file, file_size, NULL, FILE_BEGIN), "SetFilePointerEx failed\n");
625 ok(SetEndOfFile(file), "SetEndOfFile failed\n");
626 CloseHandle(file);
627 val = p_File_size(test_f1_W);
628 ok(val == 7, "file_size is %s\n", wine_dbgstr_longlong(val));
630 file = CreateFileW(test_f2_W, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
631 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
632 CloseHandle(file);
633 val = p_File_size(test_f2_W);
634 ok(val == 0, "file_size is %s\n", wine_dbgstr_longlong(val));
636 val = p_File_size(test_dir_W);
637 ok(val == 0, "file_size is %s\n", wine_dbgstr_longlong(val));
639 errno = 0xdeadbeef;
640 val = p_File_size(test_ne_W);
641 ok(val == ~(ULONGLONG)0, "file_size is %s\n", wine_dbgstr_longlong(val));
642 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
644 errno = 0xdeadbeef;
645 val = p_File_size(NULL);
646 ok(val == ~(ULONGLONG)0, "file_size is %s\n", wine_dbgstr_longlong(val));
647 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
649 ok(DeleteFileW(test_f1_W), "expect wine_test_dir/f1 to exist\n");
650 ok(DeleteFileW(test_f2_W), "expect wine_test_dir/f2 to exist\n");
651 ok(RemoveDirectoryW(test_dir_W), "expect wine_test_dir to exist\n");
652 ok(SetCurrentDirectoryW(origin_path), "SetCurrentDirectoryW to origin_path failed\n");
655 static void test_Current_get(void)
657 WCHAR temp_path[MAX_PATH], current_path[MAX_PATH], origin_path[MAX_PATH];
658 BOOL ret;
659 memset(origin_path, 0, sizeof(origin_path));
660 GetCurrentDirectoryW(MAX_PATH, origin_path);
661 memset(temp_path, 0, sizeof(temp_path));
662 GetTempPathW(MAX_PATH, temp_path);
664 ok(SetCurrentDirectoryW(temp_path), "SetCurrentDirectoryW to temp_path failed\n");
665 memset(current_path, 0, sizeof(current_path));
666 ret = p_Current_get(current_path);
667 ok(ret == TRUE, "p_Current_get returned %u\n", ret);
668 current_path[wcslen(current_path)] = '\\';
669 ok(!wcscmp(temp_path, current_path), "p_Current_get(): expect: %s, got %s\n",
670 wine_dbgstr_w(temp_path), wine_dbgstr_w(current_path));
672 ok(SetCurrentDirectoryW(origin_path), "SetCurrentDirectoryW to origin_path failed\n");
673 memset(current_path, 0, sizeof(current_path));
674 ret = p_Current_get(current_path);
675 ok(ret == TRUE, "p_Current_get returned %u\n", ret);
676 ok(!wcscmp(origin_path, current_path), "p_Current_get(): expect: %s, got %s\n",
677 wine_dbgstr_w(origin_path), wine_dbgstr_w(current_path));
680 static void test_Current_set(void)
682 WCHAR temp_path[MAX_PATH], current_path[MAX_PATH], origin_path[MAX_PATH];
683 MSVCP_bool ret;
684 WCHAR testW[] = {'.','/',0};
685 WCHAR not_exit_dirW[] = {'n', 'o', 't', '_', 'e', 'x', 'i', 's', 't', '_', 'd', 'i', 'r', 0};
686 WCHAR invalid_nameW[] = {'?', '?', 'i', 'n', 'v', 'a', 'l', 'i', 'd', '_', 'n', 'a', 'm', 'e', '>', '>', 0};
687 memset(temp_path, 0, sizeof(temp_path));
688 GetTempPathW(MAX_PATH, temp_path);
689 memset(origin_path, 0, sizeof(origin_path));
690 GetCurrentDirectoryW(MAX_PATH, origin_path);
692 ok(p_Current_set(temp_path), "p_Current_set to temp_path failed\n");
693 memset(current_path, 0, sizeof(current_path));
694 ret = p_Current_get(current_path);
695 ok(ret == TRUE, "p_Current_get returned %u\n", ret);
696 current_path[wcslen(current_path)] = '\\';
697 ok(!wcscmp(temp_path, current_path), "p_Current_get(): expect: %s, got %s\n",
698 wine_dbgstr_w(temp_path), wine_dbgstr_w(current_path));
700 ok(p_Current_set(testW), "p_Current_set to temp_path failed\n");
701 memset(current_path, 0, sizeof(current_path));
702 ret = p_Current_get(current_path);
703 ok(ret == TRUE, "p_Current_get returned %u\n", ret);
704 current_path[wcslen(current_path)] = '\\';
705 ok(!wcscmp(temp_path, current_path), "p_Current_get(): expect: %s, got %s\n",
706 wine_dbgstr_w(temp_path), wine_dbgstr_w(current_path));
708 errno = 0xdeadbeef;
709 ok(!p_Current_set(not_exit_dirW), "p_Current_set to not_exist_dir succeed\n");
710 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
712 errno = 0xdeadbeef;
713 ok(!p_Current_set(invalid_nameW), "p_Current_set to ??invalid_name>> succeed\n");
714 ok(errno == 0xdeadbeef, "errno = %d\n", errno);
716 ok(p_Current_set(origin_path), "p_Current_set to origin_path failed\n");
717 memset(current_path, 0, sizeof(current_path));
718 ret = p_Current_get(current_path);
719 ok(ret == TRUE, "p_Current_get returned %u\n", ret);
720 ok(!wcscmp(origin_path, current_path), "p_Current_get(): expect: %s, got %s\n",
721 wine_dbgstr_w(origin_path), wine_dbgstr_w(current_path));
724 static void test_Stat(void)
726 int i, perms, ret;
727 HANDLE file;
728 enum file_type val;
729 WCHAR test_dirW[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r',0};
730 WCHAR test_f1W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','f','1',0};
731 WCHAR test_f2W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','f','2',0};
732 WCHAR pipeW[] = {'\\','\\','.','\\','P','i','P','e','\\','t','e','s','t','s','_','p','i','p','e','.','c', 0};
733 WCHAR test_neW[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','n','e',0};
734 WCHAR test_invW[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','\\','?','?','i','n','v','a','l','i','d','_','n','a','m','e','>','>',0};
735 WCHAR test_f1_linkW[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','\\','f','1','_','l','i','n','k',0};
736 WCHAR test_dir_linkW[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','\\','d','i','r','_','l','i','n','k',0};
737 WCHAR sys_path[MAX_PATH], origin_path[MAX_PATH], temp_path[MAX_PATH];
738 struct {
739 WCHAR const *path;
740 enum file_type ret;
741 int perms;
742 int is_todo;
743 } tests[] = {
744 { NULL, file_not_found, 0xdeadbeef, FALSE },
745 { test_dirW, directory_file, 0777, FALSE },
746 { test_f1W, regular_file, 0777, FALSE },
747 { test_f2W, regular_file, 0555, FALSE },
748 { test_neW, file_not_found, 0xdeadbeef, FALSE },
749 { test_invW, file_not_found, 0xdeadbeef, FALSE },
750 { test_f1_linkW, regular_file, 0777, TRUE },
751 { test_dir_linkW, directory_file, 0777, TRUE },
754 memset(origin_path, 0, sizeof(origin_path));
755 memset(origin_path, 0, sizeof(temp_path));
756 GetCurrentDirectoryW(MAX_PATH, origin_path);
757 GetTempPathW(MAX_PATH, temp_path);
758 ok(SetCurrentDirectoryW(temp_path), "SetCurrentDirectoryW to temp_path failed\n");
760 CreateDirectoryW(test_dirW, NULL);
762 file = CreateFileW(test_f1W, 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
763 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
764 ok(CloseHandle(file), "CloseHandle\n");
766 file = CreateFileW(test_f2W, 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
767 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
768 ok(CloseHandle(file), "CloseHandle\n");
769 SetFileAttributesW(test_f2W, FILE_ATTRIBUTE_READONLY);
771 SetLastError(0xdeadbeef);
772 ret = pCreateSymbolicLinkW && pCreateSymbolicLinkW(test_f1_linkW, test_f1W, 0);
773 if(!ret && (!pCreateSymbolicLinkW || GetLastError()==ERROR_PRIVILEGE_NOT_HELD||GetLastError()==ERROR_INVALID_FUNCTION)) {
774 tests[6].ret = tests[7].ret = file_not_found;
775 tests[6].perms = tests[7].perms = 0xdeadbeef;
776 win_skip("Privilege not held or symbolic link not supported, skipping symbolic link tests.\n");
777 }else {
778 ok(ret, "CreateSymbolicLinkW failed\n");
779 ok(pCreateSymbolicLinkW(test_dir_linkW, test_dirW, 1), "CreateSymbolicLinkW failed\n");
782 file = CreateNamedPipeW(pipeW,
783 PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024,
784 NMPWAIT_USE_DEFAULT_WAIT, NULL);
785 ok(file != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
786 perms = 0xdeadbeef;
787 val = p_Stat(pipeW, &perms);
788 todo_wine ok(regular_file == val, "_Stat(): expect: regular, got %d\n", val);
789 todo_wine ok(0777 == perms, "_Stat(): perms expect: 0777, got 0%o\n", perms);
790 perms = 0xdeadbeef;
791 val = p_Lstat(pipeW, &perms);
792 ok(status_unknown == val, "_Lstat(): expect: unknown, got %d\n", val);
793 ok(0xdeadbeef == perms, "_Lstat(): perms expect: 0xdeadbeef, got %x\n", perms);
794 ok(CloseHandle(file), "CloseHandle\n");
795 file = CreateNamedPipeW(pipeW,
796 PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 2, 1024, 1024,
797 NMPWAIT_USE_DEFAULT_WAIT, NULL);
798 ok(file != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
799 perms = 0xdeadbeef;
800 val = p_Lstat(pipeW, &perms);
801 todo_wine ok(regular_file == val, "_Lstat(): expect: regular, got %d\n", val);
802 todo_wine ok(0777 == perms, "_Lstat(): perms expect: 0777, got 0%o\n", perms);
803 ok(CloseHandle(file), "CloseHandle\n");
805 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
806 perms = 0xdeadbeef;
807 val = p_Stat(tests[i].path, &perms);
808 todo_wine_if(tests[i].is_todo) {
809 ok(tests[i].ret == val, "_Stat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
810 ok(tests[i].perms == perms, "_Stat(): test %d perms expect: 0%o, got 0%o\n",
811 i+1, tests[i].perms, perms);
813 val = p_Stat(tests[i].path, NULL);
814 todo_wine_if(tests[i].is_todo)
815 ok(tests[i].ret == val, "_Stat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
817 /* test _Lstat */
818 perms = 0xdeadbeef;
819 val = p_Lstat(tests[i].path, &perms);
820 todo_wine_if(tests[i].is_todo) {
821 ok(tests[i].ret == val, "_Lstat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
822 ok(tests[i].perms == perms, "_Lstat(): test %d perms expect: 0%o, got 0%o\n",
823 i+1, tests[i].perms, perms);
825 val = p_Lstat(tests[i].path, NULL);
826 todo_wine_if(tests[i].is_todo)
827 ok(tests[i].ret == val, "_Lstat(): test %d expect: %d, got %d\n", i+1, tests[i].ret, val);
830 GetSystemDirectoryW(sys_path, MAX_PATH);
831 perms = 0xdeadbeef;
832 val = p_Stat(sys_path, &perms);
833 ok(directory_file == val, "_Stat(): expect: regular, got %d\n", val);
834 ok(0777 == perms, "_Stat(): perms expect: 0777, got 0%o\n", perms);
836 if(ret) {
837 todo_wine ok(DeleteFileW(test_f1_linkW), "expect tr2_test_dir/f1_link to exist\n");
838 todo_wine ok(RemoveDirectoryW(test_dir_linkW), "expect tr2_test_dir/dir_link to exist\n");
840 ok(DeleteFileW(test_f1W), "expect tr2_test_dir/f1 to exist\n");
841 SetFileAttributesW(test_f2W, FILE_ATTRIBUTE_NORMAL);
842 ok(DeleteFileW(test_f2W), "expect tr2_test_dir/f2 to exist\n");
843 ok(RemoveDirectoryW(test_dirW), "expect tr2_test_dir to exist\n");
845 ok(SetCurrentDirectoryW(origin_path), "SetCurrentDirectoryW to origin_path failed\n");
848 static void test_dir_operation(void)
850 WCHAR *file_name, first_file_name[MAX_PATH], dest[MAX_PATH], longer_path[MAX_PATH];
851 WCHAR origin_path[MAX_PATH], temp_path[MAX_PATH];
852 HANDLE file, result_handle;
853 enum file_type type;
854 int err, num_of_f1 = 0, num_of_f2 = 0, num_of_sub_dir = 0, num_of_other_files = 0;
855 WCHAR test_dirW[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r',0};
856 WCHAR test_f1W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','f','1',0};
857 WCHAR test_f2W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','f','2',0};
858 WCHAR test_sub_dirW[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r','/','s','u','b','_','d','i','r',0};
859 WCHAR test_sub_dir_f1W[] = {'w','i','n','e','_','t','e','s','t','_','d','i','r',
860 '/','s','u','b','_','d','i','r','/','f','1',0};
861 WCHAR backslashW[] = {'\\',0};
862 WCHAR sW[] = {'s',0};
863 WCHAR f1W[] = {'f','1',0};
864 WCHAR f2W[] = {'f','2',0};
865 WCHAR sub_dirW[] = {'s','u','b','_','d','i','r',0};
866 WCHAR not_existW[] = {'n','o','t','_','e','x','i','s','t',0};
867 WCHAR emtpy_dirW[] = {'e','m','p','t','y','_','d','i','r',0};
869 memset(origin_path, 0, sizeof(origin_path));
870 memset(origin_path, 0, sizeof(temp_path));
871 GetCurrentDirectoryW(MAX_PATH, origin_path);
872 GetTempPathW(MAX_PATH, temp_path);
873 ok(SetCurrentDirectoryW(temp_path), "SetCurrentDirectoryW to temp_path failed\n");
875 CreateDirectoryW(test_dirW, NULL);
876 file = CreateFileW(test_f1W, 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
877 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
878 CloseHandle(file);
879 file = CreateFileW(test_f2W, 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
880 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
881 CloseHandle(file);
882 CreateDirectoryW(test_sub_dirW, NULL);
883 file = CreateFileW(test_sub_dir_f1W, 0, 0, NULL, CREATE_ALWAYS, 0, NULL);
884 ok(file != INVALID_HANDLE_VALUE, "create file failed: INVALID_HANDLE_VALUE\n");
885 CloseHandle(file);
887 memcpy(longer_path, temp_path, sizeof(longer_path));
888 wcscat(longer_path, backslashW);
889 wcscat(longer_path, test_dirW);
890 wcscat(longer_path, backslashW);
891 while(lstrlenW(longer_path) < MAX_PATH-1)
892 wcscat(longer_path, sW);
893 memset(first_file_name, 0, sizeof(first_file_name));
894 type = err = 0xdeadbeef;
895 result_handle = NULL;
896 result_handle = p_Open_dir(first_file_name, longer_path, &err, &type);
897 ok(result_handle == NULL, "_Open_dir(): expect NULL, got %p\n", result_handle);
898 ok(!*first_file_name, "_Open_dir(): expect: 0, got %s\n", wine_dbgstr_w(first_file_name));
899 ok(err == ERROR_BAD_PATHNAME, "_Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err);
900 ok((int)type == 0xdeadbeef, "_Open_dir(): expect 0xdeadbeef, got %d\n", type);
902 memset(first_file_name, 0, sizeof(first_file_name));
903 memset(dest, 0, sizeof(dest));
904 err = type = 0xdeadbeef;
905 result_handle = NULL;
906 result_handle = p_Open_dir(first_file_name, test_dirW, &err, &type);
907 ok(result_handle != NULL, "_Open_dir(): expect: not NULL, got %p\n", result_handle);
908 ok(err == ERROR_SUCCESS, "_Open_dir(): expect: ERROR_SUCCESS, got %d\n", err);
909 file_name = first_file_name;
910 while(*file_name) {
911 if (!wcscmp(file_name, f1W)) {
912 ++num_of_f1;
913 ok(type == regular_file, "expect regular_file, got %d\n", type);
914 }else if(!wcscmp(file_name, f2W)) {
915 ++num_of_f2;
916 ok(type == regular_file, "expect regular_file, got %d\n", type);
917 }else if(!wcscmp(file_name, sub_dirW)) {
918 ++num_of_sub_dir;
919 ok(type == directory_file, "expect directory_file, got %d\n", type);
920 }else {
921 ++num_of_other_files;
923 file_name = p_Read_dir(dest, result_handle, &type);
925 ok(type == status_unknown, "_Read_dir(): expect: status_unknown, got %d\n", type);
926 p_Close_dir(result_handle);
927 ok(result_handle != NULL, "_Open_dir(): expect: not NULL, got %p\n", result_handle);
928 ok(num_of_f1 == 1, "found f1 %d times\n", num_of_f1);
929 ok(num_of_f2 == 1, "found f2 %d times\n", num_of_f2);
930 ok(num_of_sub_dir == 1, "found sub_dir %d times\n", num_of_sub_dir);
931 ok(num_of_other_files == 0, "found %d other files\n", num_of_other_files);
933 memset(first_file_name, 0, sizeof(first_file_name));
934 err = type = 0xdeadbeef;
935 result_handle = file;
936 result_handle = p_Open_dir(first_file_name, not_existW, &err, &type);
937 ok(result_handle == NULL, "_Open_dir(): expect: NULL, got %p\n", result_handle);
938 todo_wine ok(err == ERROR_BAD_PATHNAME, "_Open_dir(): expect: ERROR_BAD_PATHNAME, got %d\n", err);
939 ok((int)type == 0xdeadbeef, "_Open_dir(): expect: 0xdeadbeef, got %d\n", type);
940 ok(!*first_file_name, "_Open_dir(): expect: 0, got %s\n", wine_dbgstr_w(first_file_name));
942 CreateDirectoryW(emtpy_dirW, NULL);
943 memset(first_file_name, 0, sizeof(first_file_name));
944 err = type = 0xdeadbeef;
945 result_handle = file;
946 result_handle = p_Open_dir(first_file_name, emtpy_dirW, &err, &type);
947 ok(result_handle == NULL, "_Open_dir(): expect: NULL, got %p\n", result_handle);
948 ok(err == ERROR_SUCCESS, "_Open_dir(): expect: ERROR_SUCCESS, got %d\n", err);
949 ok(type == status_unknown, "_Open_dir(): expect: status_unknown, got %d\n", type);
950 ok(!*first_file_name, "_Open_dir(): expect: 0, got %s\n", wine_dbgstr_w(first_file_name));
951 p_Close_dir(result_handle);
952 ok(result_handle == NULL, "_Open_dir(): expect: NULL, got %p\n", result_handle);
954 ok(RemoveDirectoryW(emtpy_dirW), "expect empty_dir to exist\n");
955 ok(DeleteFileW(test_sub_dir_f1W), "expect wine_test_dir/sub_dir/sub_f1 to exist\n");
956 ok(RemoveDirectoryW(test_sub_dirW), "expect wine_test_dir/sub_dir to exist\n");
957 ok(DeleteFileW(test_f1W), "expect wine_test_dir/f1 to exist\n");
958 ok(DeleteFileW(test_f2W), "expect wine_test_dir/f2 to exist\n");
959 ok(RemoveDirectoryW(test_dirW), "expect wine_test_dir to exist\n");
961 ok(SetCurrentDirectoryW(origin_path), "SetCurrentDirectoryW to origin_path failed\n");
964 START_TEST(msvcp140)
966 if(!init()) return;
967 test_thrd();
968 test_vbtable_size_exports();
969 test_task_continuation_context();
970 test__ContextCallback();
971 test__TaskEventLogger();
972 test_chore();
973 test_to_byte();
974 test_to_wide();
975 test_File_size();
976 test_Current_get();
977 test_Current_set();
978 test_Stat();
979 test_dir_operation();
980 FreeLibrary(msvcp);