kernel32/tests: Run file tests in the temp directory if we don't have access to the...
[wine] / dlls / kernel32 / tests / file.c
1 /*
2  * Unit tests for file functions in Wine
3  *
4  * Copyright (c) 2002, 2004 Jakob Eriksson
5  * Copyright (c) 2008 Jeff Zaroyko
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  */
22
23 /* ReplaceFile requires Windows 2000 or newer */
24 #define _WIN32_WINNT 0x0500
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <time.h>
29
30 #include "wine/test.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winerror.h"
34
35 static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD);
36 static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID);
37 static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID);
38 static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT);
39
40 /* keep filename and filenameW the same */
41 static const char filename[] = "testfile.xxx";
42 static const WCHAR filenameW[] = { 't','e','s','t','f','i','l','e','.','x','x','x',0 };
43 static const char sillytext[] =
44 "en larvig liten text dx \033 gx hej 84 hej 4484 ! \001\033 bla bl\na.. bla bla."
45 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
46 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
47 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
48 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
49 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
50 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
51 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
52 "1234 43 4kljf lf &%%%&&&&&& 34 4 34   3############# 33 3 3 3 # 3## 3"
53 "sdlkfjasdlkfj a dslkj adsklf  \n  \nasdklf askldfa sdlkf \nsadklf asdklf asdf ";
54
55 static void InitFunctionPointers(void)
56 {
57     HMODULE hkernel32 = GetModuleHandleA("kernel32");
58
59     pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA");
60     pReplaceFileA=(void*)GetProcAddress(hkernel32, "ReplaceFileA");
61     pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW");
62     pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA");
63 }
64
65 static void test__hread( void )
66 {
67     HFILE filehandle;
68     char buffer[10000];
69     long bytes_read;
70     long bytes_wanted;
71     long i;
72     BOOL ret;
73
74     SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL); /* be sure to remove stale files */
75     DeleteFileA( filename );
76     filehandle = _lcreat( filename, 0 );
77     if (filehandle == HFILE_ERROR)
78     {
79         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
80         return;
81     }
82
83     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
84
85     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
86
87     filehandle = _lopen( filename, OF_READ );
88
89     ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError(  ) );
90
91     bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
92
93     ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
94
95     for (bytes_wanted = 0; bytes_wanted < lstrlenA( sillytext ); bytes_wanted++)
96     {
97         ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
98         ok( _hread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
99         for (i = 0; i < bytes_wanted; i++)
100         {
101             ok( buffer[i] == sillytext[i], "that's not what's written\n" );
102         }
103     }
104
105     ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
106
107     ret = DeleteFileA( filename );
108     ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError(  ) );
109 }
110
111
112 static void test__hwrite( void )
113 {
114     HFILE filehandle;
115     char buffer[10000];
116     long bytes_read;
117     long bytes_written;
118     long blocks;
119     long i;
120     char *contents;
121     HLOCAL memory_object;
122     char checksum[1];
123     BOOL ret;
124
125     filehandle = _lcreat( filename, 0 );
126     if (filehandle == HFILE_ERROR)
127     {
128         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
129         return;
130     }
131
132     ok( HFILE_ERROR != _hwrite( filehandle, "", 0 ), "_hwrite complains\n" );
133
134     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
135
136     filehandle = _lopen( filename, OF_READ );
137
138     bytes_read = _hread( filehandle, buffer, 1);
139
140     ok( 0 == bytes_read, "file read size error\n" );
141
142     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
143
144     filehandle = _lopen( filename, OF_READWRITE );
145
146     bytes_written = 0;
147     checksum[0] = '\0';
148     srand( (unsigned)time( NULL ) );
149     for (blocks = 0; blocks < 100; blocks++)
150     {
151         for (i = 0; i < (long)sizeof( buffer ); i++)
152         {
153             buffer[i] = rand(  );
154             checksum[0] = checksum[0] + buffer[i];
155         }
156         ok( HFILE_ERROR != _hwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
157         bytes_written = bytes_written + sizeof( buffer );
158     }
159
160     ok( HFILE_ERROR != _hwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
161     bytes_written++;
162
163     ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
164
165     memory_object = LocalAlloc( LPTR, bytes_written );
166
167     ok( 0 != memory_object, "LocalAlloc fails. (Could be out of memory.)\n" );
168
169     contents = LocalLock( memory_object );
170
171     filehandle = _lopen( filename, OF_READ );
172
173     contents = LocalLock( memory_object );
174
175     ok( NULL != contents, "LocalLock whines\n" );
176
177     ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
178
179     checksum[0] = '\0';
180     i = 0;
181     do
182     {
183         checksum[0] = checksum[0] + contents[i];
184         i++;
185     }
186     while (i < bytes_written - 1);
187
188     ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
189
190     ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
191
192     ret = DeleteFileA( filename );
193     ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError(  ) );
194 }
195
196
197 static void test__lclose( void )
198 {
199     HFILE filehandle;
200     BOOL ret;
201
202     filehandle = _lcreat( filename, 0 );
203     if (filehandle == HFILE_ERROR)
204     {
205         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
206         return;
207     }
208
209     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
210
211     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
212
213     ret = DeleteFileA( filename );
214     ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError(  ) );
215 }
216
217
218 static void test__lcreat( void )
219 {
220     HFILE filehandle;
221     char buffer[10000];
222     WIN32_FIND_DATAA search_results;
223     char slashname[] = "testfi/";
224     int err;
225     HANDLE find;
226     BOOL ret;
227
228     filehandle = _lcreat( filename, 0 );
229     if (filehandle == HFILE_ERROR)
230     {
231         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
232         return;
233     }
234
235     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
236
237     ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
238
239     ok( _hread( filehandle, buffer, strlen( sillytext ) ) ==  lstrlenA( sillytext ), "erratic _hread return value\n" );
240
241     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
242
243     ok( INVALID_HANDLE_VALUE != FindFirstFileA( filename, &search_results ), "should be able to find file\n" );
244
245     ret = DeleteFileA(filename);
246     ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError());
247
248     filehandle = _lcreat( filename, 1 ); /* readonly */
249     ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError(  ) );
250
251     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write never the less\n" );
252
253     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
254
255     ok( INVALID_HANDLE_VALUE != FindFirstFileA( filename, &search_results ), "should be able to find file\n" );
256
257     ok( 0 == DeleteFileA( filename ), "shouldn't be able to delete a readonly file\n" );
258
259     ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
260
261     ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file!\n" );
262
263     filehandle = _lcreat( filename, 2 );
264     ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError(  ) );
265
266     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
267
268     ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
269
270     ok( _hread( filehandle, buffer, strlen( sillytext ) ) ==  lstrlenA( sillytext ), "erratic _hread return value\n" );
271
272     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
273
274     ok( INVALID_HANDLE_VALUE != FindFirstFileA( filename, &search_results ), "should STILL be able to find file\n" );
275
276     ret = DeleteFileA( filename );
277     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
278
279     filehandle = _lcreat( filename, 4 ); /* SYSTEM file */
280     ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError(  ) );
281
282     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
283
284     ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
285
286     ok( _hread( filehandle, buffer, strlen( sillytext ) ) ==  lstrlenA( sillytext ), "erratic _hread return value\n" );
287
288     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
289
290     ok( INVALID_HANDLE_VALUE != FindFirstFileA( filename, &search_results ), "should STILL be able to find file\n" );
291
292     ret = DeleteFileA( filename );
293     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
294
295     filehandle=_lcreat (slashname, 0); /* illegal name */
296     if (HFILE_ERROR==filehandle) {
297       err=GetLastError ();
298       ok (err==ERROR_INVALID_NAME || err==ERROR_PATH_NOT_FOUND,
299           "creating file \"%s\" failed with error %d\n", slashname, err);
300     } else { /* only NT succeeds */
301       _lclose(filehandle);
302       find=FindFirstFileA (slashname, &search_results);
303       if (INVALID_HANDLE_VALUE!=find)
304       {
305         ret = FindClose (find);
306         ok (0 != ret, "FindClose complains (%d)\n", GetLastError ());
307         slashname[strlen(slashname)-1]=0;
308         ok (!strcmp (slashname, search_results.cFileName),
309             "found unexpected name \"%s\"\n", search_results.cFileName);
310         ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
311             "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
312             search_results.dwFileAttributes);
313       }
314     ret = DeleteFileA( slashname );
315     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
316     }
317
318     filehandle=_lcreat (filename, 8); /* illegal attribute */
319     if (HFILE_ERROR==filehandle)
320       ok (0, "couldn't create volume label \"%s\"\n", filename);
321     else {
322       _lclose(filehandle);
323       find=FindFirstFileA (filename, &search_results);
324       if (INVALID_HANDLE_VALUE==find)
325         ok (0, "file \"%s\" not found\n", filename);
326       else {
327         ret = FindClose(find);
328         ok ( 0 != ret, "FindClose complains (%d)\n", GetLastError ());
329         ok (!strcmp (filename, search_results.cFileName),
330             "found unexpected name \"%s\"\n", search_results.cFileName);
331         search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
332         ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
333             "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
334             search_results.dwFileAttributes);
335       }
336     ret = DeleteFileA( filename );
337     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
338     }
339 }
340
341
342 static void test__llseek( void )
343 {
344     INT i;
345     HFILE filehandle;
346     char buffer[1];
347     long bytes_read;
348     BOOL ret;
349
350     filehandle = _lcreat( filename, 0 );
351     if (filehandle == HFILE_ERROR)
352     {
353         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
354         return;
355     }
356
357     for (i = 0; i < 400; i++)
358     {
359         ok( _hwrite( filehandle, sillytext, strlen( sillytext ) ) != -1, "_hwrite complains\n" );
360     }
361     ok( _llseek( filehandle, 400 * strlen( sillytext ), FILE_CURRENT ) != -1, "should be able to seek\n" );
362     ok( _llseek( filehandle, 27 + 35 * strlen( sillytext ), FILE_BEGIN ) != -1, "should be able to seek\n" );
363
364     bytes_read = _hread( filehandle, buffer, 1);
365     ok( 1 == bytes_read, "file read size error\n" );
366     ok( buffer[0] == sillytext[27], "_llseek error, it got lost seeking\n" );
367     ok( _llseek( filehandle, -400 * (LONG)strlen( sillytext ), FILE_END ) != -1, "should be able to seek\n" );
368
369     bytes_read = _hread( filehandle, buffer, 1);
370     ok( 1 == bytes_read, "file read size error\n" );
371     ok( buffer[0] == sillytext[0], "_llseek error, it got lost seeking\n" );
372     ok( _llseek( filehandle, 1000000, FILE_END ) != -1, "should be able to seek past file; poor, poor Windows programmers\n" );
373     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
374
375     ret = DeleteFileA( filename );
376     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
377 }
378
379
380 static void test__llopen( void )
381 {
382     HFILE filehandle;
383     UINT bytes_read;
384     char buffer[10000];
385     BOOL ret;
386
387     filehandle = _lcreat( filename, 0 );
388     if (filehandle == HFILE_ERROR)
389     {
390         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
391         return;
392     }
393
394     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
395     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
396
397     filehandle = _lopen( filename, OF_READ );
398     ok( HFILE_ERROR == _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write!\n" );
399     bytes_read = _hread( filehandle, buffer, strlen( sillytext ) );
400     ok( strlen( sillytext )  == bytes_read, "file read size error\n" );
401     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
402
403     filehandle = _lopen( filename, OF_READWRITE );
404     bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
405     ok( strlen( sillytext )  == bytes_read, "file read size error\n" );
406     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
407     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
408
409     filehandle = _lopen( filename, OF_WRITE );
410     ok( HFILE_ERROR == _hread( filehandle, buffer, 1 ), "you should only be able to write this file\n" );
411     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
412     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
413
414     ret = DeleteFileA( filename );
415     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
416     /* TODO - add tests for the SHARE modes  -  use two processes to pull this one off */
417 }
418
419
420 static void test__lread( void )
421 {
422     HFILE filehandle;
423     char buffer[10000];
424     long bytes_read;
425     UINT bytes_wanted;
426     UINT i;
427     BOOL ret;
428
429     filehandle = _lcreat( filename, 0 );
430     if (filehandle == HFILE_ERROR)
431     {
432         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
433         return;
434     }
435
436     ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
437
438     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
439
440     filehandle = _lopen( filename, OF_READ );
441
442     ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError());
443
444     bytes_read = _lread( filehandle, buffer, 2 * strlen( sillytext ) );
445
446     ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
447
448     for (bytes_wanted = 0; bytes_wanted < strlen( sillytext ); bytes_wanted++)
449     {
450         ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
451         ok( _lread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
452         for (i = 0; i < bytes_wanted; i++)
453         {
454             ok( buffer[i] == sillytext[i], "that's not what's written\n" );
455         }
456     }
457
458     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
459
460     ret = DeleteFileA( filename );
461     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
462 }
463
464
465 static void test__lwrite( void )
466 {
467     HFILE filehandle;
468     char buffer[10000];
469     long bytes_read;
470     long bytes_written;
471     long blocks;
472     long i;
473     char *contents;
474     HLOCAL memory_object;
475     char checksum[1];
476     BOOL ret;
477
478     filehandle = _lcreat( filename, 0 );
479     if (filehandle == HFILE_ERROR)
480     {
481         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
482         return;
483     }
484
485     ok( HFILE_ERROR != _lwrite( filehandle, "", 0 ), "_hwrite complains\n" );
486
487     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
488
489     filehandle = _lopen( filename, OF_READ );
490
491     bytes_read = _hread( filehandle, buffer, 1);
492
493     ok( 0 == bytes_read, "file read size error\n" );
494
495     ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
496
497     filehandle = _lopen( filename, OF_READWRITE );
498
499     bytes_written = 0;
500     checksum[0] = '\0';
501     srand( (unsigned)time( NULL ) );
502     for (blocks = 0; blocks < 100; blocks++)
503     {
504         for (i = 0; i < (long)sizeof( buffer ); i++)
505         {
506             buffer[i] = rand(  );
507             checksum[0] = checksum[0] + buffer[i];
508         }
509         ok( HFILE_ERROR != _lwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
510         bytes_written = bytes_written + sizeof( buffer );
511     }
512
513     ok( HFILE_ERROR != _lwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
514     bytes_written++;
515
516     ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
517
518     memory_object = LocalAlloc( LPTR, bytes_written );
519
520     ok( 0 != memory_object, "LocalAlloc fails, could be out of memory\n" );
521
522     contents = LocalLock( memory_object );
523
524     filehandle = _lopen( filename, OF_READ );
525
526     contents = LocalLock( memory_object );
527
528     ok( NULL != contents, "LocalLock whines\n" );
529
530     ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
531
532     checksum[0] = '\0';
533     i = 0;
534     do
535     {
536         checksum[0] += contents[i];
537         i++;
538     }
539     while (i < bytes_written - 1);
540
541     ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
542
543     ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
544
545     ret = DeleteFileA( filename );
546     ok( ret, "DeleteFile failed (%d)\n", GetLastError(  ) );
547 }
548
549 static void test_CopyFileA(void)
550 {
551     char temp_path[MAX_PATH];
552     char source[MAX_PATH], dest[MAX_PATH];
553     static const char prefix[] = "pfx";
554     HANDLE hfile;
555     FILETIME ft1, ft2;
556     char buf[10];
557     DWORD ret;
558     BOOL retok;
559
560     ret = GetTempPathA(MAX_PATH, temp_path);
561     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
562     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
563
564     ret = GetTempFileNameA(temp_path, prefix, 0, source);
565     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
566
567     ret = MoveFileA(source, source);
568     todo_wine ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
569
570     /* make the source have not zero size */
571     hfile = CreateFileA(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
572     ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
573     retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL );
574     ok( retok && ret == sizeof(prefix),
575        "WriteFile error %d\n", GetLastError());
576     ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
577     /* get the file time and change it to prove the difference */
578     ret = GetFileTime(hfile, NULL, NULL, &ft1);
579     ok( ret, "GetFileTime error %d\n", GetLastError());
580     ft1.dwLowDateTime -= 600000000; /* 60 second */
581     ret = SetFileTime(hfile, NULL, NULL, &ft1);
582     ok( ret, "SetFileTime error %d\n", GetLastError());
583     GetFileTime(hfile, NULL, NULL, &ft1);  /* get the actual time back */
584     CloseHandle(hfile);
585
586     ret = GetTempFileNameA(temp_path, prefix, 0, dest);
587     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
588
589     SetLastError(0xdeadbeef);
590     ret = CopyFileA(source, dest, TRUE);
591     ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
592        "CopyFileA: unexpected error %d\n", GetLastError());
593
594     ret = CopyFileA(source, dest, FALSE);
595     ok(ret, "CopyFileA: error %d\n", GetLastError());
596
597     /* make sure that destination has correct size */
598     hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
599     ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
600     ret = GetFileSize(hfile, NULL);
601     ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
602
603     /* make sure that destination has the same filetime */
604     ret = GetFileTime(hfile, NULL, NULL, &ft2);
605     ok( ret, "GetFileTime error %d\n", GetLastError());
606     ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
607
608     SetLastError(0xdeadbeef);
609     ret = CopyFileA(source, dest, FALSE);
610     ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION,
611        "CopyFileA: ret = %d, unexpected error %d\n", ret, GetLastError());
612
613     /* make sure that destination still has correct size */
614     ret = GetFileSize(hfile, NULL);
615     ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
616     retok = ReadFile(hfile, buf, sizeof(buf), &ret, NULL);
617     ok( retok && ret == sizeof(prefix),
618        "ReadFile: error %d\n", GetLastError());
619     ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
620     CloseHandle(hfile);
621
622     ret = DeleteFileA(source);
623     ok(ret, "DeleteFileA: error %d\n", GetLastError());
624     ret = DeleteFileA(dest);
625     ok(ret, "DeleteFileA: error %d\n", GetLastError());
626 }
627
628 static void test_CopyFileW(void)
629 {
630     WCHAR temp_path[MAX_PATH];
631     WCHAR source[MAX_PATH], dest[MAX_PATH];
632     static const WCHAR prefix[] = {'p','f','x',0};
633     DWORD ret;
634
635     ret = GetTempPathW(MAX_PATH, temp_path);
636     if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
637     {
638         win_skip("GetTempPathW is not available\n");
639         return;
640     }
641     ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
642     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
643
644     ret = GetTempFileNameW(temp_path, prefix, 0, source);
645     ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
646
647     ret = GetTempFileNameW(temp_path, prefix, 0, dest);
648     ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
649
650     ret = CopyFileW(source, dest, TRUE);
651     ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
652        "CopyFileW: unexpected error %d\n", GetLastError());
653
654     ret = CopyFileW(source, dest, FALSE);
655     ok(ret, "CopyFileW: error %d\n", GetLastError());
656
657     ret = DeleteFileW(source);
658     ok(ret, "DeleteFileW: error %d\n", GetLastError());
659     ret = DeleteFileW(dest);
660     ok(ret, "DeleteFileW: error %d\n", GetLastError());
661 }
662
663 static void test_CreateFileA(void)
664 {
665     HANDLE hFile;
666     char temp_path[MAX_PATH];
667     char filename[MAX_PATH];
668     static const char prefix[] = "pfx";
669     DWORD ret;
670
671     ret = GetTempPathA(MAX_PATH, temp_path);
672     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
673     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
674
675     ret = GetTempFileNameA(temp_path, prefix, 0, filename);
676     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
677
678     SetLastError(0xdeadbeef);
679     hFile = CreateFileA(filename, GENERIC_READ, 0, NULL,
680                         CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
681     ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
682         "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
683
684     SetLastError(0xdeadbeef);
685     hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
686                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
687     ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
688        "hFile %p, last error %u\n", hFile, GetLastError());
689
690     CloseHandle(hFile);
691
692     SetLastError(0xdeadbeef);
693     hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
694                         OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
695     ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
696        "hFile %p, last error %u\n", hFile, GetLastError());
697
698     CloseHandle(hFile);
699
700     ret = DeleteFileA(filename);
701     ok(ret, "DeleteFileA: error %d\n", GetLastError());
702
703     SetLastError(0xdeadbeef);
704     hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
705                         OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
706     ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
707        "hFile %p, last error %u\n", hFile, GetLastError());
708
709     CloseHandle(hFile);
710
711     ret = DeleteFileA(filename);
712     ok(ret, "DeleteFileA: error %d\n", GetLastError());
713 }
714
715 static void test_CreateFileW(void)
716 {
717     HANDLE hFile;
718     WCHAR temp_path[MAX_PATH];
719     WCHAR filename[MAX_PATH];
720     static const WCHAR emptyW[]={'\0'};
721     static const WCHAR prefix[] = {'p','f','x',0};
722     static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
723     DWORD ret;
724
725     ret = GetTempPathW(MAX_PATH, temp_path);
726     if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
727     {
728         win_skip("GetTempPathW is not available\n");
729         return;
730     }
731     ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
732     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
733
734     ret = GetTempFileNameW(temp_path, prefix, 0, filename);
735     ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
736
737     SetLastError(0xdeadbeef);
738     hFile = CreateFileW(filename, GENERIC_READ, 0, NULL,
739                         CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
740     ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
741         "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
742
743     SetLastError(0xdeadbeef);
744     hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
745                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
746     ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
747        "hFile %p, last error %u\n", hFile, GetLastError());
748
749     CloseHandle(hFile);
750
751     SetLastError(0xdeadbeef);
752     hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
753                         OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
754     ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
755        "hFile %p, last error %u\n", hFile, GetLastError());
756
757     CloseHandle(hFile);
758
759     ret = DeleteFileW(filename);
760     ok(ret, "DeleteFileW: error %d\n", GetLastError());
761
762     SetLastError(0xdeadbeef);
763     hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
764                         OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
765     ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
766        "hFile %p, last error %u\n", hFile, GetLastError());
767
768     CloseHandle(hFile);
769
770     ret = DeleteFileW(filename);
771     ok(ret, "DeleteFileW: error %d\n", GetLastError());
772
773     if (0)
774     {
775         /* this crashes on NT4.0 */
776         hFile = CreateFileW(NULL, GENERIC_READ, 0, NULL,
777                             CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
778         ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
779            "CreateFileW(NULL) returned ret=%p error=%u\n",hFile,GetLastError());
780     }
781
782     hFile = CreateFileW(emptyW, GENERIC_READ, 0, NULL,
783                         CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
784     ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
785        "CreateFileW(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
786
787     /* test the result of opening a nonexistent driver name */
788     hFile = CreateFileW(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
789                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
790     ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
791        "CreateFileW on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
792
793     ret = CreateDirectoryW(filename, NULL);
794     ok(ret == TRUE, "couldn't create temporary directory\n");
795     hFile = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
796                         OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
797     ok(hFile != INVALID_HANDLE_VALUE,
798        "expected CreateFile to succeed on existing directory, error: %d\n", GetLastError());
799     CloseHandle(hFile);
800     ret = RemoveDirectoryW(filename);
801     ok(ret, "DeleteFileW: error %d\n", GetLastError());
802 }
803
804 static void test_GetTempFileNameA(void)
805 {
806     UINT result;
807     char out[MAX_PATH];
808     char expected[MAX_PATH + 10];
809     char windowsdir[MAX_PATH + 10];
810     char windowsdrive[3];
811
812     result = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
813     ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
814     ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
815
816     /* If the Windows directory is the root directory, it ends in backslash, not else. */
817     if (strlen(windowsdir) != 3) /* As in  "C:\"  or  "F:\"  */
818     {
819         strcat(windowsdir, "\\");
820     }
821
822     windowsdrive[0] = windowsdir[0];
823     windowsdrive[1] = windowsdir[1];
824     windowsdrive[2] = '\0';
825
826     result = GetTempFileNameA(windowsdrive, "abc", 1, out);
827     ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
828     ok(((out[0] == windowsdrive[0]) && (out[1] == ':')) && (out[2] == '\\'),
829        "GetTempFileNameA: first three characters should be %c:\\, string was actually %s\n",
830        windowsdrive[0], out);
831
832     result = GetTempFileNameA(windowsdir, "abc", 2, out);
833     ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
834     expected[0] = '\0';
835     strcat(expected, windowsdir);
836     strcat(expected, "abc2.tmp");
837     ok(lstrcmpiA(out, expected) == 0, "GetTempFileNameA: Unexpected output \"%s\" vs \"%s\"\n",
838        out, expected);
839 }
840
841 static void test_DeleteFileA( void )
842 {
843     BOOL ret;
844
845     ret = DeleteFileA(NULL);
846     ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER ||
847                 GetLastError() == ERROR_PATH_NOT_FOUND),
848        "DeleteFileA(NULL) returned ret=%d error=%d\n",ret,GetLastError());
849
850     ret = DeleteFileA("");
851     ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND ||
852                 GetLastError() == ERROR_BAD_PATHNAME),
853        "DeleteFileA(\"\") returned ret=%d error=%d\n",ret,GetLastError());
854
855     ret = DeleteFileA("nul");
856     ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
857                 GetLastError() == ERROR_INVALID_PARAMETER ||
858                 GetLastError() == ERROR_ACCESS_DENIED ||
859                 GetLastError() == ERROR_INVALID_FUNCTION),
860        "DeleteFileA(\"nul\") returned ret=%d error=%d\n",ret,GetLastError());
861 }
862
863 static void test_DeleteFileW( void )
864 {
865     BOOL ret;
866     WCHAR pathW[MAX_PATH];
867     WCHAR pathsubW[MAX_PATH];
868     static const WCHAR dirW[] = {'d','e','l','e','t','e','f','i','l','e',0};
869     static const WCHAR subdirW[] = {'\\','s','u','b',0};
870     static const WCHAR emptyW[]={'\0'};
871
872     ret = DeleteFileW(NULL);
873     if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
874     {
875         win_skip("DeleteFileW is not available\n");
876         return;
877     }
878     ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
879        "DeleteFileW(NULL) returned ret=%d error=%d\n",ret,GetLastError());
880
881     ret = DeleteFileW(emptyW);
882     ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
883        "DeleteFileW(\"\") returned ret=%d error=%d\n",ret,GetLastError());
884
885     /* test DeleteFile on empty directory */
886     ret = GetTempPathW(MAX_PATH, pathW);
887     if (ret + sizeof(dirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
888     {
889         ok(0, "MAX_PATH exceeded in constructing paths\n");
890         return;
891     }
892     lstrcatW(pathW, dirW);
893     lstrcpyW(pathsubW, pathW);
894     lstrcatW(pathsubW, subdirW);
895     ret = CreateDirectoryW(pathW, NULL);
896     ok(ret == TRUE, "couldn't create directory deletefile\n");
897     ret = DeleteFileW(pathW);
898     ok(ret == FALSE, "DeleteFile should fail for empty directories\n");
899     ret = RemoveDirectoryW(pathW);
900     ok(ret == TRUE, "expected to remove directory deletefile\n");
901
902     /* test DeleteFile on non-empty directory */
903     ret = CreateDirectoryW(pathW, NULL);
904     ok(ret == TRUE, "couldn't create directory deletefile\n");
905     ret = CreateDirectoryW(pathsubW, NULL);
906     ok(ret == TRUE, "couldn't create directory deletefile\\sub\n");
907     ret = DeleteFileW(pathW);
908     ok(ret == FALSE, "DeleteFile should fail for non-empty directories\n");
909     ret = RemoveDirectoryW(pathsubW);
910     ok(ret == TRUE, "expected to remove directory deletefile\\sub\n");
911     ret = RemoveDirectoryW(pathW);
912     ok(ret == TRUE, "expected to remove directory deletefile\n");
913 }
914
915 #define IsDotDir(x)     ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
916
917 static void test_MoveFileA(void)
918 {
919     char tempdir[MAX_PATH];
920     char source[MAX_PATH], dest[MAX_PATH];
921     static const char prefix[] = "pfx";
922     DWORD ret;
923
924     ret = GetTempPathA(MAX_PATH, tempdir);
925     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
926     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
927
928     ret = GetTempFileNameA(tempdir, prefix, 0, source);
929     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
930
931     ret = GetTempFileNameA(tempdir, prefix, 0, dest);
932     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
933
934     ret = MoveFileA(source, dest);
935     ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
936        "MoveFileA: unexpected error %d\n", GetLastError());
937
938     ret = DeleteFileA(dest);
939     ok(ret, "DeleteFileA: error %d\n", GetLastError());
940
941     ret = MoveFileA(source, dest);
942     ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
943
944     lstrcatA(tempdir, "Remove Me");
945     ret = CreateDirectoryA(tempdir, NULL);
946     ok(ret == TRUE, "CreateDirectoryA failed\n");
947
948     lstrcpyA(source, dest);
949     lstrcpyA(dest, tempdir);
950     lstrcatA(dest, "\\wild?.*");
951     /* FIXME: if we create a file with wildcards we can't delete it now that DeleteFile works correctly */
952     ret = MoveFileA(source, dest);
953     ok(!ret, "MoveFileA: shouldn't move to wildcard file\n");
954     ok(GetLastError() == ERROR_INVALID_NAME || /* NT */
955        GetLastError() == ERROR_FILE_NOT_FOUND, /* Win9x */
956        "MoveFileA: with wildcards, unexpected error %d\n", GetLastError());
957     if (ret || (GetLastError() != ERROR_INVALID_NAME))
958     {
959         WIN32_FIND_DATAA fd;
960         char temppath[MAX_PATH];
961         HANDLE hFind;
962
963         lstrcpyA(temppath, tempdir);
964         lstrcatA(temppath, "\\*.*");
965         hFind = FindFirstFileA(temppath, &fd);
966         if (INVALID_HANDLE_VALUE != hFind)
967         {
968           LPSTR lpName;
969           do
970           {
971             lpName = fd.cAlternateFileName;
972             if (!lpName[0])
973               lpName = fd.cFileName;
974             ok(IsDotDir(lpName), "MoveFileA: wildcards file created!\n");
975           }
976           while (FindNextFileA(hFind, &fd));
977           FindClose(hFind);
978         }
979     }
980     ret = DeleteFileA(source);
981     ok(ret, "DeleteFileA: error %d\n", GetLastError());
982     ret = DeleteFileA(dest);
983     ok(!ret, "DeleteFileA: error %d\n", GetLastError());
984     ret = RemoveDirectoryA(tempdir);
985     ok(ret, "DeleteDirectoryA: error %d\n", GetLastError());
986 }
987
988 static void test_MoveFileW(void)
989 {
990     WCHAR temp_path[MAX_PATH];
991     WCHAR source[MAX_PATH], dest[MAX_PATH];
992     static const WCHAR prefix[] = {'p','f','x',0};
993     DWORD ret;
994
995     ret = GetTempPathW(MAX_PATH, temp_path);
996     if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
997     {
998         win_skip("GetTempPathW is not available\n");
999         return;
1000     }
1001     ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1002     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1003
1004     ret = GetTempFileNameW(temp_path, prefix, 0, source);
1005     ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1006
1007     ret = GetTempFileNameW(temp_path, prefix, 0, dest);
1008     ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1009
1010     ret = MoveFileW(source, dest);
1011     ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
1012        "CopyFileW: unexpected error %d\n", GetLastError());
1013
1014     ret = DeleteFileW(source);
1015     ok(ret, "DeleteFileW: error %d\n", GetLastError());
1016     ret = DeleteFileW(dest);
1017     ok(ret, "DeleteFileW: error %d\n", GetLastError());
1018 }
1019
1020 #define PATTERN_OFFSET 0x10
1021
1022 static void test_offset_in_overlapped_structure(void)
1023 {
1024     HANDLE hFile;
1025     OVERLAPPED ov;
1026     DWORD done, offset;
1027     BOOL rc;
1028     BYTE buf[256], pattern[] = "TeSt";
1029     UINT i;
1030     char temp_path[MAX_PATH], temp_fname[MAX_PATH];
1031     BOOL ret;
1032
1033     ret =GetTempPathA(MAX_PATH, temp_path);
1034     ok( ret, "GetTempPathA error %d\n", GetLastError());
1035     ret =GetTempFileNameA(temp_path, "pfx", 0, temp_fname);
1036     ok( ret, "GetTempFileNameA error %d\n", GetLastError());
1037
1038     /*** Write File *****************************************************/
1039
1040     hFile = CreateFileA(temp_fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1041     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
1042
1043     for(i = 0; i < sizeof(buf); i++) buf[i] = i;
1044     ret = WriteFile(hFile, buf, sizeof(buf), &done, NULL);
1045     ok( ret, "WriteFile error %d\n", GetLastError());
1046     ok(done == sizeof(buf), "expected number of bytes written %u\n", done);
1047
1048     memset(&ov, 0, sizeof(ov));
1049     S(U(ov)).Offset = PATTERN_OFFSET;
1050     S(U(ov)).OffsetHigh = 0;
1051     rc=WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
1052     /* Win 9x does not support the overlapped I/O on files */
1053     if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
1054         ok(rc, "WriteFile error %d\n", GetLastError());
1055         ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
1056         offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1057         ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
1058
1059         S(U(ov)).Offset = sizeof(buf) * 2;
1060         S(U(ov)).OffsetHigh = 0;
1061         ret = WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
1062         ok( ret, "WriteFile error %d\n", GetLastError());
1063         ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
1064         offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1065         ok(offset == sizeof(buf) * 2 + sizeof(pattern), "wrong file offset %d\n", offset);
1066     }
1067
1068     CloseHandle(hFile);
1069
1070     /*** Read File *****************************************************/
1071
1072     hFile = CreateFileA(temp_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
1073     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
1074
1075     memset(buf, 0, sizeof(buf));
1076     memset(&ov, 0, sizeof(ov));
1077     S(U(ov)).Offset = PATTERN_OFFSET;
1078     S(U(ov)).OffsetHigh = 0;
1079     rc=ReadFile(hFile, buf, sizeof(pattern), &done, &ov);
1080     /* Win 9x does not support the overlapped I/O on files */
1081     if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
1082         ok(rc, "ReadFile error %d\n", GetLastError());
1083         ok(done == sizeof(pattern), "expected number of bytes read %u\n", done);
1084         offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1085         ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
1086         ok(!memcmp(buf, pattern, sizeof(pattern)), "pattern match failed\n");
1087     }
1088
1089     CloseHandle(hFile);
1090
1091     ret = DeleteFileA(temp_fname);
1092     ok( ret, "DeleteFileA error %d\n", GetLastError());
1093 }
1094
1095 static void test_LockFile(void)
1096 {
1097     HANDLE handle;
1098     DWORD written;
1099     OVERLAPPED overlapped;
1100     int limited_LockFile;
1101     int limited_UnLockFile;
1102     BOOL ret;
1103
1104     handle = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1105                           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1106                           CREATE_ALWAYS, 0, 0 );
1107     if (handle == INVALID_HANDLE_VALUE)
1108     {
1109         ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
1110         return;
1111     }
1112     ok( WriteFile( handle, sillytext, strlen(sillytext), &written, NULL ), "write failed\n" );
1113
1114     ok( LockFile( handle, 0, 0, 0, 0 ), "LockFile failed\n" );
1115     ok( UnlockFile( handle, 0, 0, 0, 0 ), "UnlockFile failed\n" );
1116
1117     limited_UnLockFile = 0;
1118     if (UnlockFile( handle, 0, 0, 0, 0 ))
1119     {
1120         limited_UnLockFile = 1;
1121     }
1122
1123     ok( LockFile( handle, 10, 0, 20, 0 ), "LockFile 10,20 failed\n" );
1124     /* overlapping locks must fail */
1125     ok( !LockFile( handle, 12, 0, 10, 0 ), "LockFile 12,10 succeeded\n" );
1126     ok( !LockFile( handle, 5, 0, 6, 0 ), "LockFile 5,6 succeeded\n" );
1127     /* non-overlapping locks must succeed */
1128     ok( LockFile( handle, 5, 0, 5, 0 ), "LockFile 5,5 failed\n" );
1129
1130     ok( !UnlockFile( handle, 10, 0, 10, 0 ), "UnlockFile 10,10 succeeded\n" );
1131     ok( UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 failed\n" );
1132     ok( !UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 again succeeded\n" );
1133     ok( UnlockFile( handle, 5, 0, 5, 0 ), "UnlockFile 5,5 failed\n" );
1134
1135     S(U(overlapped)).Offset = 100;
1136     S(U(overlapped)).OffsetHigh = 0;
1137     overlapped.hEvent = 0;
1138
1139     /* Test for broken LockFileEx a la Windows 95 OSR2. */
1140     if (LockFileEx( handle, 0, 0, 100, 0, &overlapped ))
1141     {
1142         /* LockFileEx is probably OK, test it more. */
1143         ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ),
1144             "LockFileEx 100,100 failed\n" );
1145     }
1146
1147     /* overlapping shared locks are OK */
1148     S(U(overlapped)).Offset = 150;
1149     limited_UnLockFile || ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 150,100 failed\n" );
1150
1151     /* but exclusive is not */
1152     ok( !LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
1153                      0, 50, 0, &overlapped ),
1154         "LockFileEx exclusive 150,50 succeeded\n" );
1155     if (!UnlockFileEx( handle, 0, 100, 0, &overlapped ))
1156     { /* UnLockFile is capable. */
1157         S(U(overlapped)).Offset = 100;
1158         ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ),
1159             "UnlockFileEx 150,100 again succeeded\n" );
1160     }
1161
1162     ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 );
1163     if (ret)
1164     {
1165         ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
1166         ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
1167         ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
1168     }
1169     else  /* win9x */
1170         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong LockFile error %u\n", GetLastError() );
1171
1172     /* wrap-around lock should not do anything */
1173     /* (but still succeeds on NT4 so we don't check result) */
1174     LockFile( handle, 0, 0x10000000, 0, 0xf0000001 );
1175
1176     limited_LockFile = 0;
1177     if (!LockFile( handle, ~0, ~0, 1, 0 ))
1178     {
1179         limited_LockFile = 1;
1180     }
1181
1182     limited_UnLockFile || ok( UnlockFile( handle, ~0, ~0, 1, 0 ), "Unlockfile ~0,1 failed\n" );
1183
1184     /* zero-byte lock */
1185     ok( LockFile( handle, 100, 0, 0, 0 ), "LockFile 100,0 failed\n" );
1186     limited_LockFile || ok( !LockFile( handle, 98, 0, 4, 0 ), "LockFile 98,4 succeeded\n" );
1187     ok( LockFile( handle, 90, 0, 10, 0 ), "LockFile 90,10 failed\n" );
1188     limited_LockFile || ok( !LockFile( handle, 100, 0, 10, 0 ), "LockFile 100,10 failed\n" );
1189
1190     ok( UnlockFile( handle, 90, 0, 10, 0 ), "UnlockFile 90,10 failed\n" );
1191     !ok( UnlockFile( handle, 100, 0, 10, 0 ), "UnlockFile 100,10 failed\n" );
1192
1193     ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed\n" );
1194
1195     CloseHandle( handle );
1196     DeleteFileA( filename );
1197 }
1198
1199 static inline int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2, BOOL is_win9x )
1200 {
1201     if (!is_win9x)
1202     {
1203         if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
1204         if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
1205     }
1206     else
1207     {
1208         access1 &= ~DELETE;
1209         if (!access1) access1 = GENERIC_READ;
1210
1211         access2 &= ~DELETE;
1212         if (!access2) access2 = GENERIC_READ;
1213     }
1214
1215     if ((access1 & GENERIC_READ) && !(sharing2 & FILE_SHARE_READ)) return 0;
1216     if ((access1 & GENERIC_WRITE) && !(sharing2 & FILE_SHARE_WRITE)) return 0;
1217     if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return 0;
1218     if ((access2 & GENERIC_READ) && !(sharing1 & FILE_SHARE_READ)) return 0;
1219     if ((access2 & GENERIC_WRITE) && !(sharing1 & FILE_SHARE_WRITE)) return 0;
1220     if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return 0;
1221     return 1;
1222 }
1223
1224 static void test_file_sharing(void)
1225 {
1226     static const DWORD access_modes[] =
1227         { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE,
1228           DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE };
1229     static const DWORD sharing_modes[] =
1230         { 0, FILE_SHARE_READ,
1231           FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
1232           FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_DELETE,
1233           FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE };
1234     int a1, s1, a2, s2;
1235     int ret;
1236     HANDLE h, h2;
1237     BOOL is_win9x = FALSE;
1238
1239     /* make sure the file exists */
1240     h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1241     if (h == INVALID_HANDLE_VALUE)
1242     {
1243         ok(0, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError());
1244         return;
1245     }
1246     is_win9x = GetFileAttributesW(filenameW) == INVALID_FILE_ATTRIBUTES;
1247     CloseHandle( h );
1248
1249     for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++)
1250     {
1251         for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++)
1252         {
1253             /* Win9x doesn't support FILE_SHARE_DELETE */
1254             if (is_win9x && (sharing_modes[s1] & FILE_SHARE_DELETE))
1255                 continue;
1256
1257             SetLastError(0xdeadbeef);
1258             h = CreateFileA( filename, access_modes[a1], sharing_modes[s1],
1259                              NULL, OPEN_EXISTING, 0, 0 );
1260             if (h == INVALID_HANDLE_VALUE)
1261             {
1262                 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
1263                 return;
1264             }
1265             for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
1266             {
1267                 for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
1268                 {
1269                     /* Win9x doesn't support FILE_SHARE_DELETE */
1270                     if (is_win9x && (sharing_modes[s2] & FILE_SHARE_DELETE))
1271                         continue;
1272
1273                     SetLastError(0xdeadbeef);
1274                     h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
1275                                       NULL, OPEN_EXISTING, 0, 0 );
1276
1277                     if (is_sharing_compatible( access_modes[a1], sharing_modes[s1],
1278                                                access_modes[a2], sharing_modes[s2], is_win9x ))
1279                     {
1280                         ret = GetLastError();
1281
1282                         ok( h2 != INVALID_HANDLE_VALUE,
1283                             "open failed for modes %x/%x/%x/%x\n",
1284                             access_modes[a1], sharing_modes[s1],
1285                             access_modes[a2], sharing_modes[s2] );
1286                         ok( ret == 0xdeadbeef /* Win9x */ ||
1287                             ret == 0, /* XP */
1288                              "wrong error code %d\n", ret );
1289
1290                         CloseHandle( h2 );
1291                     }
1292                     else
1293                     {
1294                         ret = GetLastError();
1295
1296                         ok( h2 == INVALID_HANDLE_VALUE,
1297                             "open succeeded for modes %x/%x/%x/%x\n",
1298                             access_modes[a1], sharing_modes[s1],
1299                             access_modes[a2], sharing_modes[s2] );
1300                          ok( ret == ERROR_SHARING_VIOLATION,
1301                              "wrong error code %d\n", ret );
1302                     }
1303                 }
1304             }
1305             CloseHandle( h );
1306         }
1307     }
1308
1309     SetLastError(0xdeadbeef);
1310     h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0 );
1311     ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
1312
1313     SetLastError(0xdeadbeef);
1314     h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1315     ok( h2 == INVALID_HANDLE_VALUE, "CreateFileA should fail\n");
1316     ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error code %d\n", GetLastError() );
1317
1318     h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
1319     ok( h2 != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
1320
1321     CloseHandle(h);
1322     CloseHandle(h2);
1323
1324     DeleteFileA( filename );
1325 }
1326
1327 static char get_windows_drive(void)
1328 {
1329     char windowsdir[MAX_PATH];
1330     GetWindowsDirectory(windowsdir, sizeof(windowsdir));
1331     return windowsdir[0];
1332 }
1333
1334 static void test_FindFirstFileA(void)
1335 {
1336     HANDLE handle;
1337     WIN32_FIND_DATAA data;
1338     int err;
1339     char buffer[5] = "C:\\";
1340     char buffer2[100];
1341     char nonexistent[MAX_PATH];
1342
1343     /* try FindFirstFileA on "C:\" */
1344     buffer[0] = get_windows_drive();
1345     
1346     SetLastError( 0xdeadbeaf );
1347     handle = FindFirstFileA(buffer, &data);
1348     err = GetLastError();
1349     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on root directory should fail\n" );
1350     ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
1351
1352     /* try FindFirstFileA on "C:\*" */
1353     strcpy(buffer2, buffer);
1354     strcat(buffer2, "*");
1355     handle = FindFirstFileA(buffer2, &data);
1356     ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
1357     ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
1358          "FindFirstFile shouldn't return '%s' in drive root\n", data.cFileName );
1359     if (FindNextFileA( handle, &data ))
1360         ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
1361              "FindNextFile shouldn't return '%s' in drive root\n", data.cFileName );
1362     ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
1363
1364     /* try FindFirstFileA on windows dir */
1365     GetWindowsDirectory( buffer2, sizeof(buffer2) );
1366     strcat(buffer2, "\\*");
1367     handle = FindFirstFileA(buffer2, &data);
1368     ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
1369     ok( !strcmp( data.cFileName, "." ), "FindFirstFile should return '.' first\n" );
1370     ok( FindNextFileA( handle, &data ), "FindNextFile failed\n" );
1371     ok( !strcmp( data.cFileName, ".." ), "FindNextFile should return '..' as second entry\n" );
1372     while (FindNextFileA( handle, &data ))
1373         ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
1374              "FindNextFile shouldn't return '%s'\n", data.cFileName );
1375     ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
1376
1377     /* try FindFirstFileA on "C:\foo\" */
1378     SetLastError( 0xdeadbeaf );
1379     if (!GetTempFileNameA( buffer, "foo", 0, nonexistent ) && GetLastError() == ERROR_ACCESS_DENIED)
1380     {
1381         char tmp[MAX_PATH];
1382         GetTempPathA( sizeof(tmp), tmp );
1383         GetTempFileNameA( tmp, "foo", 0, nonexistent );
1384     }
1385     DeleteFileA( nonexistent );
1386     strcpy(buffer2, nonexistent);
1387     strcat(buffer2, "\\");
1388     handle = FindFirstFileA(buffer2, &data);
1389     err = GetLastError();
1390     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1391     todo_wine {
1392         ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
1393     }
1394
1395     /* try FindFirstFileA on "C:\foo\bar.txt" */
1396     SetLastError( 0xdeadbeaf );
1397     strcpy(buffer2, nonexistent);
1398     strcat(buffer2, "\\bar.txt");
1399     handle = FindFirstFileA(buffer2, &data);
1400     err = GetLastError();
1401     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1402     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
1403
1404     /* try FindFirstFileA on "C:\foo\*.*" */
1405     SetLastError( 0xdeadbeaf );
1406     strcpy(buffer2, nonexistent);
1407     strcat(buffer2, "\\*.*");
1408     handle = FindFirstFileA(buffer2, &data);
1409     err = GetLastError();
1410     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1411     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
1412
1413     /* try FindFirstFileA on "foo\bar.txt" */
1414     SetLastError( 0xdeadbeaf );
1415     strcpy(buffer2, nonexistent + 3);
1416     strcat(buffer2, "\\bar.txt");
1417     handle = FindFirstFileA(buffer2, &data);
1418     err = GetLastError();
1419     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1420     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
1421
1422     /* try FindFirstFileA on "c:\nul" */
1423     SetLastError( 0xdeadbeaf );
1424     strcpy(buffer2, buffer);
1425     strcat(buffer2, "nul");
1426     handle = FindFirstFileA(buffer2, &data);
1427     err = GetLastError();
1428     ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
1429     ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
1430     ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
1431         FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
1432         "wrong attributes %x\n", data.dwFileAttributes );
1433     if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
1434     {
1435         ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
1436         ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
1437     }
1438     SetLastError( 0xdeadbeaf );
1439     ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
1440     ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
1441     ok( FindClose( handle ), "failed to close handle\n" );
1442
1443     /* try FindFirstFileA on "lpt1" */
1444     SetLastError( 0xdeadbeaf );
1445     strcpy(buffer2, "lpt1");
1446     handle = FindFirstFileA(buffer2, &data);
1447     err = GetLastError();
1448     ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
1449     ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
1450     ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
1451         FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
1452         "wrong attributes %x\n", data.dwFileAttributes );
1453     if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
1454     {
1455         ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
1456         ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
1457     }
1458     SetLastError( 0xdeadbeaf );
1459     ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
1460     ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
1461     ok( FindClose( handle ), "failed to close handle\n" );
1462
1463     /* try FindFirstFileA on "c:\nul\*" */
1464     SetLastError( 0xdeadbeaf );
1465     strcpy(buffer2, buffer);
1466     strcat(buffer2, "nul\\*");
1467     handle = FindFirstFileA(buffer2, &data);
1468     err = GetLastError();
1469     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1470     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
1471
1472     /* try FindFirstFileA on "c:\nul*" */
1473     SetLastError( 0xdeadbeaf );
1474     strcpy(buffer2, buffer);
1475     strcat(buffer2, "nul*");
1476     handle = FindFirstFileA(buffer2, &data);
1477     err = GetLastError();
1478     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1479     ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
1480
1481     /* try FindFirstFileA on "c:\foo\bar\nul" */
1482     SetLastError( 0xdeadbeaf );
1483     strcpy(buffer2, buffer);
1484     strcat(buffer2, "foo\\bar\\nul");
1485     handle = FindFirstFileA(buffer2, &data);
1486     err = GetLastError();
1487     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1488     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
1489
1490     /* try FindFirstFileA on "c:\foo\nul\bar" */
1491     SetLastError( 0xdeadbeaf );
1492     strcpy(buffer2, buffer);
1493     strcat(buffer2, "foo\\nul\\bar");
1494     handle = FindFirstFileA(buffer2, &data);
1495     err = GetLastError();
1496     ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
1497     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
1498 }
1499
1500 static void test_FindNextFileA(void)
1501 {
1502     HANDLE handle;
1503     WIN32_FIND_DATAA search_results;
1504     int err;
1505     char buffer[5] = "C:\\*";
1506
1507     buffer[0] = get_windows_drive();
1508     handle = FindFirstFileA(buffer,&search_results);
1509     ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed\n" );
1510     while (FindNextFile(handle, &search_results))
1511     {
1512         /* get to the end of the files */
1513     }
1514     ok ( FindClose(handle) == TRUE, "Failed to close handle\n");
1515     err = GetLastError();
1516     ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES\n");
1517 }
1518
1519 static void test_FindFirstFileExA(void)
1520 {
1521     WIN32_FIND_DATAA search_results;
1522     HANDLE handle;
1523
1524     if (!pFindFirstFileExA)
1525     {
1526         win_skip("FindFirstFileExA() is missing\n");
1527         return;
1528     }
1529
1530     CreateDirectoryA("test-dir", NULL);
1531     _lclose(_lcreat("test-dir\\file1", 0));
1532     _lclose(_lcreat("test-dir\\file2", 0));
1533     CreateDirectoryA("test-dir\\dir1", NULL);
1534     /* FindExLimitToDirectories is ignored */
1535     SetLastError(0xdeadbeef);
1536     handle = pFindFirstFileExA("test-dir\\*", FindExInfoStandard, &search_results, FindExSearchLimitToDirectories, NULL, 0);
1537     if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1538     {
1539         win_skip("FindFirstFileExA is not implemented\n");
1540         goto cleanup;
1541     }
1542     ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
1543     ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
1544
1545 #define CHECK_NAME(fn) (strcmp((fn), "file1") == 0 || strcmp((fn), "file2") == 0 || strcmp((fn), "dir1") == 0)
1546
1547     ok(FindNextFile(handle, &search_results), "Fetching second file failed\n");
1548     ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
1549
1550     ok(FindNextFile(handle, &search_results), "Fetching third file failed\n");
1551     ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
1552
1553     ok(FindNextFile(handle, &search_results), "Fetching fourth file failed\n");
1554     ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
1555
1556     ok(FindNextFile(handle, &search_results), "Fetching fifth file failed\n");
1557     ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName);
1558
1559 #undef CHECK_NAME
1560
1561     ok(FindNextFile(handle, &search_results) == FALSE, "Fetching sixth file should failed\n");
1562
1563     FindClose( handle );
1564
1565 cleanup:
1566     DeleteFileA("test-dir\\file1");
1567     DeleteFileA("test-dir\\file2");
1568     RemoveDirectoryA("test-dir\\dir1");
1569     RemoveDirectoryA("test-dir");
1570 }
1571
1572 static int test_Mapfile_createtemp(HANDLE *handle)
1573 {
1574     SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL);
1575     DeleteFile(filename);
1576     *handle = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, 0,
1577                          CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1578     if (*handle != INVALID_HANDLE_VALUE) {
1579
1580         return 1;
1581     }
1582
1583     return 0;
1584 }
1585
1586 static void test_MapFile(void)
1587 {
1588     HANDLE handle;
1589     HANDLE hmap;
1590
1591     ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
1592
1593     hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" );
1594     ok( hmap != NULL, "mapping should work, I named it!\n" );
1595
1596     ok( CloseHandle( hmap ), "can't close mapping handle\n");
1597
1598     /* We have to close file before we try new stuff with mapping again.
1599        Else we would always succeed on XP or block descriptors on 95. */
1600     hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
1601     ok( hmap != NULL, "We should still be able to map!\n" );
1602     ok( CloseHandle( hmap ), "can't close mapping handle\n");
1603     ok( CloseHandle( handle ), "can't close file handle\n");
1604     handle = NULL;
1605
1606     ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
1607
1608     hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
1609     ok( hmap == NULL, "mapped zero size file\n");
1610     ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
1611
1612     hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
1613     ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
1614     /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
1615     if ( hmap )
1616         CloseHandle( hmap );
1617
1618     hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
1619     ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
1620     /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
1621     if ( hmap )
1622         CloseHandle( hmap );
1623
1624     /* On XP you can now map again, on Win 95 you cannot. */
1625
1626     ok( CloseHandle( handle ), "can't close file handle\n");
1627     ok( DeleteFileA( filename ), "DeleteFile failed after map\n" );
1628 }
1629
1630 static void test_GetFileType(void)
1631 {
1632     DWORD type;
1633     HANDLE h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1634     ok( h != INVALID_HANDLE_VALUE, "open %s failed\n", filename );
1635     type = GetFileType(h);
1636     ok( type == FILE_TYPE_DISK, "expected type disk got %d\n", type );
1637     CloseHandle( h );
1638     h = CreateFileA( "nul", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
1639     ok( h != INVALID_HANDLE_VALUE, "open nul failed\n" );
1640     type = GetFileType(h);
1641     ok( type == FILE_TYPE_CHAR, "expected type char for nul got %d\n", type );
1642     CloseHandle( h );
1643     DeleteFileA( filename );
1644 }
1645
1646 static int completion_count;
1647
1648 static void CALLBACK FileIOComplete(DWORD dwError, DWORD dwBytes, LPOVERLAPPED ovl)
1649 {
1650 /*      printf("(%ld, %ld, %p { %ld, %ld, %ld, %ld, %p })\n", dwError, dwBytes, ovl, ovl->Internal, ovl->InternalHigh, ovl->Offset, ovl->OffsetHigh, ovl->hEvent);*/
1651         ReleaseSemaphore(ovl->hEvent, 1, NULL);
1652         completion_count++;
1653 }
1654
1655 static void test_async_file_errors(void)
1656 {
1657     char szFile[MAX_PATH];
1658     HANDLE hSem = CreateSemaphoreW(NULL, 1, 1, NULL);
1659     HANDLE hFile;
1660     LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096);
1661     OVERLAPPED ovl;
1662     S(U(ovl)).Offset = 0;
1663     S(U(ovl)).OffsetHigh = 0;
1664     ovl.hEvent = hSem;
1665     completion_count = 0;
1666     szFile[0] = '\0';
1667     GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini"));
1668     strcat(szFile, "\\win.ini");
1669     hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1670                         NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
1671     if (hFile == INVALID_HANDLE_VALUE)  /* win9x doesn't like FILE_SHARE_DELETE */
1672         hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1673                             NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
1674     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA(%s ...) failed\n", szFile);
1675     while (TRUE)
1676     {
1677         BOOL res;
1678         DWORD count;
1679         while (WaitForSingleObjectEx(hSem, INFINITE, TRUE) == WAIT_IO_COMPLETION)
1680             ;
1681         res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete);
1682         /*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
1683         if (!res)
1684             break;
1685         if (!GetOverlappedResult(hFile, &ovl, &count, FALSE))
1686             break;
1687         S(U(ovl)).Offset += count;
1688         /* i/o completion routine only called if ReadFileEx returned success.
1689          * we only care about violations of this rule so undo what should have
1690          * been done */
1691         completion_count--;
1692     }
1693     ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count);
1694     /*printf("Error = %ld\n", GetLastError());*/
1695     HeapFree(GetProcessHeap(), 0, lpBuffer);
1696 }
1697
1698 static void test_read_write(void)
1699 {
1700     DWORD bytes, ret, old_prot;
1701     HANDLE hFile;
1702     char temp_path[MAX_PATH];
1703     char filename[MAX_PATH];
1704     char *mem;
1705     static const char prefix[] = "pfx";
1706
1707     ret = GetTempPathA(MAX_PATH, temp_path);
1708     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1709     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1710
1711     ret = GetTempFileNameA(temp_path, prefix, 0, filename);
1712     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1713
1714     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1715                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1716     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
1717
1718     SetLastError(12345678);
1719     bytes = 12345678;
1720     ret = WriteFile(hFile, NULL, 0, &bytes, NULL);
1721     ok(ret && GetLastError() == 12345678,
1722         "ret = %d, error %d\n", ret, GetLastError());
1723     ok(!bytes, "bytes = %d\n", bytes);
1724
1725     SetLastError(12345678);
1726     bytes = 12345678;
1727     ret = WriteFile(hFile, NULL, 10, &bytes, NULL);
1728     ok((!ret && GetLastError() == ERROR_INVALID_USER_BUFFER) || /* Win2k */
1729         (ret && GetLastError() == 12345678), /* Win9x */
1730         "ret = %d, error %d\n", ret, GetLastError());
1731     ok(!bytes || /* Win2k */
1732         bytes == 10, /* Win9x */
1733         "bytes = %d\n", bytes);
1734
1735     /* make sure the file contains data */
1736     WriteFile(hFile, "this is the test data", 21, &bytes, NULL);
1737     SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
1738
1739     SetLastError(12345678);
1740     bytes = 12345678;
1741     ret = ReadFile(hFile, NULL, 0, &bytes, NULL);
1742     ok(ret && GetLastError() == 12345678,
1743         "ret = %d, error %d\n", ret, GetLastError());
1744     ok(!bytes, "bytes = %d\n", bytes);
1745
1746     SetLastError(12345678);
1747     bytes = 12345678;
1748     ret = ReadFile(hFile, NULL, 10, &bytes, NULL);
1749     ok(!ret && (GetLastError() == ERROR_NOACCESS || /* Win2k */
1750                 GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1751         "ret = %d, error %d\n", ret, GetLastError());
1752     ok(!bytes, "bytes = %d\n", bytes);
1753
1754     /* test passing protected memory as buffer */
1755
1756     mem = VirtualAlloc( NULL, 0x4000, MEM_COMMIT, PAGE_READWRITE );
1757     ok( mem != NULL, "failed to allocate virtual mem error %u\n", GetLastError() );
1758
1759     ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
1760     ok( ret, "WriteFile failed error %u\n", GetLastError() );
1761     ok( bytes == 0x4000, "only wrote %x bytes\n", bytes );
1762
1763     ret = VirtualProtect( mem + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
1764     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1765
1766     ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
1767     ok( !ret, "WriteFile succeeded\n" );
1768     ok( GetLastError() == ERROR_INVALID_USER_BUFFER ||
1769         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1770         "wrong error %u\n", GetLastError() );
1771     ok( bytes == 0, "wrote %x bytes\n", bytes );
1772
1773     ret = WriteFile( (HANDLE)0xdead, mem, 0x4000, &bytes, NULL );
1774     ok( !ret, "WriteFile succeeded\n" );
1775     ok( GetLastError() == ERROR_INVALID_HANDLE || /* handle is checked before buffer on NT */
1776         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1777         "wrong error %u\n", GetLastError() );
1778     ok( bytes == 0, "wrote %x bytes\n", bytes );
1779
1780     ret = VirtualProtect( mem, 0x2000, PAGE_NOACCESS, &old_prot );
1781     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1782
1783     ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
1784     ok( !ret, "WriteFile succeeded\n" );
1785     ok( GetLastError() == ERROR_INVALID_USER_BUFFER ||
1786         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1787         "wrong error %u\n", GetLastError() );
1788     ok( bytes == 0, "wrote %x bytes\n", bytes );
1789
1790     SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
1791
1792     ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
1793     ok( !ret, "ReadFile succeeded\n" );
1794     ok( GetLastError() == ERROR_NOACCESS ||
1795         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1796         "wrong error %u\n", GetLastError() );
1797     ok( bytes == 0, "read %x bytes\n", bytes );
1798
1799     ret = VirtualProtect( mem, 0x2000, PAGE_READONLY, &old_prot );
1800     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1801
1802     ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
1803     ok( !ret, "ReadFile succeeded\n" );
1804     ok( GetLastError() == ERROR_NOACCESS ||
1805         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1806         "wrong error %u\n", GetLastError() );
1807     ok( bytes == 0, "read %x bytes\n", bytes );
1808
1809     ret = VirtualProtect( mem, 0x2000, PAGE_READWRITE, &old_prot );
1810     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1811
1812     ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
1813     ok( !ret, "ReadFile succeeded\n" );
1814     ok( GetLastError() == ERROR_NOACCESS ||
1815         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1816         "wrong error %u\n", GetLastError() );
1817     ok( bytes == 0, "read %x bytes\n", bytes );
1818
1819     SetFilePointer( hFile, 0x1234, NULL, FILE_BEGIN );
1820     SetEndOfFile( hFile );
1821     SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
1822
1823     ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
1824     ok( !ret, "ReadFile succeeded\n" );
1825     ok( GetLastError() == ERROR_NOACCESS ||
1826         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1827         "wrong error %u\n", GetLastError() );
1828     ok( bytes == 0, "read %x bytes\n", bytes );
1829
1830     ret = ReadFile( hFile, mem, 0x2000, &bytes, NULL );
1831     ok( ret, "ReadFile failed error %u\n", GetLastError() );
1832     ok( bytes == 0x1234, "read %x bytes\n", bytes );
1833
1834     ret = ReadFile( hFile, NULL, 1, &bytes, NULL );
1835     ok( !ret, "ReadFile succeeded\n" );
1836     ok( GetLastError() == ERROR_NOACCESS ||
1837         GetLastError() == ERROR_INVALID_PARAMETER,  /* win9x */
1838         "wrong error %u\n", GetLastError() );
1839     ok( bytes == 0, "read %x bytes\n", bytes );
1840
1841     VirtualFree( mem, 0, MEM_FREE );
1842
1843     ret = CloseHandle(hFile);
1844     ok( ret, "CloseHandle: error %d\n", GetLastError());
1845     ret = DeleteFileA(filename);
1846     ok( ret, "DeleteFileA: error %d\n", GetLastError());
1847 }
1848
1849 static void test_OpenFile(void)
1850 {
1851     HFILE hFile;
1852     OFSTRUCT ofs;
1853     BOOL ret;
1854     DWORD retval;
1855     
1856     static const char file[] = "regedit.exe";
1857     static const char foo[] = ".\\foo-bar-foo.baz";
1858     static const char *foo_too_long = ".\\foo-bar-foo.baz+++++++++++++++"
1859         "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
1860         "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
1861         "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
1862         "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
1863         "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
1864     char buff[MAX_PATH];
1865     char buff_long[4*MAX_PATH];
1866     char filled_0xA5[OFS_MAXPATHNAME];
1867     char *p;
1868     UINT length;
1869     
1870     /* Check for existing file */
1871     if (!pGetSystemWindowsDirectoryA)
1872         length = GetWindowsDirectoryA(buff, MAX_PATH);
1873     else
1874         length = pGetSystemWindowsDirectoryA(buff, MAX_PATH);
1875
1876     if (length + sizeof(file) < MAX_PATH)
1877     {
1878         p = buff + strlen(buff);
1879         if (p > buff && p[-1] != '\\') *p++ = '\\';
1880         strcpy( p, file );
1881         memset(&ofs, 0xA5, sizeof(ofs));
1882         SetLastError(0xfaceabee);
1883
1884         hFile = OpenFile(buff, &ofs, OF_EXIST);
1885         ok( hFile == TRUE, "%s not found : %d\n", buff, GetLastError() );
1886         ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 
1887             "GetLastError() returns %d\n", GetLastError() );
1888         ok( ofs.cBytes == sizeof(ofs), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
1889         ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
1890         ok( lstrcmpiA(ofs.szPathName, buff) == 0,
1891             "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n",
1892             ofs.szPathName, buff );
1893     }
1894
1895     memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
1896     length = GetCurrentDirectoryA(MAX_PATH, buff);
1897
1898     /* Check for nonexistent file */
1899     if (length + sizeof(foo) < MAX_PATH)
1900     {
1901         p = buff + strlen(buff);
1902         if (p > buff && p[-1] != '\\') *p++ = '\\';
1903         strcpy( p, foo + 2 );
1904         memset(&ofs, 0xA5, sizeof(ofs));
1905         SetLastError(0xfaceabee);
1906
1907         hFile = OpenFile(foo, &ofs, OF_EXIST);
1908         ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
1909         ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError() returns %d\n", GetLastError() );
1910         todo_wine
1911         ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
1912         ok( ofs.nErrCode == ERROR_FILE_NOT_FOUND, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
1913         ok( lstrcmpiA(ofs.szPathName, buff) == 0 || strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
1914             "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n", 
1915             ofs.szPathName, buff );
1916     }
1917
1918     length = GetCurrentDirectoryA(MAX_PATH, buff_long);
1919     length += lstrlenA(foo_too_long + 1);
1920
1921     /* Check for nonexistent file with too long filename */ 
1922     if (length >= OFS_MAXPATHNAME && length < sizeof(buff_long)) 
1923     {
1924         lstrcatA(buff_long, foo_too_long + 1); /* Avoid '.' during concatenation */
1925         memset(&ofs, 0xA5, sizeof(ofs));
1926         SetLastError(0xfaceabee);
1927
1928         hFile = OpenFile(foo_too_long, &ofs, OF_EXIST);
1929         ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
1930         ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_FILENAME_EXCED_RANGE, 
1931             "GetLastError() returns %d\n", GetLastError() );
1932         todo_wine
1933         ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
1934         ok( ofs.nErrCode == ERROR_INVALID_DATA || ofs.nErrCode == ERROR_FILENAME_EXCED_RANGE,
1935             "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
1936         ok( strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, 
1937             "OpenFile returned '%s', but was expected to return string filled with 0xA5\n", 
1938             ofs.szPathName );
1939     }
1940
1941     length = GetCurrentDirectoryA(MAX_PATH, buff) + sizeof(filename);
1942
1943     if (length >= MAX_PATH) 
1944     {
1945         trace("Buffer too small, requested length = %d, but MAX_PATH = %d.  Skipping test.\n", length, MAX_PATH);
1946         return;
1947     }
1948     p = buff + strlen(buff);
1949     if (p > buff && p[-1] != '\\') *p++ = '\\';
1950     strcpy( p, filename );
1951
1952     memset(&ofs, 0xA5, sizeof(ofs));
1953     SetLastError(0xfaceabee);
1954     /* Create an empty file */
1955     hFile = OpenFile(filename, &ofs, OF_CREATE);
1956     ok( hFile != HFILE_ERROR, "OpenFile failed to create nonexistent file\n" );
1957     ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 
1958         "GetLastError() returns %d\n", GetLastError() );
1959     ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
1960     ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
1961         "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
1962     ret = _lclose(hFile);
1963     ok( !ret, "_lclose() returns %d\n", ret );
1964     retval = GetFileAttributesA(filename);
1965     ok( retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %d\n", GetLastError() );
1966
1967     memset(&ofs, 0xA5, sizeof(ofs));
1968     SetLastError(0xfaceabee);
1969     /* Check various opening options: */
1970     /* for reading only, */
1971     hFile = OpenFile(filename, &ofs, OF_READ);
1972     ok( hFile != HFILE_ERROR, "OpenFile failed on read\n" );
1973     ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 
1974         "GetLastError() returns %d\n", GetLastError() );
1975     ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
1976     ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
1977         "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
1978     ok( lstrcmpiA(ofs.szPathName, buff) == 0,
1979         "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
1980     ret = _lclose(hFile);
1981     ok( !ret, "_lclose() returns %d\n", ret );
1982
1983     memset(&ofs, 0xA5, sizeof(ofs));
1984     SetLastError(0xfaceabee);
1985     /* for writing only, */
1986     hFile = OpenFile(filename, &ofs, OF_WRITE);
1987     ok( hFile != HFILE_ERROR, "OpenFile failed on write\n" );
1988     ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 
1989         "GetLastError() returns %d\n", GetLastError() );
1990     ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
1991     ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
1992         "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
1993     ok( lstrcmpiA(ofs.szPathName, buff) == 0,
1994         "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
1995     ret = _lclose(hFile);
1996     ok( !ret, "_lclose() returns %d\n", ret );
1997
1998     memset(&ofs, 0xA5, sizeof(ofs));
1999     SetLastError(0xfaceabee);
2000     /* for reading and writing, */
2001     hFile = OpenFile(filename, &ofs, OF_READWRITE);
2002     ok( hFile != HFILE_ERROR, "OpenFile failed on read/write\n" );
2003     ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 
2004         "GetLastError() returns %d\n", GetLastError() );
2005     ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
2006     ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
2007         "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
2008     ok( lstrcmpiA(ofs.szPathName, buff) == 0,
2009         "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
2010     ret = _lclose(hFile);
2011     ok( !ret, "_lclose() returns %d\n", ret );
2012
2013     memset(&ofs, 0xA5, sizeof(ofs));
2014     SetLastError(0xfaceabee);
2015     /* for checking file presence. */
2016     hFile = OpenFile(filename, &ofs, OF_EXIST);
2017     ok( hFile == 1, "OpenFile failed on finding our created file\n" );
2018     ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 
2019         "GetLastError() returns %d\n", GetLastError() );
2020     ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
2021     ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
2022         "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
2023     ok( lstrcmpiA(ofs.szPathName, buff) == 0,
2024         "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
2025
2026     memset(&ofs, 0xA5, sizeof(ofs));
2027     SetLastError(0xfaceabee);
2028     /* Delete the file and make sure it doesn't exist anymore */
2029     hFile = OpenFile(filename, &ofs, OF_DELETE);
2030     ok( hFile == 1, "OpenFile failed on delete (%d)\n", hFile );
2031     ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 
2032         "GetLastError() returns %d\n", GetLastError() );
2033     ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
2034     ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
2035         "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
2036     ok( lstrcmpiA(ofs.szPathName, buff) == 0,
2037         "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
2038
2039     retval = GetFileAttributesA(filename);
2040     ok( retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file\n" );
2041 }
2042
2043 static void test_overlapped(void)
2044 {
2045     OVERLAPPED ov;
2046     DWORD r, result;
2047
2048     /* GetOverlappedResult crashes if the 2nd or 3rd param are NULL */
2049     if (0) /* tested: WinXP */
2050     {
2051         GetOverlappedResult(0, NULL, &result, FALSE);
2052         GetOverlappedResult(0, &ov, NULL, FALSE);
2053         GetOverlappedResult(0, NULL, NULL, FALSE);
2054     }
2055
2056     memset( &ov, 0,  sizeof ov );
2057     result = 1;
2058     r = GetOverlappedResult(0, &ov, &result, 0);
2059     if (r)
2060         ok( result == 0, "wrong result %u\n", result );
2061     else  /* win9x */
2062         ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
2063
2064     result = 0;
2065     ov.Internal = 0;
2066     ov.InternalHigh = 0xabcd;
2067     r = GetOverlappedResult(0, &ov, &result, 0);
2068     if (r)
2069         ok( result == 0xabcd, "wrong result %u\n", result );
2070     else  /* win9x */
2071         ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
2072
2073     SetLastError( 0xb00 );
2074     result = 0;
2075     ov.Internal = STATUS_INVALID_HANDLE;
2076     ov.InternalHigh = 0xabcd;
2077     r = GetOverlappedResult(0, &ov, &result, 0);
2078     ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
2079     ok( r == FALSE, "should return false\n");
2080     ok( result == 0xabcd || result == 0 /* win9x */, "wrong result %u\n", result );
2081
2082     SetLastError( 0xb00 );
2083     result = 0;
2084     ov.Internal = STATUS_PENDING;
2085     ov.InternalHigh = 0xabcd;
2086     r = GetOverlappedResult(0, &ov, &result, 0);
2087     ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
2088         "wrong error %u\n", GetLastError() );
2089     ok( r == FALSE, "should return false\n");
2090     ok( result == 0, "wrong result %u\n", result );
2091
2092     SetLastError( 0xb00 );
2093     ov.hEvent = CreateEvent( NULL, 1, 1, NULL );
2094     ov.Internal = STATUS_PENDING;
2095     ov.InternalHigh = 0xabcd;
2096     r = GetOverlappedResult(0, &ov, &result, 0);
2097     ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
2098         "wrong error %u\n", GetLastError() );
2099     ok( r == FALSE, "should return false\n");
2100
2101     ResetEvent( ov.hEvent );
2102
2103     SetLastError( 0xb00 );
2104     ov.Internal = STATUS_PENDING;
2105     ov.InternalHigh = 0;
2106     r = GetOverlappedResult(0, &ov, &result, 0);
2107     ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
2108         "wrong error %u\n", GetLastError() );
2109     ok( r == FALSE, "should return false\n");
2110
2111     r = CloseHandle( ov.hEvent );
2112     ok( r == TRUE, "close handle failed\n");
2113 }
2114
2115 static void test_RemoveDirectory(void)
2116 {
2117     int rc;
2118     char directory[] = "removeme";
2119
2120     rc = CreateDirectory(directory, NULL);
2121     ok( rc, "Createdirectory failed, gle=%d\n", GetLastError() );
2122
2123     rc = SetCurrentDirectory(directory);
2124     ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
2125
2126     rc = RemoveDirectory(".");
2127     if (!rc)
2128     {
2129         rc = SetCurrentDirectory("..");
2130         ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
2131
2132         rc = RemoveDirectory(directory);
2133         ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
2134     }
2135 }
2136
2137 static BOOL check_file_time( const FILETIME *ft1, const FILETIME *ft2, UINT tolerance )
2138 {
2139     ULONGLONG t1 = ((ULONGLONG)ft1->dwHighDateTime << 32) | ft1->dwLowDateTime;
2140     ULONGLONG t2 = ((ULONGLONG)ft2->dwHighDateTime << 32) | ft2->dwLowDateTime;
2141     return abs(t1 - t2) <= tolerance;
2142 }
2143
2144 static void test_ReplaceFileA(void)
2145 {
2146     char replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
2147     HANDLE hReplacedFile, hReplacementFile, hBackupFile;
2148     static const char replacedData[] = "file-to-replace";
2149     static const char replacementData[] = "new-file";
2150     static const char backupData[] = "backup-file";
2151     FILETIME ftReplaced, ftReplacement, ftBackup;
2152     static const char prefix[] = "pfx";
2153     char temp_path[MAX_PATH];
2154     DWORD ret;
2155     BOOL retok, removeBackup = FALSE;
2156
2157     if (!pReplaceFileA)
2158     {
2159         win_skip("ReplaceFileA() is missing\n");
2160         return;
2161     }
2162
2163     ret = GetTempPathA(MAX_PATH, temp_path);
2164     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
2165     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
2166
2167     ret = GetTempFileNameA(temp_path, prefix, 0, replaced);
2168     ok(ret != 0, "GetTempFileNameA error (replaced) %d\n", GetLastError());
2169
2170     ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
2171     ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
2172
2173     ret = GetTempFileNameA(temp_path, prefix, 0, backup);
2174     ok(ret != 0, "GetTempFileNameA error (backup) %d\n", GetLastError());
2175
2176     /* place predictable data in the file to be replaced */
2177     hReplacedFile = CreateFileA(replaced, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
2178     ok(hReplacedFile != INVALID_HANDLE_VALUE,
2179         "failed to open replaced file\n");
2180     retok = WriteFile(hReplacedFile, replacedData, sizeof(replacedData), &ret, NULL );
2181     ok( retok && ret == sizeof(replacedData),
2182        "WriteFile error (replaced) %d\n", GetLastError());
2183     ok(GetFileSize(hReplacedFile, NULL) == sizeof(replacedData),
2184         "replaced file has wrong size\n");
2185     /* place predictable data in the file to be the replacement */
2186     hReplacementFile = CreateFileA(replacement, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
2187     ok(hReplacementFile != INVALID_HANDLE_VALUE,
2188         "failed to open replacement file\n");
2189     retok = WriteFile(hReplacementFile, replacementData, sizeof(replacementData), &ret, NULL );
2190     ok( retok && ret == sizeof(replacementData),
2191        "WriteFile error (replacement) %d\n", GetLastError());
2192     ok(GetFileSize(hReplacementFile, NULL) == sizeof(replacementData),
2193         "replacement file has wrong size\n");
2194     /* place predictable data in the backup file (to be over-written) */
2195     hBackupFile = CreateFileA(backup, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
2196     ok(hBackupFile != INVALID_HANDLE_VALUE,
2197         "failed to open backup file\n");
2198     retok = WriteFile(hBackupFile, backupData, sizeof(backupData), &ret, NULL );
2199     ok( retok && ret == sizeof(backupData),
2200        "WriteFile error (replacement) %d\n", GetLastError());
2201     ok(GetFileSize(hBackupFile, NULL) == sizeof(backupData),
2202         "backup file has wrong size\n");
2203     /* change the filetime on the "replaced" file to ensure that it changes */
2204     ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
2205     ok( ret, "GetFileTime error (replaced) %d\n", GetLastError());
2206     ftReplaced.dwLowDateTime -= 600000000; /* 60 second */
2207     ret = SetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
2208     ok( ret, "SetFileTime error (replaced) %d\n", GetLastError());
2209     GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);  /* get the actual time back */
2210     CloseHandle(hReplacedFile);
2211     /* change the filetime on the backup to ensure that it changes */
2212     ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
2213     ok( ret, "GetFileTime error (backup) %d\n", GetLastError());
2214     ftBackup.dwLowDateTime -= 1200000000; /* 120 second */
2215     ret = SetFileTime(hBackupFile, NULL, NULL, &ftBackup);
2216     ok( ret, "SetFileTime error (backup) %d\n", GetLastError());
2217     GetFileTime(hBackupFile, NULL, NULL, &ftBackup);  /* get the actual time back */
2218     CloseHandle(hBackupFile);
2219     /* get the filetime on the replacement file to perform checks */
2220     ret = GetFileTime(hReplacementFile, NULL, NULL, &ftReplacement);
2221     ok( ret, "GetFileTime error (replacement) %d\n", GetLastError());
2222     CloseHandle(hReplacementFile);
2223
2224     /* perform replacement w/ backup
2225      * TODO: flags are not implemented
2226      */
2227     SetLastError(0xdeadbeef);
2228     ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
2229     ok(ret, "ReplaceFileA: unexpected error %d\n", GetLastError());
2230     /* make sure that the backup has the size of the old "replaced" file */
2231     hBackupFile = CreateFileA(backup, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2232     ok(hBackupFile != INVALID_HANDLE_VALUE,
2233         "failed to open backup file\n");
2234     ret = GetFileSize(hBackupFile, NULL);
2235     ok(ret == sizeof(replacedData),
2236         "backup file has wrong size %d\n", ret);
2237     /* make sure that the "replaced" file has the size of the replacement file */
2238     hReplacedFile = CreateFileA(replaced, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2239     ok(hReplacedFile != INVALID_HANDLE_VALUE,
2240         "failed to open replaced file: %d\n", GetLastError());
2241     if (hReplacedFile != INVALID_HANDLE_VALUE)
2242     {
2243         ret = GetFileSize(hReplacedFile, NULL);
2244         ok(ret == sizeof(replacementData),
2245             "replaced file has wrong size %d\n", ret);
2246         /* make sure that the replacement file no-longer exists */
2247         hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2248         ok(hReplacementFile == INVALID_HANDLE_VALUE,
2249            "unexpected error, replacement file should not exist %d\n", GetLastError());
2250         /* make sure that the backup has the old "replaced" filetime */
2251         ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
2252         ok( ret, "GetFileTime error (backup %d\n", GetLastError());
2253         ok(check_file_time(&ftBackup, &ftReplaced, 20000000), "backup file has wrong filetime\n");
2254         CloseHandle(hBackupFile);
2255         /* make sure that the "replaced" has the old replacement filetime */
2256         ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
2257         ok( ret, "GetFileTime error (backup %d\n", GetLastError());
2258         ok(check_file_time(&ftReplaced, &ftReplacement, 20000000),
2259            "replaced file has wrong filetime %x%08x / %x%08x\n",
2260            ftReplaced.dwHighDateTime, ftReplaced.dwLowDateTime,
2261            ftReplacement.dwHighDateTime, ftReplacement.dwLowDateTime );
2262         CloseHandle(hReplacedFile);
2263     }
2264     else
2265         skip("couldn't open replacement file, skipping tests\n");
2266
2267     /* re-create replacement file for pass w/o backup (blank) */
2268     ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
2269     ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
2270     /* perform replacement w/o backup
2271      * TODO: flags are not implemented
2272      */
2273     SetLastError(0xdeadbeef);
2274     ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
2275     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2276        "ReplaceFileA: unexpected error %d\n", GetLastError());
2277
2278     /* re-create replacement file for pass w/ backup (backup-file not existing) */
2279     ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
2280     ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
2281     ret = DeleteFileA(backup);
2282     ok(ret, "DeleteFileA: error (backup) %d\n", GetLastError());
2283     /* perform replacement w/ backup (no pre-existing backup)
2284      * TODO: flags are not implemented
2285      */
2286     SetLastError(0xdeadbeef);
2287     ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
2288     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2289        "ReplaceFileA: unexpected error %d\n", GetLastError());
2290     if (ret)
2291         removeBackup = TRUE;
2292
2293     /* re-create replacement file for pass w/ no permissions to "replaced" */
2294     ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
2295     ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
2296     ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_READONLY);
2297     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2298        "SetFileAttributesA: error setting to read only %d\n", GetLastError());
2299     /* perform replacement w/ backup (no permission to "replaced")
2300      * TODO: flags are not implemented
2301      */
2302     SetLastError(0xdeadbeef);
2303     ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
2304     ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED, "ReplaceFileA: unexpected error %d\n", GetLastError());
2305     /* make sure that the replacement file still exists */
2306     hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2307     ok(hReplacementFile != INVALID_HANDLE_VALUE ||
2308        broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* win2k */
2309        "unexpected error, replacement file should still exist %d\n", GetLastError());
2310     CloseHandle(hReplacementFile);
2311     ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_NORMAL);
2312     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2313        "SetFileAttributesA: error setting to normal %d\n", GetLastError());
2314
2315     /* replacement file still exists, make pass w/o "replaced" */
2316     ret = DeleteFileA(replaced);
2317     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2318        "DeleteFileA: error (replaced) %d\n", GetLastError());
2319     /* perform replacement w/ backup (no pre-existing backup or "replaced")
2320      * TODO: flags are not implemented
2321      */
2322     SetLastError(0xdeadbeef);
2323     ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
2324     ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
2325        GetLastError() == ERROR_ACCESS_DENIED),
2326        "ReplaceFileA: unexpected error %d\n", GetLastError());
2327
2328     /* perform replacement w/o existing "replacement" file
2329      * TODO: flags are not implemented
2330      */
2331     SetLastError(0xdeadbeef);
2332     ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
2333     ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
2334         GetLastError() == ERROR_ACCESS_DENIED),
2335         "ReplaceFileA: unexpected error %d\n", GetLastError());
2336
2337     /*
2338      * if the first round (w/ backup) worked then as long as there is no
2339      * failure then there is no need to check this round (w/ backup is the
2340      * more complete case)
2341      */
2342
2343     /* delete temporary files, replacement and replaced are already deleted */
2344     if (removeBackup)
2345     {
2346         ret = DeleteFileA(backup);
2347         ok(ret ||
2348            broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
2349            "DeleteFileA: error (backup) %d\n", GetLastError());
2350     }
2351 }
2352
2353 /*
2354  * ReplaceFileW is a simpler case of ReplaceFileA, there is no
2355  * need to be as thorough.
2356  */
2357 static void test_ReplaceFileW(void)
2358 {
2359     WCHAR replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
2360     static const WCHAR prefix[] = {'p','f','x',0};
2361     WCHAR temp_path[MAX_PATH];
2362     DWORD ret;
2363     BOOL removeBackup = FALSE;
2364
2365     if (!pReplaceFileW)
2366     {
2367         win_skip("ReplaceFileW() is missing\n");
2368         return;
2369     }
2370
2371     ret = GetTempPathW(MAX_PATH, temp_path);
2372     if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2373     {
2374         win_skip("GetTempPathW is not available\n");
2375         return;
2376     }
2377     ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
2378     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
2379
2380     ret = GetTempFileNameW(temp_path, prefix, 0, replaced);
2381     ok(ret != 0, "GetTempFileNameW error (replaced) %d\n", GetLastError());
2382
2383     ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
2384     ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
2385
2386     ret = GetTempFileNameW(temp_path, prefix, 0, backup);
2387     ok(ret != 0, "GetTempFileNameW error (backup) %d\n", GetLastError());
2388
2389     ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
2390     ok(ret, "ReplaceFileW: error %d\n", GetLastError());
2391
2392     ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
2393     ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
2394     ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0);
2395     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2396        "ReplaceFileW: error %d\n", GetLastError());
2397
2398     ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
2399     ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
2400     ret = DeleteFileW(backup);
2401     ok(ret, "DeleteFileW: error (backup) %d\n", GetLastError());
2402     ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
2403     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2404        "ReplaceFileW: error %d\n", GetLastError());
2405
2406     ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
2407     ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
2408     ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_READONLY);
2409     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2410        "SetFileAttributesW: error setting to read only %d\n", GetLastError());
2411
2412     ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
2413     ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED,
2414         "ReplaceFileW: unexpected error %d\n", GetLastError());
2415     ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_NORMAL);
2416     ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
2417        "SetFileAttributesW: error setting to normal %d\n", GetLastError());
2418     if (ret)
2419         removeBackup = TRUE;
2420
2421     ret = DeleteFileW(replaced);
2422     ok(ret, "DeleteFileW: error (replaced) %d\n", GetLastError());
2423     ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
2424     ok(!ret, "ReplaceFileW: error %d\n", GetLastError());
2425
2426     ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0);
2427     ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
2428        GetLastError() == ERROR_ACCESS_DENIED),
2429         "ReplaceFileW: unexpected error %d\n", GetLastError());
2430
2431     if (removeBackup)
2432     {
2433         ret = DeleteFileW(backup);
2434         ok(ret ||
2435            broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
2436            "DeleteFileW: error (backup) %d\n", GetLastError());
2437     }
2438 }
2439
2440 START_TEST(file)
2441 {
2442     InitFunctionPointers();
2443
2444     test__hread(  );
2445     test__hwrite(  );
2446     test__lclose(  );
2447     test__lcreat(  );
2448     test__llseek(  );
2449     test__llopen(  );
2450     test__lread(  );
2451     test__lwrite(  );
2452     test_GetTempFileNameA();
2453     test_CopyFileA();
2454     test_CopyFileW();
2455     test_CreateFileA();
2456     test_CreateFileW();
2457     test_DeleteFileA();
2458     test_DeleteFileW();
2459     test_MoveFileA();
2460     test_MoveFileW();
2461     test_FindFirstFileA();
2462     test_FindNextFileA();
2463     test_FindFirstFileExA();
2464     test_LockFile();
2465     test_file_sharing();
2466     test_offset_in_overlapped_structure();
2467     test_MapFile();
2468     test_GetFileType();
2469     test_async_file_errors();
2470     test_read_write();
2471     test_OpenFile();
2472     test_overlapped();
2473     test_RemoveDirectory();
2474     test_ReplaceFileA();
2475     test_ReplaceFileW();
2476 }