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