ntdll: Add support for FILE_APPEND_DATA to NtWriteFile.
[wine.git] / dlls / kernel32 / tests / file.c
blob866a29a3f04c724bf9cb3279c6a8c1107944b012
1 /*
2 * Unit tests for file functions in Wine
4 * Copyright (c) 2002, 2004 Jakob Eriksson
5 * Copyright (c) 2008 Jeff Zaroyko
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.
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.
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
23 /* ReplaceFile requires Windows 2000 or newer */
24 #define _WIN32_WINNT 0x0500
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include <stdio.h>
31 #include "wine/test.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winerror.h"
35 #include "winnls.h"
36 #include "fileapi.h"
38 static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD);
39 static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID);
40 static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID);
41 static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT);
42 static BOOL (WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
43 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
44 static BOOL (WINAPI *pGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD);
45 static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD);
46 static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
47 static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*);
48 static HANDLE (WINAPI *pCreateFile2)(LPCWSTR, DWORD, DWORD, DWORD, CREATEFILE2_EXTENDED_PARAMETERS*);
50 /* keep filename and filenameW the same */
51 static const char filename[] = "testfile.xxx";
52 static const WCHAR filenameW[] = { 't','e','s','t','f','i','l','e','.','x','x','x',0 };
53 static const char sillytext[] =
54 "en larvig liten text dx \033 gx hej 84 hej 4484 ! \001\033 bla bl\na.. bla bla."
55 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
56 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
57 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
58 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
59 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
60 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
61 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
62 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
63 "sdlkfjasdlkfj a dslkj adsklf \n \nasdklf askldfa sdlkf \nsadklf asdklf asdf ";
65 struct test_list {
66 const char *file; /* file string to test */
67 const DWORD err; /* Win NT and further error code */
68 const LONG err2; /* Win 9x & ME error code or -1 */
69 const DWORD options; /* option flag to use for open */
70 const BOOL todo_flag; /* todo_wine indicator */
71 } ;
73 static void InitFunctionPointers(void)
75 HMODULE hkernel32 = GetModuleHandleA("kernel32");
77 pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA");
78 pReplaceFileA=(void*)GetProcAddress(hkernel32, "ReplaceFileA");
79 pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW");
80 pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA");
81 pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hkernel32, "GetVolumeNameForVolumeMountPointA");
82 pQueueUserAPC = (void *) GetProcAddress(hkernel32, "QueueUserAPC");
83 pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx");
84 pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById");
85 pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
86 pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2");
87 pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2");
90 static void test__hread( void )
92 HFILE filehandle;
93 char buffer[10000];
94 LONG bytes_read;
95 LONG bytes_wanted;
96 LONG i;
97 BOOL ret;
99 SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL); /* be sure to remove stale files */
100 DeleteFileA( filename );
101 filehandle = _lcreat( filename, 0 );
102 if (filehandle == HFILE_ERROR)
104 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
105 return;
108 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
110 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
112 filehandle = _lopen( filename, OF_READ );
114 ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError( ) );
116 bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
118 ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
120 for (bytes_wanted = 0; bytes_wanted < lstrlenA( sillytext ); bytes_wanted++)
122 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
123 ok( _hread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
124 for (i = 0; i < bytes_wanted; i++)
126 ok( buffer[i] == sillytext[i], "that's not what's written\n" );
130 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
132 ret = DeleteFileA( filename );
133 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
137 static void test__hwrite( void )
139 HFILE filehandle;
140 char buffer[10000];
141 LONG bytes_read;
142 LONG bytes_written;
143 ULONG blocks;
144 LONG i;
145 char *contents;
146 HLOCAL memory_object;
147 char checksum[1];
148 BOOL ret;
150 filehandle = _lcreat( filename, 0 );
151 if (filehandle == HFILE_ERROR)
153 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
154 return;
157 ok( HFILE_ERROR != _hwrite( filehandle, "", 0 ), "_hwrite complains\n" );
159 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
161 filehandle = _lopen( filename, OF_READ );
163 bytes_read = _hread( filehandle, buffer, 1);
165 ok( 0 == bytes_read, "file read size error\n" );
167 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
169 filehandle = _lopen( filename, OF_READWRITE );
171 bytes_written = 0;
172 checksum[0] = '\0';
173 srand( (unsigned)time( NULL ) );
174 for (blocks = 0; blocks < 100; blocks++)
176 for (i = 0; i < (LONG)sizeof( buffer ); i++)
178 buffer[i] = rand( );
179 checksum[0] = checksum[0] + buffer[i];
181 ok( HFILE_ERROR != _hwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
182 bytes_written = bytes_written + sizeof( buffer );
185 ok( HFILE_ERROR != _hwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
186 bytes_written++;
188 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
190 memory_object = LocalAlloc( LPTR, bytes_written );
192 ok( 0 != memory_object, "LocalAlloc fails. (Could be out of memory.)\n" );
194 contents = LocalLock( memory_object );
195 ok( NULL != contents, "LocalLock whines\n" );
197 filehandle = _lopen( filename, OF_READ );
199 contents = LocalLock( memory_object );
200 ok( NULL != contents, "LocalLock whines\n" );
202 ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
204 checksum[0] = '\0';
205 i = 0;
208 checksum[0] = checksum[0] + contents[i];
209 i++;
211 while (i < bytes_written - 1);
213 ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
215 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
217 ret = DeleteFileA( filename );
218 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
220 LocalFree( contents );
224 static void test__lclose( void )
226 HFILE filehandle;
227 BOOL ret;
229 filehandle = _lcreat( filename, 0 );
230 if (filehandle == HFILE_ERROR)
232 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
233 return;
236 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
238 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
240 ret = DeleteFileA( filename );
241 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
245 static void test__lcreat( void )
247 HFILE filehandle;
248 char buffer[10000];
249 WIN32_FIND_DATAA search_results;
250 char slashname[] = "testfi/";
251 int err;
252 HANDLE find;
253 BOOL ret;
255 filehandle = _lcreat( filename, 0 );
256 if (filehandle == HFILE_ERROR)
258 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
259 return;
262 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
264 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
266 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
268 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
270 find = FindFirstFileA( filename, &search_results );
271 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
272 FindClose( find );
274 ret = DeleteFileA(filename);
275 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError());
277 filehandle = _lcreat( filename, 1 ); /* readonly */
278 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
280 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write never the less\n" );
282 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
284 find = FindFirstFileA( filename, &search_results );
285 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
286 FindClose( find );
288 ok( 0 == DeleteFileA( filename ), "shouldn't be able to delete a readonly file\n" );
290 ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
292 ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file!\n" );
294 filehandle = _lcreat( filename, 2 );
295 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
297 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
299 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
301 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
303 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
305 find = FindFirstFileA( filename, &search_results );
306 ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" );
307 FindClose( find );
309 ret = DeleteFileA( filename );
310 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
312 filehandle = _lcreat( filename, 4 ); /* SYSTEM file */
313 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
315 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
317 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
319 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
321 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
323 find = FindFirstFileA( filename, &search_results );
324 ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" );
325 FindClose( find );
327 ret = DeleteFileA( filename );
328 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
330 filehandle=_lcreat (slashname, 0); /* illegal name */
331 if (HFILE_ERROR==filehandle) {
332 err=GetLastError ();
333 ok (err==ERROR_INVALID_NAME || err==ERROR_PATH_NOT_FOUND,
334 "creating file \"%s\" failed with error %d\n", slashname, err);
335 } else { /* only NT succeeds */
336 _lclose(filehandle);
337 find=FindFirstFileA (slashname, &search_results);
338 if (INVALID_HANDLE_VALUE!=find)
340 ret = FindClose (find);
341 ok (0 != ret, "FindClose complains (%d)\n", GetLastError ());
342 slashname[strlen(slashname)-1]=0;
343 ok (!strcmp (slashname, search_results.cFileName),
344 "found unexpected name \"%s\"\n", search_results.cFileName);
345 ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
346 "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
347 search_results.dwFileAttributes);
349 ret = DeleteFileA( slashname );
350 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
353 filehandle=_lcreat (filename, 8); /* illegal attribute */
354 if (HFILE_ERROR==filehandle)
355 ok (0, "couldn't create volume label \"%s\"\n", filename);
356 else {
357 _lclose(filehandle);
358 find=FindFirstFileA (filename, &search_results);
359 if (INVALID_HANDLE_VALUE==find)
360 ok (0, "file \"%s\" not found\n", filename);
361 else {
362 ret = FindClose(find);
363 ok ( 0 != ret, "FindClose complains (%d)\n", GetLastError ());
364 ok (!strcmp (filename, search_results.cFileName),
365 "found unexpected name \"%s\"\n", search_results.cFileName);
366 search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
367 ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
368 "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
369 search_results.dwFileAttributes);
371 ret = DeleteFileA( filename );
372 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
377 static void test__llseek( void )
379 INT i;
380 HFILE filehandle;
381 char buffer[1];
382 LONG bytes_read;
383 BOOL ret;
385 filehandle = _lcreat( filename, 0 );
386 if (filehandle == HFILE_ERROR)
388 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
389 return;
392 for (i = 0; i < 400; i++)
394 ok( _hwrite( filehandle, sillytext, strlen( sillytext ) ) != -1, "_hwrite complains\n" );
396 ok( _llseek( filehandle, 400 * strlen( sillytext ), FILE_CURRENT ) != -1, "should be able to seek\n" );
397 ok( _llseek( filehandle, 27 + 35 * strlen( sillytext ), FILE_BEGIN ) != -1, "should be able to seek\n" );
399 bytes_read = _hread( filehandle, buffer, 1);
400 ok( 1 == bytes_read, "file read size error\n" );
401 ok( buffer[0] == sillytext[27], "_llseek error, it got lost seeking\n" );
402 ok( _llseek( filehandle, -400 * (LONG)strlen( sillytext ), FILE_END ) != -1, "should be able to seek\n" );
404 bytes_read = _hread( filehandle, buffer, 1);
405 ok( 1 == bytes_read, "file read size error\n" );
406 ok( buffer[0] == sillytext[0], "_llseek error, it got lost seeking\n" );
407 ok( _llseek( filehandle, 1000000, FILE_END ) != -1, "should be able to seek past file; poor, poor Windows programmers\n" );
408 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
410 ret = DeleteFileA( filename );
411 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
415 static void test__llopen( void )
417 HFILE filehandle;
418 UINT bytes_read;
419 char buffer[10000];
420 BOOL ret;
422 filehandle = _lcreat( filename, 0 );
423 if (filehandle == HFILE_ERROR)
425 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
426 return;
429 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
430 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
432 filehandle = _lopen( filename, OF_READ );
433 ok( HFILE_ERROR == _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write!\n" );
434 bytes_read = _hread( filehandle, buffer, strlen( sillytext ) );
435 ok( strlen( sillytext ) == bytes_read, "file read size error\n" );
436 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
438 filehandle = _lopen( filename, OF_READWRITE );
439 bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
440 ok( strlen( sillytext ) == bytes_read, "file read size error\n" );
441 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
442 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
444 filehandle = _lopen( filename, OF_WRITE );
445 ok( HFILE_ERROR == _hread( filehandle, buffer, 1 ), "you should only be able to write this file\n" );
446 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
447 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
449 ret = DeleteFileA( filename );
450 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
451 /* TODO - add tests for the SHARE modes - use two processes to pull this one off */
455 static void test__lread( void )
457 HFILE filehandle;
458 char buffer[10000];
459 UINT bytes_read;
460 UINT bytes_wanted;
461 UINT i;
462 BOOL ret;
464 filehandle = _lcreat( filename, 0 );
465 if (filehandle == HFILE_ERROR)
467 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
468 return;
471 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
473 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
475 filehandle = _lopen( filename, OF_READ );
477 ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError());
479 bytes_read = _lread( filehandle, buffer, 2 * strlen( sillytext ) );
481 ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
483 for (bytes_wanted = 0; bytes_wanted < strlen( sillytext ); bytes_wanted++)
485 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
486 ok( _lread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
487 for (i = 0; i < bytes_wanted; i++)
489 ok( buffer[i] == sillytext[i], "that's not what's written\n" );
493 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
495 ret = DeleteFileA( filename );
496 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
500 static void test__lwrite( void )
502 HFILE filehandle;
503 char buffer[10000];
504 UINT bytes_read;
505 UINT bytes_written;
506 UINT blocks;
507 INT i;
508 char *contents;
509 HLOCAL memory_object;
510 char checksum[1];
511 BOOL ret;
513 filehandle = _lcreat( filename, 0 );
514 if (filehandle == HFILE_ERROR)
516 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
517 return;
520 ok( HFILE_ERROR != _lwrite( filehandle, "", 0 ), "_hwrite complains\n" );
522 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
524 filehandle = _lopen( filename, OF_READ );
526 bytes_read = _hread( filehandle, buffer, 1);
528 ok( 0 == bytes_read, "file read size error\n" );
530 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
532 filehandle = _lopen( filename, OF_READWRITE );
534 bytes_written = 0;
535 checksum[0] = '\0';
536 srand( (unsigned)time( NULL ) );
537 for (blocks = 0; blocks < 100; blocks++)
539 for (i = 0; i < (INT)sizeof( buffer ); i++)
541 buffer[i] = rand( );
542 checksum[0] = checksum[0] + buffer[i];
544 ok( HFILE_ERROR != _lwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
545 bytes_written = bytes_written + sizeof( buffer );
548 ok( HFILE_ERROR != _lwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
549 bytes_written++;
551 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
553 memory_object = LocalAlloc( LPTR, bytes_written );
555 ok( 0 != memory_object, "LocalAlloc fails, could be out of memory\n" );
557 contents = LocalLock( memory_object );
558 ok( NULL != contents, "LocalLock whines\n" );
560 filehandle = _lopen( filename, OF_READ );
562 contents = LocalLock( memory_object );
563 ok( NULL != contents, "LocalLock whines\n" );
565 ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
567 checksum[0] = '\0';
568 i = 0;
571 checksum[0] += contents[i];
572 i++;
574 while (i < bytes_written - 1);
576 ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
578 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
580 ret = DeleteFileA( filename );
581 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
583 LocalFree( contents );
586 static void test_CopyFileA(void)
588 char temp_path[MAX_PATH];
589 char source[MAX_PATH], dest[MAX_PATH];
590 static const char prefix[] = "pfx";
591 HANDLE hfile;
592 HANDLE hmapfile;
593 FILETIME ft1, ft2;
594 char buf[10];
595 DWORD ret;
596 BOOL retok;
598 ret = GetTempPathA(MAX_PATH, temp_path);
599 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
600 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
602 ret = GetTempFileNameA(temp_path, prefix, 0, source);
603 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
605 ret = MoveFileA(source, source);
606 todo_wine ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
608 /* copying a file to itself must fail */
609 retok = CopyFileA(source, source, FALSE);
610 ok( !retok && (GetLastError() == ERROR_SHARING_VIOLATION || broken(GetLastError() == ERROR_FILE_EXISTS) /* Win 9x */),
611 "copying a file to itself didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
613 /* make the source have not zero size */
614 hfile = CreateFileA(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
615 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
616 retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL );
617 ok( retok && ret == sizeof(prefix),
618 "WriteFile error %d\n", GetLastError());
619 ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
620 /* get the file time and change it to prove the difference */
621 ret = GetFileTime(hfile, NULL, NULL, &ft1);
622 ok( ret, "GetFileTime error %d\n", GetLastError());
623 ft1.dwLowDateTime -= 600000000; /* 60 second */
624 ret = SetFileTime(hfile, NULL, NULL, &ft1);
625 ok( ret, "SetFileTime error %d\n", GetLastError());
626 GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */
627 CloseHandle(hfile);
629 ret = GetTempFileNameA(temp_path, prefix, 0, dest);
630 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
632 SetLastError(0xdeadbeef);
633 ret = CopyFileA(source, dest, TRUE);
634 ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
635 "CopyFileA: unexpected error %d\n", GetLastError());
637 ret = CopyFileA(source, dest, FALSE);
638 ok(ret, "CopyFileA: error %d\n", GetLastError());
640 /* copying from a read-locked source fails */
641 hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
642 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
643 retok = CopyFileA(source, dest, FALSE);
644 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
645 "copying from a read-locked file succeeded when it shouldn't have\n");
646 /* in addition, the source is opened before the destination */
647 retok = CopyFileA("25f99d3b-4ba4-4f66-88f5-2906886993cc", dest, FALSE);
648 ok(!retok && GetLastError() == ERROR_FILE_NOT_FOUND,
649 "copying from a file that doesn't exist failed in an unexpected way (ret=%d, err=%d)\n", retok, GetLastError());
650 CloseHandle(hfile);
652 /* copying from a r+w opened, r shared source succeeds */
653 hfile = CreateFileA(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
654 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
655 retok = CopyFileA(source, dest, FALSE);
656 ok(retok,
657 "copying from an r+w opened and r shared file failed (ret=%d, err=%d)\n", retok, GetLastError());
658 CloseHandle(hfile);
660 /* copying from a delete-locked source mostly succeeds */
661 hfile = CreateFileA(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
662 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
663 retok = CopyFileA(source, dest, FALSE);
664 ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* NT, 2000, XP */,
665 "copying from a delete-locked file failed (ret=%d, err=%d)\n", retok, GetLastError());
666 CloseHandle(hfile);
668 /* copying to a write-locked destination fails */
669 hfile = CreateFileA(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
670 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
671 retok = CopyFileA(source, dest, FALSE);
672 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
673 "copying to a write-locked file didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
674 CloseHandle(hfile);
676 /* copying to a r+w opened, w shared destination mostly succeeds */
677 hfile = CreateFileA(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
678 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
679 retok = CopyFileA(source, dest, FALSE);
680 ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */,
681 "copying to a r+w opened and w shared file failed (ret=%d, err=%d)\n", retok, GetLastError());
682 CloseHandle(hfile);
684 /* copying to a delete-locked destination fails, even when the destination is delete-shared */
685 hfile = CreateFileA(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0);
686 ok(hfile != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* Win 9x */,
687 "failed to open destination file, error %d\n", GetLastError());
688 if (hfile != INVALID_HANDLE_VALUE)
690 retok = CopyFileA(source, dest, FALSE);
691 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
692 "copying to a delete-locked shared file didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
693 CloseHandle(hfile);
696 /* copy to a file that's opened the way Wine opens the source */
697 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
698 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
699 retok = CopyFileA(source, dest, FALSE);
700 ok(retok || broken(GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */,
701 "copying to a file opened the way Wine opens the source failed (ret=%d, err=%d)\n", retok, GetLastError());
702 CloseHandle(hfile);
704 /* make sure that destination has correct size */
705 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
706 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
707 ret = GetFileSize(hfile, NULL);
708 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
710 /* make sure that destination has the same filetime */
711 ret = GetFileTime(hfile, NULL, NULL, &ft2);
712 ok( ret, "GetFileTime error %d\n", GetLastError());
713 ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
715 SetLastError(0xdeadbeef);
716 ret = CopyFileA(source, dest, FALSE);
717 ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION,
718 "CopyFileA: ret = %d, unexpected error %d\n", ret, GetLastError());
720 /* make sure that destination still has correct size */
721 ret = GetFileSize(hfile, NULL);
722 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
723 retok = ReadFile(hfile, buf, sizeof(buf), &ret, NULL);
724 ok( retok && ret == sizeof(prefix),
725 "ReadFile: error %d\n", GetLastError());
726 ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
728 /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
729 hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
730 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
732 ret = CopyFileA(source, dest, FALSE);
733 ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION,
734 "CopyFileA with mapped dest file: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
736 CloseHandle(hmapfile);
737 CloseHandle(hfile);
739 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
740 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
742 /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
743 hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
744 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
746 ret = CopyFileA(source, dest, FALSE);
747 ok(!ret, "CopyFileA: expected failure\n");
748 ok(GetLastError() == ERROR_USER_MAPPED_FILE ||
749 broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x */
750 "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
752 CloseHandle(hmapfile);
753 CloseHandle(hfile);
755 ret = DeleteFileA(source);
756 ok(ret, "DeleteFileA: error %d\n", GetLastError());
757 ret = DeleteFileA(dest);
758 ok(ret, "DeleteFileA: error %d\n", GetLastError());
761 static void test_CopyFileW(void)
763 WCHAR temp_path[MAX_PATH];
764 WCHAR source[MAX_PATH], dest[MAX_PATH];
765 static const WCHAR prefix[] = {'p','f','x',0};
766 DWORD ret;
768 ret = GetTempPathW(MAX_PATH, temp_path);
769 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
771 win_skip("GetTempPathW is not available\n");
772 return;
774 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
775 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
777 ret = GetTempFileNameW(temp_path, prefix, 0, source);
778 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
780 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
781 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
783 ret = CopyFileW(source, dest, TRUE);
784 ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
785 "CopyFileW: unexpected error %d\n", GetLastError());
787 ret = CopyFileW(source, dest, FALSE);
788 ok(ret, "CopyFileW: error %d\n", GetLastError());
790 ret = DeleteFileW(source);
791 ok(ret, "DeleteFileW: error %d\n", GetLastError());
792 ret = DeleteFileW(dest);
793 ok(ret, "DeleteFileW: error %d\n", GetLastError());
796 static void test_CopyFile2(void)
798 static const WCHAR doesntexistW[] = {'d','o','e','s','n','t','e','x','i','s','t',0};
799 static const WCHAR prefix[] = {'p','f','x',0};
800 WCHAR source[MAX_PATH], dest[MAX_PATH], temp_path[MAX_PATH];
801 COPYFILE2_EXTENDED_PARAMETERS params;
802 HANDLE hfile, hmapfile;
803 FILETIME ft1, ft2;
804 DWORD ret, len;
805 char buf[10];
806 HRESULT hr;
808 if (!pCopyFile2)
810 skip("CopyFile2 is not available\n");
811 return;
814 ret = GetTempPathW(MAX_PATH, temp_path);
815 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
816 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
818 ret = GetTempFileNameW(temp_path, prefix, 0, source);
819 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
821 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
822 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
824 /* fail if exists */
825 memset(&params, 0, sizeof(params));
826 params.dwSize = sizeof(params);
827 params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
829 SetLastError(0xdeadbeef);
830 hr = pCopyFile2(source, dest, &params);
831 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
832 ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
834 /* don't fail if exists */
835 params.dwSize = sizeof(params);
836 params.dwCopyFlags = 0;
838 hr = pCopyFile2(source, dest, &params);
839 ok(hr == S_OK, "CopyFile2: error 0x%08x\n", hr);
841 /* copying a file to itself must fail */
842 params.dwSize = sizeof(params);
843 params.dwCopyFlags = 0;
845 SetLastError(0xdeadbeef);
846 hr = pCopyFile2(source, source, &params);
847 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: copying a file to itself didn't fail, 0x%08x\n", hr);
848 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
850 /* make the source have not zero size */
851 hfile = CreateFileW(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
852 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
853 ret = WriteFile(hfile, prefix, sizeof(prefix), &len, NULL );
854 ok(ret && len == sizeof(prefix), "WriteFile error %d\n", GetLastError());
855 ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
857 /* get the file time and change it to prove the difference */
858 ret = GetFileTime(hfile, NULL, NULL, &ft1);
859 ok(ret, "GetFileTime error %d\n", GetLastError());
860 ft1.dwLowDateTime -= 600000000; /* 60 second */
861 ret = SetFileTime(hfile, NULL, NULL, &ft1);
862 ok(ret, "SetFileTime error %d\n", GetLastError());
863 GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */
864 CloseHandle(hfile);
866 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
867 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
869 params.dwSize = sizeof(params);
870 params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
872 SetLastError(0xdeadbeef);
873 hr = pCopyFile2(source, dest, &params);
874 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
875 ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
877 params.dwSize = sizeof(params);
878 params.dwCopyFlags = 0;
879 hr = pCopyFile2(source, dest, &params);
880 ok(ret, "CopyFile2: error 0x%08x\n", hr);
882 /* copying from a read-locked source fails */
883 hfile = CreateFileW(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
884 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
886 params.dwSize = sizeof(params);
887 params.dwCopyFlags = 0;
888 SetLastError(0xdeadbeef);
889 hr = pCopyFile2(source, dest, &params);
890 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
891 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
893 /* in addition, the source is opened before the destination */
894 params.dwSize = sizeof(params);
895 params.dwCopyFlags = 0;
896 SetLastError(0xdeadbeef);
897 hr = pCopyFile2(doesntexistW, dest, &params);
898 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
899 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "CopyFile2: last error %d\n", GetLastError());
900 CloseHandle(hfile);
902 /* copying from a r+w opened, r shared source succeeds */
903 hfile = CreateFileW(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
904 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
906 params.dwSize = sizeof(params);
907 params.dwCopyFlags = 0;
908 hr = pCopyFile2(source, dest, &params);
909 ok(hr == S_OK, "failed 0x%08x\n", hr);
910 CloseHandle(hfile);
912 /* copying from a delete-locked source mostly succeeds */
913 hfile = CreateFileW(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
914 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
916 params.dwSize = sizeof(params);
917 params.dwCopyFlags = 0;
918 hr = pCopyFile2(source, dest, &params);
919 ok(hr == S_OK, "failed 0x%08x\n", hr);
920 CloseHandle(hfile);
922 /* copying to a write-locked destination fails */
923 hfile = CreateFileW(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
924 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
926 params.dwSize = sizeof(params);
927 params.dwCopyFlags = 0;
928 SetLastError(0xdeadbeef);
929 hr = pCopyFile2(source, dest, FALSE);
930 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
931 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
932 CloseHandle(hfile);
934 /* copying to a r+w opened, w shared destination mostly succeeds */
935 hfile = CreateFileW(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
936 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
938 params.dwSize = sizeof(params);
939 params.dwCopyFlags = 0;
940 hr = pCopyFile2(source, dest, FALSE);
941 ok(hr == S_OK, "got 0x%08x\n", hr);
942 CloseHandle(hfile);
944 /* copying to a delete-locked destination fails, even when the destination is delete-shared */
945 hfile = CreateFileW(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0);
946 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
948 params.dwSize = sizeof(params);
949 params.dwCopyFlags = 0;
950 SetLastError(0xdeadbeef);
951 hr = pCopyFile2(source, dest, &params);
952 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
953 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
954 CloseHandle(hfile);
956 /* copy to a file that's opened the way Wine opens the source */
957 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
958 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
960 params.dwSize = sizeof(params);
961 params.dwCopyFlags = 0;
962 hr = pCopyFile2(source, dest, &params);
963 ok(hr == S_OK, "got 0x%08x\n", hr);
964 CloseHandle(hfile);
966 /* make sure that destination has correct size */
967 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
968 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
969 ret = GetFileSize(hfile, NULL);
970 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
972 /* make sure that destination has the same filetime */
973 ret = GetFileTime(hfile, NULL, NULL, &ft2);
974 ok(ret, "GetFileTime error %d\n", GetLastError());
975 ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
977 params.dwSize = sizeof(params);
978 params.dwCopyFlags = 0;
979 SetLastError(0xdeadbeef);
980 hr = pCopyFile2(source, dest, &params);
981 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
982 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
984 /* make sure that destination still has correct size */
985 ret = GetFileSize(hfile, NULL);
986 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
987 ret = ReadFile(hfile, buf, sizeof(buf), &len, NULL);
988 ok(ret && len == sizeof(prefix), "ReadFile: error %d\n", GetLastError());
989 ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
991 /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
992 hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
993 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
995 params.dwSize = sizeof(params);
996 params.dwCopyFlags = 0;
997 SetLastError(0xdeadbeef);
998 hr = pCopyFile2(source, dest, &params);
999 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1000 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1002 CloseHandle(hmapfile);
1003 CloseHandle(hfile);
1005 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
1006 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
1008 /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
1009 hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1010 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1012 params.dwSize = sizeof(params);
1013 params.dwCopyFlags = 0;
1014 hr = pCopyFile2(source, dest, &params);
1015 ok(hr == HRESULT_FROM_WIN32(ERROR_USER_MAPPED_FILE), "CopyFile2: unexpected error 0x%08x\n", hr);
1016 ok(GetLastError() == ERROR_USER_MAPPED_FILE, "CopyFile2: last error %d\n", GetLastError());
1018 CloseHandle(hmapfile);
1019 CloseHandle(hfile);
1021 DeleteFileW(source);
1022 DeleteFileW(dest);
1026 * Debugging routine to dump a buffer in a hexdump-like fashion.
1028 static void dumpmem(unsigned char *mem, int len)
1030 int x = 0;
1031 char hex[49], *p;
1032 char txt[17], *c;
1034 while (x < len)
1036 p = hex;
1037 c = txt;
1038 do {
1039 p += sprintf(p, "%02x ", mem[x]);
1040 *c++ = (mem[x] >= 32 && mem[x] <= 127) ? mem[x] : '.';
1041 } while (++x % 16 && x < len);
1042 *c = '\0';
1043 trace("%04x: %-48s- %s\n", x, hex, txt);
1047 static void test_CreateFileA(void)
1049 HANDLE hFile;
1050 char temp_path[MAX_PATH], dirname[MAX_PATH];
1051 char filename[MAX_PATH];
1052 static const char prefix[] = "pfx";
1053 char windowsdir[MAX_PATH];
1054 char Volume_1[MAX_PATH];
1055 unsigned char buffer[512];
1056 char directory[] = "removeme";
1057 static const char nt_drive[] = "\\\\?\\A:";
1058 DWORD i, ret, len;
1059 struct test_list p[] = {
1060 {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dir as file w \ */
1061 {"", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* dir as dir w \ */
1062 {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */
1063 {"a\\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */
1064 {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */
1065 {"removeme\\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exst dir w \ */
1066 {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */
1067 {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */
1068 {"c:\\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */
1069 {"c:\\", ERROR_SUCCESS, ERROR_ACCESS_DENIED, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* root dir w \ as dir */
1070 {"\\\\?\\c:", ERROR_SUCCESS, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL,FALSE }, /* dev namespace drive */
1071 {"\\\\?\\c:\\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dev namespace drive w \ */
1072 {NULL, 0, -1, 0, FALSE}
1074 BY_HANDLE_FILE_INFORMATION Finfo;
1076 ret = GetTempPathA(MAX_PATH, temp_path);
1077 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1078 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1080 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
1081 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1083 SetLastError(0xdeadbeef);
1084 hFile = CreateFileA(filename, GENERIC_READ, 0, NULL,
1085 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1086 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
1087 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1089 SetLastError(0xdeadbeef);
1090 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1091 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1092 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1093 "hFile %p, last error %u\n", hFile, GetLastError());
1095 CloseHandle(hFile);
1097 SetLastError(0xdeadbeef);
1098 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1099 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1100 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1101 "hFile %p, last error %u\n", hFile, GetLastError());
1103 CloseHandle(hFile);
1105 ret = DeleteFileA(filename);
1106 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1108 SetLastError(0xdeadbeef);
1109 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1110 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1111 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1112 "hFile %p, last error %u\n", hFile, GetLastError());
1114 CloseHandle(hFile);
1116 ret = DeleteFileA(filename);
1117 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1119 SetLastError(0xdeadbeef);
1120 hFile = CreateFileA("c:\\*.*", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1121 ok(hFile == INVALID_HANDLE_VALUE, "hFile should have been INVALID_HANDLE_VALUE\n");
1122 ok(GetLastError() == ERROR_INVALID_NAME ||
1123 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */
1124 "LastError should have been ERROR_INVALID_NAME or ERROR_FILE_NOT_FOUND but got %u\n", GetLastError());
1126 /* get windows drive letter */
1127 ret = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
1128 ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
1129 ok(ret != 0, "GetWindowsDirectory: error %d\n", GetLastError());
1131 /* test error return codes from CreateFile for some cases */
1132 ret = GetTempPathA(MAX_PATH, temp_path);
1133 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1134 strcpy(dirname, temp_path);
1135 strcat(dirname, directory);
1136 ret = CreateDirectory(dirname, NULL);
1137 ok( ret, "Createdirectory failed, gle=%d\n", GetLastError() );
1138 /* set current drive & directory to known location */
1139 SetCurrentDirectoryA( temp_path );
1140 i = 0;
1141 while (p[i].file)
1143 filename[0] = 0;
1144 /* update the drive id in the table entry with the current one */
1145 if (p[i].file[1] == ':')
1147 strcpy(filename, p[i].file);
1148 filename[0] = windowsdir[0];
1150 else if (p[i].file[0] == '\\' && p[i].file[5] == ':')
1152 strcpy(filename, p[i].file);
1153 filename[4] = windowsdir[0];
1155 else
1157 /* prefix the table entry with the current temp directory */
1158 strcpy(filename, temp_path);
1159 strcat(filename, p[i].file);
1161 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1162 FILE_SHARE_READ | FILE_SHARE_WRITE,
1163 NULL, OPEN_EXISTING,
1164 p[i].options, NULL );
1165 /* if we get ACCESS_DENIED when we do not expect it, assume
1166 * no access to the volume
1168 if (hFile == INVALID_HANDLE_VALUE &&
1169 GetLastError() == ERROR_ACCESS_DENIED &&
1170 p[i].err != ERROR_ACCESS_DENIED)
1172 if (p[i].todo_flag)
1173 skip("Either no authority to volume, or is todo_wine for %s err=%d should be %d\n", filename, GetLastError(), p[i].err);
1174 else
1175 skip("Do not have authority to access volumes. Test for %s skipped\n", filename);
1177 /* otherwise validate results with expectations */
1178 else if (p[i].todo_flag)
1179 todo_wine ok(
1180 (hFile == INVALID_HANDLE_VALUE &&
1181 (p[i].err == GetLastError() || p[i].err2 == GetLastError())) ||
1182 (hFile != INVALID_HANDLE_VALUE && p[i].err == ERROR_SUCCESS),
1183 "CreateFileA failed on %s, hFile %p, err=%u, should be %u\n",
1184 filename, hFile, GetLastError(), p[i].err);
1185 else
1187 (hFile == INVALID_HANDLE_VALUE &&
1188 (p[i].err == GetLastError() || p[i].err2 == GetLastError())) ||
1189 (hFile != INVALID_HANDLE_VALUE && p[i].err == ERROR_SUCCESS),
1190 "CreateFileA failed on %s, hFile %p, err=%u, should be %u\n",
1191 filename, hFile, GetLastError(), p[i].err);
1192 if (hFile != INVALID_HANDLE_VALUE)
1193 CloseHandle( hFile );
1194 i++;
1196 ret = RemoveDirectoryA(dirname);
1197 ok(ret, "RemoveDirectoryA: error %d\n", GetLastError());
1200 /* test opening directory as a directory */
1201 hFile = CreateFileA( temp_path, GENERIC_READ,
1202 FILE_SHARE_READ,
1203 NULL,
1204 OPEN_EXISTING,
1205 FILE_FLAG_BACKUP_SEMANTICS, NULL );
1206 if (hFile != INVALID_HANDLE_VALUE && GetLastError() != ERROR_PATH_NOT_FOUND)
1208 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_SUCCESS,
1209 "CreateFileA did not work, last error %u on volume <%s>\n",
1210 GetLastError(), temp_path );
1212 if (hFile != INVALID_HANDLE_VALUE)
1214 ret = GetFileInformationByHandle( hFile, &Finfo );
1215 if (ret)
1217 ok(Finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY,
1218 "CreateFileA probably did not open temp directory %s correctly\n file information does not include FILE_ATTRIBUTE_DIRECTORY, actual=0x%08x\n",
1219 temp_path, Finfo.dwFileAttributes);
1221 CloseHandle( hFile );
1224 else
1225 skip("Probable Win9x, got ERROR_PATH_NOT_FOUND w/ FILE_FLAG_BACKUP_SEMANTICS or %s\n", temp_path);
1228 /* *** Test opening volumes/devices using drive letter *** */
1230 /* test using drive letter in non-rewrite format without trailing \ */
1231 /* this should work */
1232 strcpy(filename, nt_drive);
1233 filename[4] = windowsdir[0];
1234 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1235 FILE_SHARE_READ | FILE_SHARE_WRITE,
1236 NULL, OPEN_EXISTING,
1237 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1238 if (hFile != INVALID_HANDLE_VALUE ||
1239 (GetLastError() != ERROR_ACCESS_DENIED && GetLastError() != ERROR_BAD_NETPATH))
1241 /* if we have adm rights to volume, then try rest of tests */
1242 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1243 filename, GetLastError());
1244 if (hFile != INVALID_HANDLE_VALUE)
1246 /* if we opened the volume/device, try to read it. Since it */
1247 /* opened, we should be able to read it. We don't care about*/
1248 /* what the data is at this time. */
1249 len = 512;
1250 ret = ReadFile( hFile, buffer, len, &len, NULL );
1251 todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n",
1252 GetLastError(), ret, filename);
1253 if (ret)
1255 trace("buffer is\n");
1256 dumpmem(buffer, 64);
1258 CloseHandle( hFile );
1261 /* test using drive letter with trailing \ and in non-rewrite */
1262 /* this should not work */
1263 strcpy(filename, nt_drive);
1264 filename[4] = windowsdir[0];
1265 strcat( filename, "\\" );
1266 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1267 FILE_SHARE_READ | FILE_SHARE_WRITE,
1268 NULL, OPEN_EXISTING,
1269 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1270 todo_wine
1271 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1272 "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n",
1273 filename, GetLastError());
1274 if (hFile != INVALID_HANDLE_VALUE)
1275 CloseHandle( hFile );
1277 /* test using temp path with trailing \ and in non-rewrite as dir */
1278 /* this should work */
1279 strcpy(filename, nt_drive);
1280 filename[4] = 0;
1281 strcat( filename, temp_path );
1282 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1283 FILE_SHARE_READ | FILE_SHARE_WRITE,
1284 NULL, OPEN_EXISTING,
1285 FILE_FLAG_BACKUP_SEMANTICS, NULL );
1286 ok(hFile != INVALID_HANDLE_VALUE,
1287 "CreateFileA should have worked on %s, but got %u\n",
1288 filename, GetLastError());
1289 if (hFile != INVALID_HANDLE_VALUE)
1290 CloseHandle( hFile );
1292 /* test using drive letter without trailing \ and in device ns */
1293 /* this should work */
1294 strcpy(filename, nt_drive);
1295 filename[4] = windowsdir[0];
1296 filename[2] = '.';
1297 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1298 FILE_SHARE_READ | FILE_SHARE_WRITE,
1299 NULL, OPEN_EXISTING,
1300 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1301 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1302 filename, GetLastError());
1303 if (hFile != INVALID_HANDLE_VALUE)
1304 CloseHandle( hFile );
1306 /* If we see ERROR_BAD_NETPATH then on Win9x or WinME, so skip */
1307 else if (GetLastError() == ERROR_BAD_NETPATH)
1308 skip("Probable Win9x, got ERROR_BAD_NETPATH (53)\n");
1309 else
1310 skip("Do not have authority to access volumes. Tests skipped\n");
1313 /* *** Test opening volumes/devices using GUID *** */
1315 if (pGetVolumeNameForVolumeMountPointA)
1317 strcpy(filename, "c:\\");
1318 filename[0] = windowsdir[0];
1319 ret = pGetVolumeNameForVolumeMountPointA( filename, Volume_1, MAX_PATH );
1320 ok(ret, "GetVolumeNameForVolumeMountPointA failed, for %s, last error=%d\n", filename, GetLastError());
1321 if (ret)
1323 ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name <%s>\n", Volume_1);
1325 /* test the result of opening a unique volume name (GUID)
1326 * with the trailing \
1327 * this should error out
1329 strcpy(filename, Volume_1);
1330 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1331 FILE_SHARE_READ | FILE_SHARE_WRITE,
1332 NULL, OPEN_EXISTING,
1333 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1334 todo_wine
1335 ok(hFile == INVALID_HANDLE_VALUE,
1336 "CreateFileA should not have opened %s, hFile %p\n",
1337 filename, hFile);
1338 todo_wine
1339 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1340 "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n",
1341 filename, GetLastError());
1342 if (hFile != INVALID_HANDLE_VALUE)
1343 CloseHandle( hFile );
1345 /* test the result of opening a unique volume name (GUID)
1346 * with the temp path string as dir
1347 * this should work
1349 strcpy(filename, Volume_1);
1350 strcat(filename, temp_path+3);
1351 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1352 FILE_SHARE_READ | FILE_SHARE_WRITE,
1353 NULL, OPEN_EXISTING,
1354 FILE_FLAG_BACKUP_SEMANTICS, NULL );
1355 todo_wine
1356 ok(hFile != INVALID_HANDLE_VALUE,
1357 "CreateFileA should have opened %s, but got %u\n",
1358 filename, GetLastError());
1359 if (hFile != INVALID_HANDLE_VALUE)
1360 CloseHandle( hFile );
1362 /* test the result of opening a unique volume name (GUID)
1363 * without the trailing \ and in device namespace
1364 * this should work
1366 strcpy(filename, Volume_1);
1367 filename[2] = '.';
1368 filename[48] = 0;
1369 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1370 FILE_SHARE_READ | FILE_SHARE_WRITE,
1371 NULL, OPEN_EXISTING,
1372 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1373 if (hFile != INVALID_HANDLE_VALUE || GetLastError() != ERROR_ACCESS_DENIED)
1375 /* if we have adm rights to volume, then try rest of tests */
1376 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1377 filename, GetLastError());
1378 if (hFile != INVALID_HANDLE_VALUE)
1380 /* if we opened the volume/device, try to read it. Since it */
1381 /* opened, we should be able to read it. We don't care about*/
1382 /* what the data is at this time. */
1383 len = 512;
1384 ret = ReadFile( hFile, buffer, len, &len, NULL );
1385 todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n",
1386 GetLastError(), ret, filename);
1387 if (ret)
1389 trace("buffer is\n");
1390 dumpmem(buffer, 64);
1392 CloseHandle( hFile );
1395 else
1396 skip("Do not have authority to access volumes. Tests skipped\n");
1398 else
1399 win_skip("GetVolumeNameForVolumeMountPointA not functioning\n");
1401 else
1402 win_skip("GetVolumeNameForVolumeMountPointA not found\n");
1405 static void test_CreateFileW(void)
1407 HANDLE hFile;
1408 WCHAR temp_path[MAX_PATH];
1409 WCHAR filename[MAX_PATH];
1410 static const WCHAR emptyW[]={'\0'};
1411 static const WCHAR prefix[] = {'p','f','x',0};
1412 static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
1413 DWORD ret;
1415 ret = GetTempPathW(MAX_PATH, temp_path);
1416 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1418 win_skip("GetTempPathW is not available\n");
1419 return;
1421 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1422 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1424 ret = GetTempFileNameW(temp_path, prefix, 0, filename);
1425 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1427 SetLastError(0xdeadbeef);
1428 hFile = CreateFileW(filename, GENERIC_READ, 0, NULL,
1429 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1430 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
1431 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1433 SetLastError(0xdeadbeef);
1434 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1435 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1436 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1437 "hFile %p, last error %u\n", hFile, GetLastError());
1439 CloseHandle(hFile);
1441 SetLastError(0xdeadbeef);
1442 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1443 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1444 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1445 "hFile %p, last error %u\n", hFile, GetLastError());
1447 CloseHandle(hFile);
1449 ret = DeleteFileW(filename);
1450 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1452 SetLastError(0xdeadbeef);
1453 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1454 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1455 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1456 "hFile %p, last error %u\n", hFile, GetLastError());
1458 CloseHandle(hFile);
1460 ret = DeleteFileW(filename);
1461 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1463 if (0)
1465 /* this crashes on NT4.0 */
1466 hFile = CreateFileW(NULL, GENERIC_READ, 0, NULL,
1467 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1468 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1469 "CreateFileW(NULL) returned ret=%p error=%u\n",hFile,GetLastError());
1472 hFile = CreateFileW(emptyW, GENERIC_READ, 0, NULL,
1473 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1474 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1475 "CreateFileW(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
1477 /* test the result of opening a nonexistent driver name */
1478 hFile = CreateFileW(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1479 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1480 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
1481 "CreateFileW on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
1483 ret = CreateDirectoryW(filename, NULL);
1484 ok(ret == TRUE, "couldn't create temporary directory\n");
1485 hFile = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1486 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
1487 ok(hFile != INVALID_HANDLE_VALUE,
1488 "expected CreateFile to succeed on existing directory, error: %d\n", GetLastError());
1489 CloseHandle(hFile);
1490 ret = RemoveDirectoryW(filename);
1491 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1494 static void test_CreateFile2(void)
1496 HANDLE hFile;
1497 WCHAR temp_path[MAX_PATH];
1498 WCHAR filename[MAX_PATH];
1499 CREATEFILE2_EXTENDED_PARAMETERS exparams;
1500 static const WCHAR emptyW[]={'\0'};
1501 static const WCHAR prefix[] = {'p','f','x',0};
1502 static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
1503 DWORD ret;
1505 if (!pCreateFile2)
1507 win_skip("CreateFile2 is missing\n");
1508 return;
1511 ret = GetTempPathW(MAX_PATH, temp_path);
1512 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1513 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1515 ret = GetTempFileNameW(temp_path, prefix, 0, filename);
1516 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1518 SetLastError(0xdeadbeef);
1519 exparams.dwSize = sizeof(exparams);
1520 exparams.dwFileAttributes = FILE_FLAG_RANDOM_ACCESS;
1521 exparams.dwFileFlags = 0;
1522 exparams.dwSecurityQosFlags = 0;
1523 exparams.lpSecurityAttributes = NULL;
1524 exparams.hTemplateFile = 0;
1525 hFile = pCreateFile2(filename, GENERIC_READ, 0, CREATE_NEW, &exparams);
1526 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
1527 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1529 SetLastError(0xdeadbeef);
1530 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, CREATE_ALWAYS, &exparams);
1531 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1532 "hFile %p, last error %u\n", hFile, GetLastError());
1533 CloseHandle(hFile);
1535 SetLastError(0xdeadbeef);
1536 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
1537 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1538 "hFile %p, last error %u\n", hFile, GetLastError());
1539 CloseHandle(hFile);
1541 ret = DeleteFileW(filename);
1542 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1544 SetLastError(0xdeadbeef);
1545 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
1546 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1547 "hFile %p, last error %u\n", hFile, GetLastError());
1548 CloseHandle(hFile);
1550 ret = DeleteFileW(filename);
1551 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1553 hFile = pCreateFile2(emptyW, GENERIC_READ, 0, CREATE_NEW, &exparams);
1554 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1555 "CreateFile2(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
1557 /* test the result of opening a nonexistent driver name */
1558 exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
1559 hFile = pCreateFile2(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &exparams);
1560 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
1561 "CreateFile2 on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
1563 ret = CreateDirectoryW(filename, NULL);
1564 ok(ret == TRUE, "couldn't create temporary directory\n");
1565 exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS;
1566 hFile = pCreateFile2(filename, GENERIC_READ | GENERIC_WRITE, 0, OPEN_ALWAYS, &exparams);
1567 todo_wine
1568 ok(hFile == INVALID_HANDLE_VALUE,
1569 "expected CreateFile2 to fail on existing directory, error: %d\n", GetLastError());
1570 CloseHandle(hFile);
1571 ret = RemoveDirectoryW(filename);
1572 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1575 static void test_GetTempFileNameA(void)
1577 UINT result;
1578 char out[MAX_PATH];
1579 char expected[MAX_PATH + 10];
1580 char windowsdir[MAX_PATH + 10];
1581 char windowsdrive[3];
1583 result = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
1584 ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
1585 ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
1587 /* If the Windows directory is the root directory, it ends in backslash, not else. */
1588 if (strlen(windowsdir) != 3) /* As in "C:\" or "F:\" */
1590 strcat(windowsdir, "\\");
1593 windowsdrive[0] = windowsdir[0];
1594 windowsdrive[1] = windowsdir[1];
1595 windowsdrive[2] = '\0';
1597 result = GetTempFileNameA(windowsdrive, "abc", 1, out);
1598 ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
1599 ok(((out[0] == windowsdrive[0]) && (out[1] == ':')) && (out[2] == '\\'),
1600 "GetTempFileNameA: first three characters should be %c:\\, string was actually %s\n",
1601 windowsdrive[0], out);
1603 result = GetTempFileNameA(windowsdir, "abc", 2, out);
1604 ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
1605 expected[0] = '\0';
1606 strcat(expected, windowsdir);
1607 strcat(expected, "abc2.tmp");
1608 ok(lstrcmpiA(out, expected) == 0, "GetTempFileNameA: Unexpected output \"%s\" vs \"%s\"\n",
1609 out, expected);
1612 static void test_DeleteFileA( void )
1614 BOOL ret;
1615 char temp_path[MAX_PATH], temp_file[MAX_PATH];
1616 HANDLE hfile;
1618 ret = DeleteFileA(NULL);
1619 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER ||
1620 GetLastError() == ERROR_PATH_NOT_FOUND),
1621 "DeleteFileA(NULL) returned ret=%d error=%d\n",ret,GetLastError());
1623 ret = DeleteFileA("");
1624 ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND ||
1625 GetLastError() == ERROR_BAD_PATHNAME),
1626 "DeleteFileA(\"\") returned ret=%d error=%d\n",ret,GetLastError());
1628 ret = DeleteFileA("nul");
1629 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
1630 GetLastError() == ERROR_INVALID_PARAMETER ||
1631 GetLastError() == ERROR_ACCESS_DENIED ||
1632 GetLastError() == ERROR_INVALID_FUNCTION),
1633 "DeleteFileA(\"nul\") returned ret=%d error=%d\n",ret,GetLastError());
1635 GetTempPathA(MAX_PATH, temp_path);
1636 GetTempFileName(temp_path, "tst", 0, temp_file);
1638 SetLastError(0xdeadbeef);
1639 hfile = CreateFile(temp_file, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1640 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1642 SetLastError(0xdeadbeef);
1643 ret = DeleteFile(temp_file);
1644 todo_wine
1645 ok(ret, "DeleteFile error %d\n", GetLastError());
1647 SetLastError(0xdeadbeef);
1648 ret = CloseHandle(hfile);
1649 ok(ret, "CloseHandle error %d\n", GetLastError());
1650 ret = DeleteFile(temp_file);
1651 todo_wine
1652 ok(!ret, "DeleteFile should fail\n");
1655 static void test_DeleteFileW( void )
1657 BOOL ret;
1658 WCHAR pathW[MAX_PATH];
1659 WCHAR pathsubW[MAX_PATH];
1660 static const WCHAR dirW[] = {'d','e','l','e','t','e','f','i','l','e',0};
1661 static const WCHAR subdirW[] = {'\\','s','u','b',0};
1662 static const WCHAR emptyW[]={'\0'};
1664 ret = DeleteFileW(NULL);
1665 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1667 win_skip("DeleteFileW is not available\n");
1668 return;
1670 ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
1671 "DeleteFileW(NULL) returned ret=%d error=%d\n",ret,GetLastError());
1673 ret = DeleteFileW(emptyW);
1674 ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
1675 "DeleteFileW(\"\") returned ret=%d error=%d\n",ret,GetLastError());
1677 /* test DeleteFile on empty directory */
1678 ret = GetTempPathW(MAX_PATH, pathW);
1679 if (ret + sizeof(dirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
1681 ok(0, "MAX_PATH exceeded in constructing paths\n");
1682 return;
1684 lstrcatW(pathW, dirW);
1685 lstrcpyW(pathsubW, pathW);
1686 lstrcatW(pathsubW, subdirW);
1687 ret = CreateDirectoryW(pathW, NULL);
1688 ok(ret == TRUE, "couldn't create directory deletefile\n");
1689 ret = DeleteFileW(pathW);
1690 ok(ret == FALSE, "DeleteFile should fail for empty directories\n");
1691 ret = RemoveDirectoryW(pathW);
1692 ok(ret == TRUE, "expected to remove directory deletefile\n");
1694 /* test DeleteFile on non-empty directory */
1695 ret = CreateDirectoryW(pathW, NULL);
1696 ok(ret == TRUE, "couldn't create directory deletefile\n");
1697 ret = CreateDirectoryW(pathsubW, NULL);
1698 ok(ret == TRUE, "couldn't create directory deletefile\\sub\n");
1699 ret = DeleteFileW(pathW);
1700 ok(ret == FALSE, "DeleteFile should fail for non-empty directories\n");
1701 ret = RemoveDirectoryW(pathsubW);
1702 ok(ret == TRUE, "expected to remove directory deletefile\\sub\n");
1703 ret = RemoveDirectoryW(pathW);
1704 ok(ret == TRUE, "expected to remove directory deletefile\n");
1707 #define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
1709 static void test_MoveFileA(void)
1711 char tempdir[MAX_PATH];
1712 char source[MAX_PATH], dest[MAX_PATH];
1713 static const char prefix[] = "pfx";
1714 HANDLE hfile;
1715 HANDLE hmapfile;
1716 DWORD ret;
1717 BOOL retok;
1719 ret = GetTempPathA(MAX_PATH, tempdir);
1720 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1721 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1723 ret = GetTempFileNameA(tempdir, prefix, 0, source);
1724 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1726 ret = GetTempFileNameA(tempdir, prefix, 0, dest);
1727 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1729 ret = MoveFileA(source, dest);
1730 ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
1731 "MoveFileA: unexpected error %d\n", GetLastError());
1733 ret = DeleteFileA(dest);
1734 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1736 hfile = CreateFileA(source, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
1737 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
1739 retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL );
1740 ok( retok && ret == sizeof(prefix),
1741 "WriteFile error %d\n", GetLastError());
1743 hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1744 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1746 ret = MoveFileA(source, dest);
1747 todo_wine {
1748 ok(!ret, "MoveFileA: expected failure\n");
1749 ok(GetLastError() == ERROR_SHARING_VIOLATION ||
1750 broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
1751 "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
1754 CloseHandle(hmapfile);
1755 CloseHandle(hfile);
1757 /* if MoveFile succeeded, move back to dest */
1758 if (ret) MoveFile(dest, source);
1760 hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1761 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
1763 hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1764 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1766 ret = MoveFileA(source, dest);
1767 todo_wine {
1768 ok(!ret, "MoveFileA: expected failure\n");
1769 ok(GetLastError() == ERROR_SHARING_VIOLATION ||
1770 broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
1771 "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
1774 CloseHandle(hmapfile);
1775 CloseHandle(hfile);
1777 /* if MoveFile succeeded, move back to dest */
1778 if (ret) MoveFile(dest, source);
1780 ret = MoveFileA(source, dest);
1781 ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
1783 lstrcatA(tempdir, "Remove Me");
1784 ret = CreateDirectoryA(tempdir, NULL);
1785 ok(ret == TRUE, "CreateDirectoryA failed\n");
1787 lstrcpyA(source, dest);
1788 lstrcpyA(dest, tempdir);
1789 lstrcatA(dest, "\\wild?.*");
1790 /* FIXME: if we create a file with wildcards we can't delete it now that DeleteFile works correctly */
1791 ret = MoveFileA(source, dest);
1792 ok(!ret, "MoveFileA: shouldn't move to wildcard file\n");
1793 ok(GetLastError() == ERROR_INVALID_NAME || /* NT */
1794 GetLastError() == ERROR_FILE_NOT_FOUND, /* Win9x */
1795 "MoveFileA: with wildcards, unexpected error %d\n", GetLastError());
1796 if (ret || (GetLastError() != ERROR_INVALID_NAME))
1798 WIN32_FIND_DATAA fd;
1799 char temppath[MAX_PATH];
1800 HANDLE hFind;
1802 lstrcpyA(temppath, tempdir);
1803 lstrcatA(temppath, "\\*.*");
1804 hFind = FindFirstFileA(temppath, &fd);
1805 if (INVALID_HANDLE_VALUE != hFind)
1807 LPSTR lpName;
1810 lpName = fd.cAlternateFileName;
1811 if (!lpName[0])
1812 lpName = fd.cFileName;
1813 ok(IsDotDir(lpName), "MoveFileA: wildcards file created!\n");
1815 while (FindNextFileA(hFind, &fd));
1816 FindClose(hFind);
1819 ret = DeleteFileA(source);
1820 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1821 ret = DeleteFileA(dest);
1822 ok(!ret, "DeleteFileA: error %d\n", GetLastError());
1823 ret = RemoveDirectoryA(tempdir);
1824 ok(ret, "DeleteDirectoryA: error %d\n", GetLastError());
1827 static void test_MoveFileW(void)
1829 WCHAR temp_path[MAX_PATH];
1830 WCHAR source[MAX_PATH], dest[MAX_PATH];
1831 static const WCHAR prefix[] = {'p','f','x',0};
1832 DWORD ret;
1834 ret = GetTempPathW(MAX_PATH, temp_path);
1835 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1837 win_skip("GetTempPathW is not available\n");
1838 return;
1840 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1841 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1843 ret = GetTempFileNameW(temp_path, prefix, 0, source);
1844 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1846 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
1847 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1849 ret = MoveFileW(source, dest);
1850 ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
1851 "CopyFileW: unexpected error %d\n", GetLastError());
1853 ret = DeleteFileW(source);
1854 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1855 ret = DeleteFileW(dest);
1856 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1859 #define PATTERN_OFFSET 0x10
1861 static void test_offset_in_overlapped_structure(void)
1863 HANDLE hFile;
1864 OVERLAPPED ov;
1865 DWORD done, offset;
1866 BOOL rc;
1867 BYTE buf[256], pattern[] = "TeSt";
1868 UINT i;
1869 char temp_path[MAX_PATH], temp_fname[MAX_PATH];
1870 BOOL ret;
1872 ret =GetTempPathA(MAX_PATH, temp_path);
1873 ok( ret, "GetTempPathA error %d\n", GetLastError());
1874 ret =GetTempFileNameA(temp_path, "pfx", 0, temp_fname);
1875 ok( ret, "GetTempFileNameA error %d\n", GetLastError());
1877 /*** Write File *****************************************************/
1879 hFile = CreateFileA(temp_fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1880 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
1882 for(i = 0; i < sizeof(buf); i++) buf[i] = i;
1883 ret = WriteFile(hFile, buf, sizeof(buf), &done, NULL);
1884 ok( ret, "WriteFile error %d\n", GetLastError());
1885 ok(done == sizeof(buf), "expected number of bytes written %u\n", done);
1887 memset(&ov, 0, sizeof(ov));
1888 S(U(ov)).Offset = PATTERN_OFFSET;
1889 S(U(ov)).OffsetHigh = 0;
1890 rc=WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
1891 /* Win 9x does not support the overlapped I/O on files */
1892 if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
1893 ok(rc, "WriteFile error %d\n", GetLastError());
1894 ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
1895 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1896 ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
1898 S(U(ov)).Offset = sizeof(buf) * 2;
1899 S(U(ov)).OffsetHigh = 0;
1900 ret = WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
1901 ok( ret, "WriteFile error %d\n", GetLastError());
1902 ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
1903 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1904 ok(offset == sizeof(buf) * 2 + sizeof(pattern), "wrong file offset %d\n", offset);
1907 CloseHandle(hFile);
1909 /*** Read File *****************************************************/
1911 hFile = CreateFileA(temp_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
1912 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
1914 memset(buf, 0, sizeof(buf));
1915 memset(&ov, 0, sizeof(ov));
1916 S(U(ov)).Offset = PATTERN_OFFSET;
1917 S(U(ov)).OffsetHigh = 0;
1918 rc=ReadFile(hFile, buf, sizeof(pattern), &done, &ov);
1919 /* Win 9x does not support the overlapped I/O on files */
1920 if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
1921 ok(rc, "ReadFile error %d\n", GetLastError());
1922 ok(done == sizeof(pattern), "expected number of bytes read %u\n", done);
1923 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1924 ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
1925 ok(!memcmp(buf, pattern, sizeof(pattern)), "pattern match failed\n");
1928 CloseHandle(hFile);
1930 ret = DeleteFileA(temp_fname);
1931 ok( ret, "DeleteFileA error %d\n", GetLastError());
1934 static void test_LockFile(void)
1936 HANDLE handle, handle2;
1937 DWORD written;
1938 OVERLAPPED overlapped;
1939 int limited_LockFile;
1940 int limited_UnLockFile;
1941 BOOL ret;
1943 handle = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1944 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1945 CREATE_ALWAYS, 0, 0 );
1946 if (handle == INVALID_HANDLE_VALUE)
1948 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
1949 return;
1951 handle2 = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1952 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1953 OPEN_EXISTING, 0, 0 );
1954 if (handle2 == INVALID_HANDLE_VALUE)
1956 ok( 0, "couldn't open file \"%s\" (err=%d)\n", filename, GetLastError() );
1957 goto cleanup;
1959 ok( WriteFile( handle, sillytext, strlen(sillytext), &written, NULL ), "write failed\n" );
1961 ok( LockFile( handle, 0, 0, 0, 0 ), "LockFile failed\n" );
1962 ok( UnlockFile( handle, 0, 0, 0, 0 ), "UnlockFile failed\n" );
1964 limited_UnLockFile = 0;
1965 if (UnlockFile( handle, 0, 0, 0, 0 ))
1967 limited_UnLockFile = 1;
1970 ok( LockFile( handle, 10, 0, 20, 0 ), "LockFile 10,20 failed\n" );
1971 /* overlapping locks must fail */
1972 ok( !LockFile( handle, 12, 0, 10, 0 ), "LockFile 12,10 succeeded\n" );
1973 ok( !LockFile( handle, 5, 0, 6, 0 ), "LockFile 5,6 succeeded\n" );
1974 /* non-overlapping locks must succeed */
1975 ok( LockFile( handle, 5, 0, 5, 0 ), "LockFile 5,5 failed\n" );
1977 ok( !UnlockFile( handle, 10, 0, 10, 0 ), "UnlockFile 10,10 succeeded\n" );
1978 ok( UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 failed\n" );
1979 ok( !UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 again succeeded\n" );
1980 ok( UnlockFile( handle, 5, 0, 5, 0 ), "UnlockFile 5,5 failed\n" );
1982 S(U(overlapped)).Offset = 100;
1983 S(U(overlapped)).OffsetHigh = 0;
1984 overlapped.hEvent = 0;
1986 /* Test for broken LockFileEx a la Windows 95 OSR2. */
1987 if (LockFileEx( handle, 0, 0, 100, 0, &overlapped ))
1989 /* LockFileEx is probably OK, test it more. */
1990 ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ),
1991 "LockFileEx 100,100 failed\n" );
1994 /* overlapping shared locks are OK */
1995 S(U(overlapped)).Offset = 150;
1996 limited_UnLockFile || ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 150,100 failed\n" );
1998 /* but exclusive is not */
1999 ok( !LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2000 0, 50, 0, &overlapped ),
2001 "LockFileEx exclusive 150,50 succeeded\n" );
2002 if (!UnlockFileEx( handle, 0, 100, 0, &overlapped ))
2003 { /* UnLockFile is capable. */
2004 S(U(overlapped)).Offset = 100;
2005 ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ),
2006 "UnlockFileEx 150,100 again succeeded\n" );
2009 /* shared lock can overlap exclusive if handles are equal */
2010 S(U(overlapped)).Offset = 300;
2011 ok( LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, &overlapped ),
2012 "LockFileEx exclusive 300,100 failed\n" );
2013 ok( !LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
2014 "LockFileEx handle2 300,100 succeeded\n" );
2015 ret = LockFileEx( handle, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped );
2016 ok( ret, "LockFileEx 300,100 failed\n" );
2017 ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2018 /* exclusive lock is removed first */
2019 ok( LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
2020 "LockFileEx handle2 300,100 failed\n" );
2021 ok( UnlockFileEx( handle2, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2022 if (ret)
2023 ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2025 ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 );
2026 if (ret)
2028 ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
2029 ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
2030 ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
2032 else /* win9x */
2033 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong LockFile error %u\n", GetLastError() );
2035 /* wrap-around lock should not do anything */
2036 /* (but still succeeds on NT4 so we don't check result) */
2037 LockFile( handle, 0, 0x10000000, 0, 0xf0000001 );
2039 limited_LockFile = 0;
2040 if (!LockFile( handle, ~0, ~0, 1, 0 ))
2042 limited_LockFile = 1;
2045 limited_UnLockFile || ok( UnlockFile( handle, ~0, ~0, 1, 0 ), "Unlockfile ~0,1 failed\n" );
2047 /* zero-byte lock */
2048 ok( LockFile( handle, 100, 0, 0, 0 ), "LockFile 100,0 failed\n" );
2049 if (!limited_LockFile) ok( !LockFile( handle, 98, 0, 4, 0 ), "LockFile 98,4 succeeded\n" );
2050 ok( LockFile( handle, 90, 0, 10, 0 ), "LockFile 90,10 failed\n" );
2051 if (!limited_LockFile) ok( !LockFile( handle, 100, 0, 10, 0 ), "LockFile 100,10 failed\n" );
2053 ok( UnlockFile( handle, 90, 0, 10, 0 ), "UnlockFile 90,10 failed\n" );
2054 ok( !UnlockFile( handle, 100, 0, 10, 0 ), "UnlockFile 100,10 succeeded\n" );
2056 ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed\n" );
2058 CloseHandle( handle2 );
2059 cleanup:
2060 CloseHandle( handle );
2061 DeleteFileA( filename );
2064 static BOOL create_fake_dll( LPCSTR filename )
2066 IMAGE_DOS_HEADER *dos;
2067 IMAGE_NT_HEADERS *nt;
2068 IMAGE_SECTION_HEADER *sec;
2069 BYTE *buffer;
2070 DWORD lfanew = sizeof(*dos);
2071 DWORD size = lfanew + sizeof(*nt) + sizeof(*sec);
2072 DWORD written;
2073 BOOL ret;
2075 HANDLE file = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2076 if (file == INVALID_HANDLE_VALUE) return FALSE;
2078 buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
2080 dos = (IMAGE_DOS_HEADER *)buffer;
2081 dos->e_magic = IMAGE_DOS_SIGNATURE;
2082 dos->e_cblp = sizeof(*dos);
2083 dos->e_cp = 1;
2084 dos->e_cparhdr = lfanew / 16;
2085 dos->e_minalloc = 0;
2086 dos->e_maxalloc = 0xffff;
2087 dos->e_ss = 0x0000;
2088 dos->e_sp = 0x00b8;
2089 dos->e_lfarlc = lfanew;
2090 dos->e_lfanew = lfanew;
2092 nt = (IMAGE_NT_HEADERS *)(buffer + lfanew);
2093 nt->Signature = IMAGE_NT_SIGNATURE;
2094 #if defined __i386__
2095 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386;
2096 #elif defined __x86_64__
2097 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64;
2098 #elif defined __powerpc__
2099 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC;
2100 #elif defined __arm__
2101 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT;
2102 #elif defined __aarch64__
2103 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64;
2104 #else
2105 # error You must specify the machine type
2106 #endif
2107 nt->FileHeader.NumberOfSections = 1;
2108 nt->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
2109 nt->FileHeader.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE;
2110 nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
2111 nt->OptionalHeader.MajorLinkerVersion = 1;
2112 nt->OptionalHeader.MinorLinkerVersion = 0;
2113 nt->OptionalHeader.ImageBase = 0x10000000;
2114 nt->OptionalHeader.SectionAlignment = 0x1000;
2115 nt->OptionalHeader.FileAlignment = 0x1000;
2116 nt->OptionalHeader.MajorOperatingSystemVersion = 1;
2117 nt->OptionalHeader.MinorOperatingSystemVersion = 0;
2118 nt->OptionalHeader.MajorImageVersion = 1;
2119 nt->OptionalHeader.MinorImageVersion = 0;
2120 nt->OptionalHeader.MajorSubsystemVersion = 4;
2121 nt->OptionalHeader.MinorSubsystemVersion = 0;
2122 nt->OptionalHeader.SizeOfImage = 0x2000;
2123 nt->OptionalHeader.SizeOfHeaders = size;
2124 nt->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
2125 nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
2127 sec = (IMAGE_SECTION_HEADER *)(nt + 1);
2128 memcpy( sec->Name, ".rodata", sizeof(".rodata") );
2129 sec->Misc.VirtualSize = 0x1000;
2130 sec->VirtualAddress = 0x1000;
2131 sec->SizeOfRawData = 0;
2132 sec->PointerToRawData = 0;
2133 sec->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
2135 ret = WriteFile( file, buffer, size, &written, NULL ) && written == size;
2136 HeapFree( GetProcessHeap(), 0, buffer );
2137 CloseHandle( file );
2138 return ret;
2141 static unsigned int map_file_access( unsigned int access )
2143 if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
2144 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
2145 if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
2146 if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS;
2147 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
2150 static int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 )
2152 access1 = map_file_access( access1 );
2153 access2 = map_file_access( access2 );
2154 access1 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE;
2155 access2 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE;
2157 if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
2158 if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
2160 if ((access1 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing2 & FILE_SHARE_READ)) return 0;
2161 if ((access1 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing2 & FILE_SHARE_WRITE)) return 0;
2162 if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return 0;
2163 if ((access2 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing1 & FILE_SHARE_READ)) return 0;
2164 if ((access2 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing1 & FILE_SHARE_WRITE)) return 0;
2165 if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return 0;
2166 return 1;
2169 static int is_sharing_map_compatible( DWORD map_access, DWORD access2, DWORD sharing2 )
2171 if ((map_access == PAGE_READWRITE || map_access == PAGE_EXECUTE_READWRITE) &&
2172 !(sharing2 & FILE_SHARE_WRITE)) return 0;
2173 access2 = map_file_access( access2 );
2174 if ((map_access & SEC_IMAGE) && (access2 & FILE_WRITE_DATA)) return 0;
2175 return 1;
2178 static void test_file_sharing(void)
2180 static const DWORD access_modes[] =
2181 { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE,
2182 DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE,
2183 GENERIC_EXECUTE, GENERIC_EXECUTE | DELETE,
2184 FILE_READ_DATA, FILE_WRITE_DATA, FILE_APPEND_DATA, FILE_READ_EA, FILE_WRITE_EA,
2185 FILE_READ_DATA | FILE_EXECUTE, FILE_WRITE_DATA | FILE_EXECUTE, FILE_APPEND_DATA | FILE_EXECUTE,
2186 FILE_READ_EA | FILE_EXECUTE, FILE_WRITE_EA | FILE_EXECUTE, FILE_EXECUTE,
2187 FILE_DELETE_CHILD, FILE_READ_ATTRIBUTES, FILE_WRITE_ATTRIBUTES };
2188 static const DWORD sharing_modes[] =
2189 { 0, FILE_SHARE_READ,
2190 FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
2191 FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_DELETE,
2192 FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE };
2193 static const DWORD mapping_modes[] =
2194 { PAGE_READONLY, PAGE_WRITECOPY, PAGE_READWRITE, SEC_IMAGE | PAGE_WRITECOPY };
2195 int a1, s1, a2, s2;
2196 int ret;
2197 HANDLE h, h2;
2199 /* make sure the file exists */
2200 if (!create_fake_dll( filename ))
2202 ok(0, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError());
2203 return;
2206 for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++)
2208 for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++)
2210 SetLastError(0xdeadbeef);
2211 h = CreateFileA( filename, access_modes[a1], sharing_modes[s1],
2212 NULL, OPEN_EXISTING, 0, 0 );
2213 if (h == INVALID_HANDLE_VALUE)
2215 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2216 return;
2218 for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
2220 for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
2222 SetLastError(0xdeadbeef);
2223 h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
2224 NULL, OPEN_EXISTING, 0, 0 );
2225 ret = GetLastError();
2226 if (is_sharing_compatible( access_modes[a1], sharing_modes[s1],
2227 access_modes[a2], sharing_modes[s2] ))
2229 ok( h2 != INVALID_HANDLE_VALUE,
2230 "open failed for modes %x/%x/%x/%x\n",
2231 access_modes[a1], sharing_modes[s1],
2232 access_modes[a2], sharing_modes[s2] );
2233 ok( ret == 0, "wrong error code %d\n", ret );
2235 else
2237 ok( h2 == INVALID_HANDLE_VALUE,
2238 "open succeeded for modes %x/%x/%x/%x\n",
2239 access_modes[a1], sharing_modes[s1],
2240 access_modes[a2], sharing_modes[s2] );
2241 ok( ret == ERROR_SHARING_VIOLATION,
2242 "wrong error code %d\n", ret );
2244 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2247 CloseHandle( h );
2251 for (a1 = 0; a1 < sizeof(mapping_modes)/sizeof(mapping_modes[0]); a1++)
2253 HANDLE m;
2255 create_fake_dll( filename );
2256 SetLastError(0xdeadbeef);
2257 h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
2258 if (h == INVALID_HANDLE_VALUE)
2260 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2261 return;
2263 m = CreateFileMappingA( h, NULL, mapping_modes[a1], 0, 0, NULL );
2264 ok( m != 0, "failed to create mapping %x err %u\n", mapping_modes[a1], GetLastError() );
2265 CloseHandle( h );
2266 if (!m) continue;
2268 for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
2270 for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
2272 SetLastError(0xdeadbeef);
2273 h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
2274 NULL, OPEN_EXISTING, 0, 0 );
2276 ret = GetLastError();
2277 if (h2 == INVALID_HANDLE_VALUE)
2279 ok( !is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]),
2280 "open failed for modes map %x/%x/%x\n",
2281 mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
2282 ok( ret == ERROR_SHARING_VIOLATION,
2283 "wrong error code %d\n", ret );
2285 else
2287 if (!is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
2288 ok( broken(1), /* no checking on nt4 */
2289 "open succeeded for modes map %x/%x/%x\n",
2290 mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
2291 ok( ret == 0xdeadbeef /* Win9x */ ||
2292 ret == 0, /* XP */
2293 "wrong error code %d\n", ret );
2294 CloseHandle( h2 );
2299 /* try CREATE_ALWAYS over an existing mapping */
2300 SetLastError(0xdeadbeef);
2301 h2 = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2302 NULL, CREATE_ALWAYS, 0, 0 );
2303 ret = GetLastError();
2304 if (mapping_modes[a1] & SEC_IMAGE)
2306 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
2307 ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
2309 else
2311 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
2312 ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
2314 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2316 /* try DELETE_ON_CLOSE over an existing mapping */
2317 SetLastError(0xdeadbeef);
2318 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2319 NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2320 ret = GetLastError();
2321 if (mapping_modes[a1] & SEC_IMAGE)
2323 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
2324 ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
2326 else
2328 ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %x err %u\n", mapping_modes[a1], ret );
2330 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2332 CloseHandle( m );
2335 SetLastError(0xdeadbeef);
2336 h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0 );
2337 ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
2339 SetLastError(0xdeadbeef);
2340 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2341 ok( h2 == INVALID_HANDLE_VALUE, "CreateFileA should fail\n");
2342 ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error code %d\n", GetLastError() );
2344 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
2345 ok( h2 != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
2347 CloseHandle(h);
2348 CloseHandle(h2);
2350 DeleteFileA( filename );
2353 static char get_windows_drive(void)
2355 char windowsdir[MAX_PATH];
2356 GetWindowsDirectory(windowsdir, sizeof(windowsdir));
2357 return windowsdir[0];
2360 static void test_FindFirstFileA(void)
2362 HANDLE handle;
2363 WIN32_FIND_DATAA data;
2364 int err;
2365 char buffer[5] = "C:\\";
2366 char buffer2[100];
2367 char nonexistent[MAX_PATH];
2369 /* try FindFirstFileA on "C:\" */
2370 buffer[0] = get_windows_drive();
2372 SetLastError( 0xdeadbeaf );
2373 handle = FindFirstFileA(buffer, &data);
2374 err = GetLastError();
2375 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on root directory should fail\n" );
2376 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2378 /* try FindFirstFileA on "C:\*" */
2379 strcpy(buffer2, buffer);
2380 strcat(buffer2, "*");
2381 handle = FindFirstFileA(buffer2, &data);
2382 ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
2383 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2384 "FindFirstFile shouldn't return '%s' in drive root\n", data.cFileName );
2385 if (FindNextFileA( handle, &data ))
2386 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2387 "FindNextFile shouldn't return '%s' in drive root\n", data.cFileName );
2388 ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
2390 /* try FindFirstFileA on windows dir */
2391 GetWindowsDirectory( buffer2, sizeof(buffer2) );
2392 strcat(buffer2, "\\*");
2393 handle = FindFirstFileA(buffer2, &data);
2394 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
2395 ok( !strcmp( data.cFileName, "." ), "FindFirstFile should return '.' first\n" );
2396 ok( FindNextFileA( handle, &data ), "FindNextFile failed\n" );
2397 ok( !strcmp( data.cFileName, ".." ), "FindNextFile should return '..' as second entry\n" );
2398 while (FindNextFileA( handle, &data ))
2399 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2400 "FindNextFile shouldn't return '%s'\n", data.cFileName );
2401 ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
2403 /* try FindFirstFileA on "C:\foo\" */
2404 SetLastError( 0xdeadbeaf );
2405 if (!GetTempFileNameA( buffer, "foo", 0, nonexistent ) && GetLastError() == ERROR_ACCESS_DENIED)
2407 char tmp[MAX_PATH];
2408 GetTempPathA( sizeof(tmp), tmp );
2409 GetTempFileNameA( tmp, "foo", 0, nonexistent );
2411 DeleteFileA( nonexistent );
2412 strcpy(buffer2, nonexistent);
2413 strcat(buffer2, "\\");
2414 handle = FindFirstFileA(buffer2, &data);
2415 err = GetLastError();
2416 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2417 todo_wine {
2418 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2421 /* try FindFirstFileA on "C:\foo\bar.txt" */
2422 SetLastError( 0xdeadbeaf );
2423 strcpy(buffer2, nonexistent);
2424 strcat(buffer2, "\\bar.txt");
2425 handle = FindFirstFileA(buffer2, &data);
2426 err = GetLastError();
2427 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2428 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2430 /* try FindFirstFileA on "C:\foo\*.*" */
2431 SetLastError( 0xdeadbeaf );
2432 strcpy(buffer2, nonexistent);
2433 strcat(buffer2, "\\*.*");
2434 handle = FindFirstFileA(buffer2, &data);
2435 err = GetLastError();
2436 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2437 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2439 /* try FindFirstFileA on "foo\bar.txt" */
2440 SetLastError( 0xdeadbeaf );
2441 strcpy(buffer2, nonexistent + 3);
2442 strcat(buffer2, "\\bar.txt");
2443 handle = FindFirstFileA(buffer2, &data);
2444 err = GetLastError();
2445 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2446 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2448 /* try FindFirstFileA on "c:\nul" */
2449 SetLastError( 0xdeadbeaf );
2450 strcpy(buffer2, buffer);
2451 strcat(buffer2, "nul");
2452 handle = FindFirstFileA(buffer2, &data);
2453 err = GetLastError();
2454 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
2455 ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
2456 ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
2457 FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
2458 "wrong attributes %x\n", data.dwFileAttributes );
2459 if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
2461 ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
2462 ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
2464 SetLastError( 0xdeadbeaf );
2465 ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
2466 ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
2467 ok( FindClose( handle ), "failed to close handle\n" );
2469 /* try FindFirstFileA on "lpt1" */
2470 SetLastError( 0xdeadbeaf );
2471 strcpy(buffer2, "lpt1");
2472 handle = FindFirstFileA(buffer2, &data);
2473 err = GetLastError();
2474 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
2475 ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
2476 ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
2477 FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
2478 "wrong attributes %x\n", data.dwFileAttributes );
2479 if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
2481 ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
2482 ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
2484 SetLastError( 0xdeadbeaf );
2485 ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
2486 ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
2487 ok( FindClose( handle ), "failed to close handle\n" );
2489 /* try FindFirstFileA on "c:\nul\*" */
2490 SetLastError( 0xdeadbeaf );
2491 strcpy(buffer2, buffer);
2492 strcat(buffer2, "nul\\*");
2493 handle = FindFirstFileA(buffer2, &data);
2494 err = GetLastError();
2495 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2496 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2498 /* try FindFirstFileA on "c:\nul*" */
2499 SetLastError( 0xdeadbeaf );
2500 strcpy(buffer2, buffer);
2501 strcat(buffer2, "nul*");
2502 handle = FindFirstFileA(buffer2, &data);
2503 err = GetLastError();
2504 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2505 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2507 /* try FindFirstFileA on "c:\foo\bar\nul" */
2508 SetLastError( 0xdeadbeaf );
2509 strcpy(buffer2, buffer);
2510 strcat(buffer2, "foo\\bar\\nul");
2511 handle = FindFirstFileA(buffer2, &data);
2512 err = GetLastError();
2513 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2514 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2516 /* try FindFirstFileA on "c:\foo\nul\bar" */
2517 SetLastError( 0xdeadbeaf );
2518 strcpy(buffer2, buffer);
2519 strcat(buffer2, "foo\\nul\\bar");
2520 handle = FindFirstFileA(buffer2, &data);
2521 err = GetLastError();
2522 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
2523 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2526 static void test_FindNextFileA(void)
2528 HANDLE handle;
2529 WIN32_FIND_DATAA search_results;
2530 int err;
2531 char buffer[5] = "C:\\*";
2533 buffer[0] = get_windows_drive();
2534 handle = FindFirstFileA(buffer,&search_results);
2535 ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed\n" );
2536 while (FindNextFile(handle, &search_results))
2538 /* get to the end of the files */
2540 ok ( FindClose(handle) == TRUE, "Failed to close handle\n");
2541 err = GetLastError();
2542 ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES\n");
2545 static void test_FindFirstFileExA(FINDEX_SEARCH_OPS search_ops)
2547 WIN32_FIND_DATAA search_results;
2548 HANDLE handle;
2549 BOOL ret;
2551 if (!pFindFirstFileExA)
2553 win_skip("FindFirstFileExA() is missing\n");
2554 return;
2557 CreateDirectoryA("test-dir", NULL);
2558 _lclose(_lcreat("test-dir\\file1", 0));
2559 _lclose(_lcreat("test-dir\\file2", 0));
2560 CreateDirectoryA("test-dir\\dir1", NULL);
2561 SetLastError(0xdeadbeef);
2562 handle = pFindFirstFileExA("test-dir\\*", FindExInfoStandard, &search_results, search_ops, NULL, 0);
2563 if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2565 win_skip("FindFirstFileExA is not implemented\n");
2566 goto cleanup;
2568 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
2569 ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
2571 #define CHECK_NAME(fn) (strcmp((fn), "file1") == 0 || strcmp((fn), "file2") == 0 || strcmp((fn), "dir1") == 0)
2573 ok(FindNextFile(handle, &search_results), "Fetching second file failed\n");
2574 ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
2576 ok(FindNextFile(handle, &search_results), "Fetching third file failed\n");
2577 ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
2579 SetLastError(0xdeadbeef);
2580 ret = FindNextFile(handle, &search_results);
2581 if (!ret && (GetLastError() == ERROR_NO_MORE_FILES) && (search_ops == FindExSearchLimitToDirectories))
2583 skip("File system supports directory filtering\n");
2584 /* Results from the previous call are not cleared */
2585 ok(strcmp(search_results.cFileName, "dir1") == 0, "Third entry should be 'dir1' is %s\n", search_results.cFileName);
2586 FindClose( handle );
2587 goto cleanup;
2590 ok(ret, "Fetching fourth file failed\n");
2591 ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
2593 ok(FindNextFile(handle, &search_results), "Fetching fifth file failed\n");
2594 ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName);
2596 #undef CHECK_NAME
2598 ok(FindNextFile(handle, &search_results) == FALSE, "Fetching sixth file should fail\n");
2600 FindClose( handle );
2602 cleanup:
2603 DeleteFileA("test-dir\\file1");
2604 DeleteFileA("test-dir\\file2");
2605 RemoveDirectoryA("test-dir\\dir1");
2606 RemoveDirectoryA("test-dir");
2609 static int test_Mapfile_createtemp(HANDLE *handle)
2611 SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL);
2612 DeleteFile(filename);
2613 *handle = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, 0,
2614 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2615 if (*handle != INVALID_HANDLE_VALUE) {
2617 return 1;
2620 return 0;
2623 static void test_MapFile(void)
2625 HANDLE handle;
2626 HANDLE hmap;
2628 ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
2630 hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" );
2631 ok( hmap != NULL, "mapping should work, I named it!\n" );
2633 ok( CloseHandle( hmap ), "can't close mapping handle\n");
2635 /* We have to close file before we try new stuff with mapping again.
2636 Else we would always succeed on XP or block descriptors on 95. */
2637 hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
2638 ok( hmap != NULL, "We should still be able to map!\n" );
2639 ok( CloseHandle( hmap ), "can't close mapping handle\n");
2640 ok( CloseHandle( handle ), "can't close file handle\n");
2641 handle = NULL;
2643 ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
2645 hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
2646 ok( hmap == NULL, "mapped zero size file\n");
2647 ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
2649 hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
2650 ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
2651 /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
2652 if ( hmap )
2653 CloseHandle( hmap );
2655 hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
2656 ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
2657 /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
2658 if ( hmap )
2659 CloseHandle( hmap );
2661 /* On XP you can now map again, on Win 95 you cannot. */
2663 ok( CloseHandle( handle ), "can't close file handle\n");
2664 ok( DeleteFileA( filename ), "DeleteFile failed after map\n" );
2667 static void test_GetFileType(void)
2669 DWORD type;
2670 HANDLE h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2671 ok( h != INVALID_HANDLE_VALUE, "open %s failed\n", filename );
2672 type = GetFileType(h);
2673 ok( type == FILE_TYPE_DISK, "expected type disk got %d\n", type );
2674 CloseHandle( h );
2675 h = CreateFileA( "nul", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
2676 ok( h != INVALID_HANDLE_VALUE, "open nul failed\n" );
2677 type = GetFileType(h);
2678 ok( type == FILE_TYPE_CHAR, "expected type char for nul got %d\n", type );
2679 CloseHandle( h );
2680 DeleteFileA( filename );
2683 static int completion_count;
2685 static void CALLBACK FileIOComplete(DWORD dwError, DWORD dwBytes, LPOVERLAPPED ovl)
2687 /* printf("(%ld, %ld, %p { %ld, %ld, %ld, %ld, %p })\n", dwError, dwBytes, ovl, ovl->Internal, ovl->InternalHigh, ovl->Offset, ovl->OffsetHigh, ovl->hEvent);*/
2688 ReleaseSemaphore(ovl->hEvent, 1, NULL);
2689 completion_count++;
2692 static void test_async_file_errors(void)
2694 char szFile[MAX_PATH];
2695 HANDLE hSem = CreateSemaphoreW(NULL, 1, 1, NULL);
2696 HANDLE hFile;
2697 LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096);
2698 OVERLAPPED ovl;
2699 S(U(ovl)).Offset = 0;
2700 S(U(ovl)).OffsetHigh = 0;
2701 ovl.hEvent = hSem;
2702 completion_count = 0;
2703 szFile[0] = '\0';
2704 GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini"));
2705 strcat(szFile, "\\win.ini");
2706 hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2707 NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
2708 if (hFile == INVALID_HANDLE_VALUE) /* win9x doesn't like FILE_SHARE_DELETE */
2709 hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2710 NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
2711 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA(%s ...) failed\n", szFile);
2712 while (TRUE)
2714 BOOL res;
2715 DWORD count;
2716 while (WaitForSingleObjectEx(hSem, INFINITE, TRUE) == WAIT_IO_COMPLETION)
2718 res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete);
2719 /*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
2720 if (!res)
2721 break;
2722 if (!GetOverlappedResult(hFile, &ovl, &count, FALSE))
2723 break;
2724 S(U(ovl)).Offset += count;
2725 /* i/o completion routine only called if ReadFileEx returned success.
2726 * we only care about violations of this rule so undo what should have
2727 * been done */
2728 completion_count--;
2730 ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count);
2731 /*printf("Error = %ld\n", GetLastError());*/
2732 HeapFree(GetProcessHeap(), 0, lpBuffer);
2735 static BOOL user_apc_ran;
2736 static void CALLBACK user_apc(ULONG_PTR param)
2738 user_apc_ran = TRUE;
2741 static void test_read_write(void)
2743 DWORD bytes, ret, old_prot;
2744 HANDLE hFile;
2745 char temp_path[MAX_PATH];
2746 char filename[MAX_PATH];
2747 char *mem;
2748 static const char prefix[] = "pfx";
2750 ret = GetTempPathA(MAX_PATH, temp_path);
2751 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
2752 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
2754 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
2755 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
2757 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2758 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
2759 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
2761 user_apc_ran = FALSE;
2762 if (pQueueUserAPC) {
2763 trace("Queueing an user APC\n"); /* verify the file is non alerable */
2764 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
2765 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
2768 SetLastError(12345678);
2769 bytes = 12345678;
2770 ret = WriteFile(hFile, NULL, 0, &bytes, NULL);
2771 ok(ret && GetLastError() == 12345678,
2772 "ret = %d, error %d\n", ret, GetLastError());
2773 ok(!bytes, "bytes = %d\n", bytes);
2775 SetLastError(12345678);
2776 bytes = 12345678;
2777 ret = WriteFile(hFile, NULL, 10, &bytes, NULL);
2778 ok((!ret && GetLastError() == ERROR_INVALID_USER_BUFFER) || /* Win2k */
2779 (ret && GetLastError() == 12345678), /* Win9x */
2780 "ret = %d, error %d\n", ret, GetLastError());
2781 ok(!bytes || /* Win2k */
2782 bytes == 10, /* Win9x */
2783 "bytes = %d\n", bytes);
2785 /* make sure the file contains data */
2786 WriteFile(hFile, "this is the test data", 21, &bytes, NULL);
2787 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
2789 SetLastError(12345678);
2790 bytes = 12345678;
2791 ret = ReadFile(hFile, NULL, 0, &bytes, NULL);
2792 ok(ret && GetLastError() == 12345678,
2793 "ret = %d, error %d\n", ret, GetLastError());
2794 ok(!bytes, "bytes = %d\n", bytes);
2796 SetLastError(12345678);
2797 bytes = 12345678;
2798 ret = ReadFile(hFile, NULL, 10, &bytes, NULL);
2799 ok(!ret && (GetLastError() == ERROR_NOACCESS || /* Win2k */
2800 GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2801 "ret = %d, error %d\n", ret, GetLastError());
2802 ok(!bytes, "bytes = %d\n", bytes);
2804 ok(user_apc_ran == FALSE, "UserAPC ran, file using alertable io mode\n");
2805 if (pQueueUserAPC)
2806 SleepEx(0, TRUE); /* get rid of apc */
2808 /* test passing protected memory as buffer */
2810 mem = VirtualAlloc( NULL, 0x4000, MEM_COMMIT, PAGE_READWRITE );
2811 ok( mem != NULL, "failed to allocate virtual mem error %u\n", GetLastError() );
2813 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
2814 ok( ret, "WriteFile failed error %u\n", GetLastError() );
2815 ok( bytes == 0x4000, "only wrote %x bytes\n", bytes );
2817 ret = VirtualProtect( mem + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
2818 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
2820 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
2821 ok( !ret, "WriteFile succeeded\n" );
2822 ok( GetLastError() == ERROR_INVALID_USER_BUFFER ||
2823 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2824 "wrong error %u\n", GetLastError() );
2825 ok( bytes == 0, "wrote %x bytes\n", bytes );
2827 ret = WriteFile( (HANDLE)0xdead, mem, 0x4000, &bytes, NULL );
2828 ok( !ret, "WriteFile succeeded\n" );
2829 ok( GetLastError() == ERROR_INVALID_HANDLE || /* handle is checked before buffer on NT */
2830 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2831 "wrong error %u\n", GetLastError() );
2832 ok( bytes == 0, "wrote %x bytes\n", bytes );
2834 ret = VirtualProtect( mem, 0x2000, PAGE_NOACCESS, &old_prot );
2835 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
2837 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
2838 ok( !ret, "WriteFile succeeded\n" );
2839 ok( GetLastError() == ERROR_INVALID_USER_BUFFER ||
2840 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2841 "wrong error %u\n", GetLastError() );
2842 ok( bytes == 0, "wrote %x bytes\n", bytes );
2844 SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
2846 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
2847 ok( !ret, "ReadFile succeeded\n" );
2848 ok( GetLastError() == ERROR_NOACCESS ||
2849 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2850 "wrong error %u\n", GetLastError() );
2851 ok( bytes == 0, "read %x bytes\n", bytes );
2853 ret = VirtualProtect( mem, 0x2000, PAGE_READONLY, &old_prot );
2854 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
2856 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
2857 ok( !ret, "ReadFile succeeded\n" );
2858 ok( GetLastError() == ERROR_NOACCESS ||
2859 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2860 "wrong error %u\n", GetLastError() );
2861 ok( bytes == 0, "read %x bytes\n", bytes );
2863 ret = VirtualProtect( mem, 0x2000, PAGE_READWRITE, &old_prot );
2864 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
2866 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
2867 ok( !ret, "ReadFile succeeded\n" );
2868 ok( GetLastError() == ERROR_NOACCESS ||
2869 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2870 "wrong error %u\n", GetLastError() );
2871 ok( bytes == 0, "read %x bytes\n", bytes );
2873 SetFilePointer( hFile, 0x1234, NULL, FILE_BEGIN );
2874 SetEndOfFile( hFile );
2875 SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
2877 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
2878 ok( !ret, "ReadFile succeeded\n" );
2879 ok( GetLastError() == ERROR_NOACCESS ||
2880 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2881 "wrong error %u\n", GetLastError() );
2882 ok( bytes == 0, "read %x bytes\n", bytes );
2884 ret = ReadFile( hFile, mem, 0x2000, &bytes, NULL );
2885 ok( ret, "ReadFile failed error %u\n", GetLastError() );
2886 ok( bytes == 0x1234, "read %x bytes\n", bytes );
2888 ret = ReadFile( hFile, NULL, 1, &bytes, NULL );
2889 ok( !ret, "ReadFile succeeded\n" );
2890 ok( GetLastError() == ERROR_NOACCESS ||
2891 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
2892 "wrong error %u\n", GetLastError() );
2893 ok( bytes == 0, "read %x bytes\n", bytes );
2895 VirtualFree( mem, 0, MEM_FREE );
2897 ret = CloseHandle(hFile);
2898 ok( ret, "CloseHandle: error %d\n", GetLastError());
2899 ret = DeleteFileA(filename);
2900 ok( ret, "DeleteFileA: error %d\n", GetLastError());
2903 static void test_OpenFile(void)
2905 HFILE hFile;
2906 OFSTRUCT ofs;
2907 BOOL ret;
2908 DWORD retval;
2910 static const char file[] = "regedit.exe";
2911 static const char foo[] = ".\\foo-bar-foo.baz";
2912 static const char *foo_too_long = ".\\foo-bar-foo.baz+++++++++++++++"
2913 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
2914 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
2915 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
2916 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
2917 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
2918 char buff[MAX_PATH];
2919 char buff_long[4*MAX_PATH];
2920 char filled_0xA5[OFS_MAXPATHNAME];
2921 char *p;
2922 UINT length;
2924 /* Check for existing file */
2925 if (!pGetSystemWindowsDirectoryA)
2926 length = GetWindowsDirectoryA(buff, MAX_PATH);
2927 else
2928 length = pGetSystemWindowsDirectoryA(buff, MAX_PATH);
2930 if (length + sizeof(file) < MAX_PATH)
2932 p = buff + strlen(buff);
2933 if (p > buff && p[-1] != '\\') *p++ = '\\';
2934 strcpy( p, file );
2935 memset(&ofs, 0xA5, sizeof(ofs));
2936 SetLastError(0xfaceabee);
2938 hFile = OpenFile(buff, &ofs, OF_EXIST);
2939 ok( hFile == TRUE, "%s not found : %d\n", buff, GetLastError() );
2940 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
2941 "GetLastError() returns %d\n", GetLastError() );
2942 ok( ofs.cBytes == sizeof(ofs), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
2943 ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
2944 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
2945 "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n",
2946 ofs.szPathName, buff );
2949 memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
2950 length = GetCurrentDirectoryA(MAX_PATH, buff);
2952 /* Check for nonexistent file */
2953 if (length + sizeof(foo) < MAX_PATH)
2955 p = buff + strlen(buff);
2956 if (p > buff && p[-1] != '\\') *p++ = '\\';
2957 strcpy( p, foo + 2 );
2958 memset(&ofs, 0xA5, sizeof(ofs));
2959 SetLastError(0xfaceabee);
2961 hFile = OpenFile(foo, &ofs, OF_EXIST);
2962 ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
2963 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError() returns %d\n", GetLastError() );
2964 todo_wine
2965 ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
2966 ok( ofs.nErrCode == ERROR_FILE_NOT_FOUND, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
2967 ok( lstrcmpiA(ofs.szPathName, buff) == 0 || strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
2968 "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n",
2969 ofs.szPathName, buff );
2972 length = GetCurrentDirectoryA(MAX_PATH, buff_long);
2973 length += lstrlenA(foo_too_long + 1);
2975 /* Check for nonexistent file with too long filename */
2976 if (length >= OFS_MAXPATHNAME && length < sizeof(buff_long))
2978 lstrcatA(buff_long, foo_too_long + 1); /* Avoid '.' during concatenation */
2979 memset(&ofs, 0xA5, sizeof(ofs));
2980 SetLastError(0xfaceabee);
2982 hFile = OpenFile(foo_too_long, &ofs, OF_EXIST);
2983 ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
2984 ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_FILENAME_EXCED_RANGE,
2985 "GetLastError() returns %d\n", GetLastError() );
2986 todo_wine
2987 ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
2988 ok( ofs.nErrCode == ERROR_INVALID_DATA || ofs.nErrCode == ERROR_FILENAME_EXCED_RANGE,
2989 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
2990 ok( strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
2991 "OpenFile returned '%s', but was expected to return string filled with 0xA5\n",
2992 ofs.szPathName );
2995 length = GetCurrentDirectoryA(MAX_PATH, buff) + sizeof(filename);
2997 if (length >= MAX_PATH)
2999 trace("Buffer too small, requested length = %d, but MAX_PATH = %d. Skipping test.\n", length, MAX_PATH);
3000 return;
3002 p = buff + strlen(buff);
3003 if (p > buff && p[-1] != '\\') *p++ = '\\';
3004 strcpy( p, filename );
3006 memset(&ofs, 0xA5, sizeof(ofs));
3007 SetLastError(0xfaceabee);
3008 /* Create an empty file */
3009 hFile = OpenFile(filename, &ofs, OF_CREATE);
3010 ok( hFile != HFILE_ERROR, "OpenFile failed to create nonexistent file\n" );
3011 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3012 "GetLastError() returns %d\n", GetLastError() );
3013 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3014 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3015 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3016 ret = _lclose(hFile);
3017 ok( !ret, "_lclose() returns %d\n", ret );
3018 retval = GetFileAttributesA(filename);
3019 ok( retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %d\n", GetLastError() );
3021 memset(&ofs, 0xA5, sizeof(ofs));
3022 SetLastError(0xfaceabee);
3023 /* Check various opening options: */
3024 /* for reading only, */
3025 hFile = OpenFile(filename, &ofs, OF_READ);
3026 ok( hFile != HFILE_ERROR, "OpenFile failed on read\n" );
3027 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3028 "GetLastError() returns %d\n", GetLastError() );
3029 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3030 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3031 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3032 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3033 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3034 ret = _lclose(hFile);
3035 ok( !ret, "_lclose() returns %d\n", ret );
3037 memset(&ofs, 0xA5, sizeof(ofs));
3038 SetLastError(0xfaceabee);
3039 /* for writing only, */
3040 hFile = OpenFile(filename, &ofs, OF_WRITE);
3041 ok( hFile != HFILE_ERROR, "OpenFile failed on write\n" );
3042 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3043 "GetLastError() returns %d\n", GetLastError() );
3044 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3045 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3046 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3047 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3048 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3049 ret = _lclose(hFile);
3050 ok( !ret, "_lclose() returns %d\n", ret );
3052 memset(&ofs, 0xA5, sizeof(ofs));
3053 SetLastError(0xfaceabee);
3054 /* for reading and writing, */
3055 hFile = OpenFile(filename, &ofs, OF_READWRITE);
3056 ok( hFile != HFILE_ERROR, "OpenFile failed on read/write\n" );
3057 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3058 "GetLastError() returns %d\n", GetLastError() );
3059 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3060 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3061 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3062 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3063 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3064 ret = _lclose(hFile);
3065 ok( !ret, "_lclose() returns %d\n", ret );
3067 memset(&ofs, 0xA5, sizeof(ofs));
3068 SetLastError(0xfaceabee);
3069 /* for checking file presence. */
3070 hFile = OpenFile(filename, &ofs, OF_EXIST);
3071 ok( hFile == 1, "OpenFile failed on finding our created file\n" );
3072 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3073 "GetLastError() returns %d\n", GetLastError() );
3074 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3075 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3076 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3077 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3078 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3080 memset(&ofs, 0xA5, sizeof(ofs));
3081 SetLastError(0xfaceabee);
3082 /* Delete the file and make sure it doesn't exist anymore */
3083 hFile = OpenFile(filename, &ofs, OF_DELETE);
3084 ok( hFile == 1, "OpenFile failed on delete (%d)\n", hFile );
3085 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3086 "GetLastError() returns %d\n", GetLastError() );
3087 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3088 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3089 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3090 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3091 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3093 retval = GetFileAttributesA(filename);
3094 ok( retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file\n" );
3097 static void test_overlapped(void)
3099 OVERLAPPED ov;
3100 DWORD r, result;
3102 /* GetOverlappedResult crashes if the 2nd or 3rd param are NULL */
3103 if (0) /* tested: WinXP */
3105 GetOverlappedResult(0, NULL, &result, FALSE);
3106 GetOverlappedResult(0, &ov, NULL, FALSE);
3107 GetOverlappedResult(0, NULL, NULL, FALSE);
3110 memset( &ov, 0, sizeof ov );
3111 result = 1;
3112 r = GetOverlappedResult(0, &ov, &result, 0);
3113 if (r)
3114 ok( result == 0, "wrong result %u\n", result );
3115 else /* win9x */
3116 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3118 result = 0;
3119 ov.Internal = 0;
3120 ov.InternalHigh = 0xabcd;
3121 r = GetOverlappedResult(0, &ov, &result, 0);
3122 if (r)
3123 ok( result == 0xabcd, "wrong result %u\n", result );
3124 else /* win9x */
3125 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3127 SetLastError( 0xb00 );
3128 result = 0;
3129 ov.Internal = STATUS_INVALID_HANDLE;
3130 ov.InternalHigh = 0xabcd;
3131 r = GetOverlappedResult(0, &ov, &result, 0);
3132 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3133 ok( r == FALSE, "should return false\n");
3134 ok( result == 0xabcd || result == 0 /* win9x */, "wrong result %u\n", result );
3136 SetLastError( 0xb00 );
3137 result = 0;
3138 ov.Internal = STATUS_PENDING;
3139 ov.InternalHigh = 0xabcd;
3140 r = GetOverlappedResult(0, &ov, &result, 0);
3141 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
3142 "wrong error %u\n", GetLastError() );
3143 ok( r == FALSE, "should return false\n");
3144 ok( result == 0, "wrong result %u\n", result );
3146 SetLastError( 0xb00 );
3147 ov.hEvent = CreateEvent( NULL, 1, 1, NULL );
3148 ov.Internal = STATUS_PENDING;
3149 ov.InternalHigh = 0xabcd;
3150 r = GetOverlappedResult(0, &ov, &result, 0);
3151 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
3152 "wrong error %u\n", GetLastError() );
3153 ok( r == FALSE, "should return false\n");
3155 ResetEvent( ov.hEvent );
3157 SetLastError( 0xb00 );
3158 ov.Internal = STATUS_PENDING;
3159 ov.InternalHigh = 0;
3160 r = GetOverlappedResult(0, &ov, &result, 0);
3161 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
3162 "wrong error %u\n", GetLastError() );
3163 ok( r == FALSE, "should return false\n");
3165 r = CloseHandle( ov.hEvent );
3166 ok( r == TRUE, "close handle failed\n");
3169 static void test_RemoveDirectory(void)
3171 int rc;
3172 char directory[] = "removeme";
3174 rc = CreateDirectory(directory, NULL);
3175 ok( rc, "Createdirectory failed, gle=%d\n", GetLastError() );
3177 rc = SetCurrentDirectory(directory);
3178 ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
3180 rc = RemoveDirectory(".");
3181 if (!rc)
3183 rc = SetCurrentDirectory("..");
3184 ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
3186 rc = RemoveDirectory(directory);
3187 ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
3191 static BOOL check_file_time( const FILETIME *ft1, const FILETIME *ft2, UINT tolerance )
3193 ULONGLONG t1 = ((ULONGLONG)ft1->dwHighDateTime << 32) | ft1->dwLowDateTime;
3194 ULONGLONG t2 = ((ULONGLONG)ft2->dwHighDateTime << 32) | ft2->dwLowDateTime;
3195 return abs(t1 - t2) <= tolerance;
3198 static void test_ReplaceFileA(void)
3200 char replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
3201 HANDLE hReplacedFile, hReplacementFile, hBackupFile;
3202 static const char replacedData[] = "file-to-replace";
3203 static const char replacementData[] = "new-file";
3204 static const char backupData[] = "backup-file";
3205 FILETIME ftReplaced, ftReplacement, ftBackup;
3206 static const char prefix[] = "pfx";
3207 char temp_path[MAX_PATH];
3208 DWORD ret;
3209 BOOL retok, removeBackup = FALSE;
3211 if (!pReplaceFileA)
3213 win_skip("ReplaceFileA() is missing\n");
3214 return;
3217 ret = GetTempPathA(MAX_PATH, temp_path);
3218 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
3219 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
3221 ret = GetTempFileNameA(temp_path, prefix, 0, replaced);
3222 ok(ret != 0, "GetTempFileNameA error (replaced) %d\n", GetLastError());
3224 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3225 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3227 ret = GetTempFileNameA(temp_path, prefix, 0, backup);
3228 ok(ret != 0, "GetTempFileNameA error (backup) %d\n", GetLastError());
3230 /* place predictable data in the file to be replaced */
3231 hReplacedFile = CreateFileA(replaced, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3232 ok(hReplacedFile != INVALID_HANDLE_VALUE,
3233 "failed to open replaced file\n");
3234 retok = WriteFile(hReplacedFile, replacedData, sizeof(replacedData), &ret, NULL );
3235 ok( retok && ret == sizeof(replacedData),
3236 "WriteFile error (replaced) %d\n", GetLastError());
3237 ok(GetFileSize(hReplacedFile, NULL) == sizeof(replacedData),
3238 "replaced file has wrong size\n");
3239 /* place predictable data in the file to be the replacement */
3240 hReplacementFile = CreateFileA(replacement, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3241 ok(hReplacementFile != INVALID_HANDLE_VALUE,
3242 "failed to open replacement file\n");
3243 retok = WriteFile(hReplacementFile, replacementData, sizeof(replacementData), &ret, NULL );
3244 ok( retok && ret == sizeof(replacementData),
3245 "WriteFile error (replacement) %d\n", GetLastError());
3246 ok(GetFileSize(hReplacementFile, NULL) == sizeof(replacementData),
3247 "replacement file has wrong size\n");
3248 /* place predictable data in the backup file (to be over-written) */
3249 hBackupFile = CreateFileA(backup, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3250 ok(hBackupFile != INVALID_HANDLE_VALUE,
3251 "failed to open backup file\n");
3252 retok = WriteFile(hBackupFile, backupData, sizeof(backupData), &ret, NULL );
3253 ok( retok && ret == sizeof(backupData),
3254 "WriteFile error (replacement) %d\n", GetLastError());
3255 ok(GetFileSize(hBackupFile, NULL) == sizeof(backupData),
3256 "backup file has wrong size\n");
3257 /* change the filetime on the "replaced" file to ensure that it changes */
3258 ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3259 ok( ret, "GetFileTime error (replaced) %d\n", GetLastError());
3260 ftReplaced.dwLowDateTime -= 600000000; /* 60 second */
3261 ret = SetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3262 ok( ret, "SetFileTime error (replaced) %d\n", GetLastError());
3263 GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced); /* get the actual time back */
3264 CloseHandle(hReplacedFile);
3265 /* change the filetime on the backup to ensure that it changes */
3266 ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3267 ok( ret, "GetFileTime error (backup) %d\n", GetLastError());
3268 ftBackup.dwLowDateTime -= 1200000000; /* 120 second */
3269 ret = SetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3270 ok( ret, "SetFileTime error (backup) %d\n", GetLastError());
3271 GetFileTime(hBackupFile, NULL, NULL, &ftBackup); /* get the actual time back */
3272 CloseHandle(hBackupFile);
3273 /* get the filetime on the replacement file to perform checks */
3274 ret = GetFileTime(hReplacementFile, NULL, NULL, &ftReplacement);
3275 ok( ret, "GetFileTime error (replacement) %d\n", GetLastError());
3276 CloseHandle(hReplacementFile);
3278 /* perform replacement w/ backup
3279 * TODO: flags are not implemented
3281 SetLastError(0xdeadbeef);
3282 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3283 ok(ret, "ReplaceFileA: unexpected error %d\n", GetLastError());
3284 /* make sure that the backup has the size of the old "replaced" file */
3285 hBackupFile = CreateFileA(backup, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3286 ok(hBackupFile != INVALID_HANDLE_VALUE,
3287 "failed to open backup file\n");
3288 ret = GetFileSize(hBackupFile, NULL);
3289 ok(ret == sizeof(replacedData),
3290 "backup file has wrong size %d\n", ret);
3291 /* make sure that the "replaced" file has the size of the replacement file */
3292 hReplacedFile = CreateFileA(replaced, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3293 ok(hReplacedFile != INVALID_HANDLE_VALUE,
3294 "failed to open replaced file: %d\n", GetLastError());
3295 if (hReplacedFile != INVALID_HANDLE_VALUE)
3297 ret = GetFileSize(hReplacedFile, NULL);
3298 ok(ret == sizeof(replacementData),
3299 "replaced file has wrong size %d\n", ret);
3300 /* make sure that the replacement file no-longer exists */
3301 hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3302 ok(hReplacementFile == INVALID_HANDLE_VALUE,
3303 "unexpected error, replacement file should not exist %d\n", GetLastError());
3304 /* make sure that the backup has the old "replaced" filetime */
3305 ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3306 ok( ret, "GetFileTime error (backup %d\n", GetLastError());
3307 ok(check_file_time(&ftBackup, &ftReplaced, 20000000), "backup file has wrong filetime\n");
3308 CloseHandle(hBackupFile);
3309 /* make sure that the "replaced" has the old replacement filetime */
3310 ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3311 ok( ret, "GetFileTime error (backup %d\n", GetLastError());
3312 ok(check_file_time(&ftReplaced, &ftReplacement, 20000000),
3313 "replaced file has wrong filetime %x%08x / %x%08x\n",
3314 ftReplaced.dwHighDateTime, ftReplaced.dwLowDateTime,
3315 ftReplacement.dwHighDateTime, ftReplacement.dwLowDateTime );
3316 CloseHandle(hReplacedFile);
3318 else
3319 skip("couldn't open replacement file, skipping tests\n");
3321 /* re-create replacement file for pass w/o backup (blank) */
3322 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3323 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3324 /* perform replacement w/o backup
3325 * TODO: flags are not implemented
3327 SetLastError(0xdeadbeef);
3328 ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
3329 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3330 "ReplaceFileA: unexpected error %d\n", GetLastError());
3332 /* re-create replacement file for pass w/ backup (backup-file not existing) */
3333 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3334 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3335 ret = DeleteFileA(backup);
3336 ok(ret, "DeleteFileA: error (backup) %d\n", GetLastError());
3337 /* perform replacement w/ backup (no pre-existing backup)
3338 * TODO: flags are not implemented
3340 SetLastError(0xdeadbeef);
3341 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3342 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3343 "ReplaceFileA: unexpected error %d\n", GetLastError());
3344 if (ret)
3345 removeBackup = TRUE;
3347 /* re-create replacement file for pass w/ no permissions to "replaced" */
3348 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3349 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3350 ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_READONLY);
3351 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3352 "SetFileAttributesA: error setting to read only %d\n", GetLastError());
3353 /* perform replacement w/ backup (no permission to "replaced")
3354 * TODO: flags are not implemented
3356 SetLastError(0xdeadbeef);
3357 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3358 ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED, "ReplaceFileA: unexpected error %d\n", GetLastError());
3359 /* make sure that the replacement file still exists */
3360 hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3361 ok(hReplacementFile != INVALID_HANDLE_VALUE ||
3362 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* win2k */
3363 "unexpected error, replacement file should still exist %d\n", GetLastError());
3364 CloseHandle(hReplacementFile);
3365 ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_NORMAL);
3366 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3367 "SetFileAttributesA: error setting to normal %d\n", GetLastError());
3369 /* replacement file still exists, make pass w/o "replaced" */
3370 ret = DeleteFileA(replaced);
3371 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3372 "DeleteFileA: error (replaced) %d\n", GetLastError());
3373 /* perform replacement w/ backup (no pre-existing backup or "replaced")
3374 * TODO: flags are not implemented
3376 SetLastError(0xdeadbeef);
3377 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3378 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
3379 GetLastError() == ERROR_ACCESS_DENIED),
3380 "ReplaceFileA: unexpected error %d\n", GetLastError());
3382 /* perform replacement w/o existing "replacement" file
3383 * TODO: flags are not implemented
3385 SetLastError(0xdeadbeef);
3386 ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
3387 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
3388 GetLastError() == ERROR_ACCESS_DENIED),
3389 "ReplaceFileA: unexpected error %d\n", GetLastError());
3390 DeleteFileA( replacement );
3393 * if the first round (w/ backup) worked then as long as there is no
3394 * failure then there is no need to check this round (w/ backup is the
3395 * more complete case)
3398 /* delete temporary files, replacement and replaced are already deleted */
3399 if (removeBackup)
3401 ret = DeleteFileA(backup);
3402 ok(ret ||
3403 broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
3404 "DeleteFileA: error (backup) %d\n", GetLastError());
3409 * ReplaceFileW is a simpler case of ReplaceFileA, there is no
3410 * need to be as thorough.
3412 static void test_ReplaceFileW(void)
3414 WCHAR replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
3415 static const WCHAR prefix[] = {'p','f','x',0};
3416 WCHAR temp_path[MAX_PATH];
3417 DWORD ret;
3418 BOOL removeBackup = FALSE;
3420 if (!pReplaceFileW)
3422 win_skip("ReplaceFileW() is missing\n");
3423 return;
3426 ret = GetTempPathW(MAX_PATH, temp_path);
3427 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3429 win_skip("GetTempPathW is not available\n");
3430 return;
3432 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
3433 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
3435 ret = GetTempFileNameW(temp_path, prefix, 0, replaced);
3436 ok(ret != 0, "GetTempFileNameW error (replaced) %d\n", GetLastError());
3438 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3439 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3441 ret = GetTempFileNameW(temp_path, prefix, 0, backup);
3442 ok(ret != 0, "GetTempFileNameW error (backup) %d\n", GetLastError());
3444 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3445 ok(ret, "ReplaceFileW: error %d\n", GetLastError());
3447 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3448 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3449 ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0);
3450 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3451 "ReplaceFileW: error %d\n", GetLastError());
3453 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3454 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3455 ret = DeleteFileW(backup);
3456 ok(ret, "DeleteFileW: error (backup) %d\n", GetLastError());
3457 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3458 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3459 "ReplaceFileW: error %d\n", GetLastError());
3461 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3462 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3463 ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_READONLY);
3464 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3465 "SetFileAttributesW: error setting to read only %d\n", GetLastError());
3467 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3468 ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED,
3469 "ReplaceFileW: unexpected error %d\n", GetLastError());
3470 ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_NORMAL);
3471 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3472 "SetFileAttributesW: error setting to normal %d\n", GetLastError());
3473 if (ret)
3474 removeBackup = TRUE;
3476 ret = DeleteFileW(replaced);
3477 ok(ret, "DeleteFileW: error (replaced) %d\n", GetLastError());
3478 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3479 ok(!ret, "ReplaceFileW: error %d\n", GetLastError());
3481 ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0);
3482 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
3483 GetLastError() == ERROR_ACCESS_DENIED),
3484 "ReplaceFileW: unexpected error %d\n", GetLastError());
3485 DeleteFileW( replacement );
3487 if (removeBackup)
3489 ret = DeleteFileW(backup);
3490 ok(ret ||
3491 broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
3492 "DeleteFileW: error (backup) %d\n", GetLastError());
3496 static void test_CreateFile(void)
3498 static const struct test_data
3500 DWORD disposition, access, error, clean_up;
3501 } td[] =
3503 /* 0 */ { 0, 0, ERROR_INVALID_PARAMETER, 0 },
3504 /* 1 */ { 0, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 },
3505 /* 2 */ { 0, GENERIC_READ|GENERIC_WRITE, ERROR_INVALID_PARAMETER, 0 },
3506 /* 3 */ { CREATE_NEW, 0, ERROR_FILE_EXISTS, 1 },
3507 /* 4 */ { CREATE_NEW, 0, 0, 1 },
3508 /* 5 */ { CREATE_NEW, GENERIC_READ, 0, 1 },
3509 /* 6 */ { CREATE_NEW, GENERIC_WRITE, 0, 1 },
3510 /* 7 */ { CREATE_NEW, GENERIC_READ|GENERIC_WRITE, 0, 0 },
3511 /* 8 */ { CREATE_ALWAYS, 0, 0, 0 },
3512 /* 9 */ { CREATE_ALWAYS, GENERIC_READ, 0, 0 },
3513 /* 10*/ { CREATE_ALWAYS, GENERIC_WRITE, 0, 0 },
3514 /* 11*/ { CREATE_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 1 },
3515 /* 12*/ { OPEN_EXISTING, 0, ERROR_FILE_NOT_FOUND, 0 },
3516 /* 13*/ { CREATE_ALWAYS, 0, 0, 0 },
3517 /* 14*/ { OPEN_EXISTING, 0, 0, 0 },
3518 /* 15*/ { OPEN_EXISTING, GENERIC_READ, 0, 0 },
3519 /* 16*/ { OPEN_EXISTING, GENERIC_WRITE, 0, 0 },
3520 /* 17*/ { OPEN_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 1 },
3521 /* 18*/ { OPEN_ALWAYS, 0, 0, 0 },
3522 /* 19*/ { OPEN_ALWAYS, GENERIC_READ, 0, 0 },
3523 /* 20*/ { OPEN_ALWAYS, GENERIC_WRITE, 0, 0 },
3524 /* 21*/ { OPEN_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 0 },
3525 /* 22*/ { TRUNCATE_EXISTING, 0, ERROR_INVALID_PARAMETER, 0 },
3526 /* 23*/ { TRUNCATE_EXISTING, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 },
3527 /* 24*/ { TRUNCATE_EXISTING, GENERIC_WRITE, 0, 0 },
3528 /* 25*/ { TRUNCATE_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 0 }
3530 char temp_path[MAX_PATH];
3531 char file_name[MAX_PATH];
3532 DWORD i, ret, written;
3533 HANDLE hfile;
3535 GetTempPath(MAX_PATH, temp_path);
3536 GetTempFileName(temp_path, "tmp", 0, file_name);
3538 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3540 SetLastError(0xdeadbeef);
3541 hfile = CreateFile(file_name, td[i].access, 0, NULL, td[i].disposition, 0, 0);
3542 if (!td[i].error)
3544 ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
3545 written = 0xdeadbeef;
3546 SetLastError(0xdeadbeef);
3547 ret = WriteFile(hfile, &td[i].error, sizeof(td[i].error), &written, NULL);
3548 if (td[i].access & GENERIC_WRITE)
3549 ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
3550 else
3552 ok(!ret, "%d: WriteFile should fail\n", i);
3553 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3555 CloseHandle(hfile);
3557 else
3559 /* FIXME: remove the condition below once Wine is fixed */
3560 if (td[i].disposition == TRUNCATE_EXISTING && !(td[i].access & GENERIC_WRITE))
3562 todo_wine
3564 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
3565 ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError());
3567 CloseHandle(hfile);
3569 else
3571 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
3572 ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError());
3576 if (td[i].clean_up) DeleteFile(file_name);
3579 DeleteFile(file_name);
3582 static void test_GetFileInformationByHandleEx(void)
3584 int i;
3585 char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024];
3586 BOOL ret;
3587 DWORD ret2;
3588 HANDLE directory;
3589 FILE_ID_BOTH_DIR_INFO *bothDirInfo;
3590 struct {
3591 FILE_INFO_BY_HANDLE_CLASS handleClass;
3592 void *ptr;
3593 DWORD size;
3594 DWORD errorCode;
3595 } checks[] = {
3596 {0xdeadbeef, NULL, 0, ERROR_INVALID_PARAMETER},
3597 {FileIdBothDirectoryInfo, NULL, 0, ERROR_BAD_LENGTH},
3598 {FileIdBothDirectoryInfo, NULL, sizeof(buffer), ERROR_NOACCESS},
3599 {FileIdBothDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH}};
3601 if (!pGetFileInformationByHandleEx)
3603 win_skip("GetFileInformationByHandleEx is missing.\n");
3604 return;
3607 ret2 = GetTempPathA(sizeof(tempPath), tempPath);
3608 ok(ret2, "GetFileInformationByHandleEx: GetTempPathA failed, got error %u.\n", GetLastError());
3610 /* ensure the existence of a file in the temp folder */
3611 ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
3612 ok(ret2, "GetFileInformationByHandleEx: GetTempFileNameA failed, got error %u.\n", GetLastError());
3613 ret2 = GetFileAttributesA(tempFileName);
3614 ok(ret2 != INVALID_FILE_ATTRIBUTES, "GetFileInformationByHandleEx: "
3615 "GetFileAttributesA failed to find the temp file, got error %u.\n", GetLastError());
3617 directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3618 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
3619 ok(directory != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp folder, "
3620 "got error %u.\n", GetLastError());
3622 for (i = 0; i < sizeof(checks) / sizeof(checks[0]); i += 1)
3624 SetLastError(0xdeadbeef);
3625 ret = pGetFileInformationByHandleEx(directory, checks[i].handleClass, checks[i].ptr, checks[i].size);
3626 ok(!ret && GetLastError() == checks[i].errorCode, "GetFileInformationByHandleEx: expected error %u, "
3627 "got %u.\n", checks[i].errorCode, GetLastError());
3630 while (TRUE)
3632 memset(buffer, 0xff, sizeof(buffer));
3633 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
3634 if (!ret && GetLastError() == ERROR_NO_MORE_FILES)
3635 break;
3636 ok(ret, "GetFileInformationByHandleEx: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
3637 if (!ret)
3638 break;
3639 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
3640 while (TRUE)
3642 ok(bothDirInfo->FileAttributes != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file attributes.\n");
3643 ok(bothDirInfo->FileId.u.LowPart != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file id.\n");
3644 ok(bothDirInfo->FileNameLength != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file name length.\n");
3645 if (!bothDirInfo->NextEntryOffset)
3646 break;
3647 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
3651 CloseHandle(directory);
3652 DeleteFile(tempFileName);
3655 static void test_OpenFileById(void)
3657 char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[256], tickCount[256];
3658 WCHAR tempFileNameW[MAX_PATH];
3659 BOOL ret, found;
3660 DWORD ret2, count, tempFileNameLen;
3661 HANDLE directory, handle, tempFile;
3662 FILE_ID_BOTH_DIR_INFO *bothDirInfo;
3663 FILE_ID_DESCRIPTOR fileIdDescr;
3665 if (!pGetFileInformationByHandleEx || !pOpenFileById)
3667 win_skip("GetFileInformationByHandleEx or OpenFileById is missing.\n");
3668 return;
3671 ret2 = GetTempPathA(sizeof(tempPath), tempPath);
3672 ok(ret2, "OpenFileById: GetTempPath failed, got error %u.\n", GetLastError());
3674 /* ensure the existence of a file in the temp folder */
3675 ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
3676 ok(ret2, "OpenFileById: GetTempFileNameA failed, got error %u.\n", GetLastError());
3677 ret2 = GetFileAttributesA(tempFileName);
3678 ok(ret2 != INVALID_FILE_ATTRIBUTES,
3679 "OpenFileById: GetFileAttributesA failed to find the temp file, got error %u\n", GetLastError());
3681 ret2 = MultiByteToWideChar(CP_ACP, 0, tempFileName + strlen(tempPath), -1, tempFileNameW, sizeof(tempFileNameW)/sizeof(tempFileNameW[0]));
3682 ok(ret2, "OpenFileById: MultiByteToWideChar failed to convert tempFileName, got error %u.\n", GetLastError());
3683 tempFileNameLen = ret2 - 1;
3685 tempFile = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3686 ok(tempFile != INVALID_HANDLE_VALUE, "OpenFileById: failed to create a temp file, "
3687 "got error %u.\n", GetLastError());
3688 ret2 = sprintf(tickCount, "%u", GetTickCount());
3689 ret = WriteFile(tempFile, tickCount, ret2, &count, NULL);
3690 ok(ret, "OpenFileById: WriteFile failed, got error %u.\n", GetLastError());
3691 CloseHandle(tempFile);
3693 directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3694 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
3695 ok(directory != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder, "
3696 "got error %u.\n", GetLastError());
3698 /* get info about the temp folder itself */
3699 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
3700 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
3701 ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
3702 ok(bothDirInfo->FileNameLength == sizeof(WCHAR) && bothDirInfo->FileName[0] == '.',
3703 "OpenFileById: failed to return the temp folder at the first entry, got error %u.\n", GetLastError());
3705 /* open the temp folder itself */
3706 fileIdDescr.dwSize = sizeof(fileIdDescr);
3707 fileIdDescr.Type = FileIdType;
3708 U(fileIdDescr).FileId = bothDirInfo->FileId;
3709 handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
3710 todo_wine
3711 ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder itself, got error %u.\n", GetLastError());
3712 CloseHandle(handle);
3714 /* find the temp file in the temp folder */
3715 found = FALSE;
3716 while (!found)
3718 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
3719 ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
3720 if (!ret)
3721 break;
3722 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
3723 while (TRUE)
3725 if (tempFileNameLen == bothDirInfo->FileNameLength / sizeof(WCHAR) &&
3726 memcmp(tempFileNameW, bothDirInfo->FileName, bothDirInfo->FileNameLength) == 0)
3728 found = TRUE;
3729 break;
3731 if (!bothDirInfo->NextEntryOffset)
3732 break;
3733 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
3736 ok(found, "OpenFileById: failed to find the temp file in the temp folder.\n");
3738 SetLastError(0xdeadbeef);
3739 handle = pOpenFileById(directory, NULL, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
3740 ok(handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
3741 "OpenFileById: expected ERROR_INVALID_PARAMETER, got error %u.\n", GetLastError());
3743 fileIdDescr.dwSize = sizeof(fileIdDescr);
3744 fileIdDescr.Type = FileIdType;
3745 U(fileIdDescr).FileId = bothDirInfo->FileId;
3746 handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
3747 ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the file, got error %u.\n", GetLastError());
3749 ret = ReadFile(handle, buffer, sizeof(buffer), &count, NULL);
3750 buffer[count] = 0;
3751 ok(ret, "OpenFileById: ReadFile failed, got error %u.\n", GetLastError());
3752 ok(strcmp(tickCount, buffer) == 0, "OpenFileById: invalid contents of the temp file.\n");
3754 CloseHandle(handle);
3755 CloseHandle(directory);
3756 DeleteFile(tempFileName);
3759 static void test_SetFileValidData(void)
3761 BOOL ret;
3762 HANDLE handle;
3763 DWORD error, count;
3764 char path[MAX_PATH], filename[MAX_PATH];
3765 TOKEN_PRIVILEGES privs;
3766 HANDLE token = NULL;
3768 if (!pSetFileValidData)
3770 win_skip("SetFileValidData is missing\n");
3771 return;
3773 GetTempPathA(sizeof(path), path);
3774 GetTempFileNameA(path, "tst", 0, filename);
3775 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3776 WriteFile(handle, "test", sizeof("test") - 1, &count, NULL);
3777 CloseHandle(handle);
3779 SetLastError(0xdeadbeef);
3780 ret = pSetFileValidData(INVALID_HANDLE_VALUE, 0);
3781 error = GetLastError();
3782 ok(!ret, "SetFileValidData succeeded\n");
3783 ok(error == ERROR_INVALID_HANDLE, "got %u\n", error);
3785 SetLastError(0xdeadbeef);
3786 ret = pSetFileValidData(INVALID_HANDLE_VALUE, -1);
3787 error = GetLastError();
3788 ok(!ret, "SetFileValidData succeeded\n");
3789 ok(error == ERROR_INVALID_HANDLE, "got %u\n", error);
3791 /* file opened for reading */
3792 handle = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
3794 SetLastError(0xdeadbeef);
3795 ret = pSetFileValidData(handle, 0);
3796 ok(!ret, "SetFileValidData succeeded\n");
3797 error = GetLastError();
3798 ok(error == ERROR_ACCESS_DENIED, "got %u\n", error);
3800 SetLastError(0xdeadbeef);
3801 ret = pSetFileValidData(handle, -1);
3802 error = GetLastError();
3803 ok(!ret, "SetFileValidData succeeded\n");
3804 ok(error == ERROR_ACCESS_DENIED, "got %u\n", error);
3805 CloseHandle(handle);
3807 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3809 SetLastError(0xdeadbeef);
3810 ret = pSetFileValidData(handle, 0);
3811 error = GetLastError();
3812 ok(!ret, "SetFileValidData succeeded\n");
3813 todo_wine ok(error == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", error);
3814 CloseHandle(handle);
3816 privs.PrivilegeCount = 1;
3817 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
3819 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token) ||
3820 !LookupPrivilegeValue(NULL, SE_MANAGE_VOLUME_NAME, &privs.Privileges[0].Luid) ||
3821 !AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL) ||
3822 GetLastError() == ERROR_NOT_ALL_ASSIGNED)
3824 win_skip("cannot enable SE_MANAGE_VOLUME_NAME privilege\n");
3825 CloseHandle(token);
3826 return;
3828 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3830 SetLastError(0xdeadbeef);
3831 ret = pSetFileValidData(handle, 0);
3832 error = GetLastError();
3833 ok(!ret, "SetFileValidData succeeded\n");
3834 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
3836 SetLastError(0xdeadbeef);
3837 ret = pSetFileValidData(handle, -1);
3838 error = GetLastError();
3839 ok(!ret, "SetFileValidData succeeded\n");
3840 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
3842 SetLastError(0xdeadbeef);
3843 ret = pSetFileValidData(handle, 2);
3844 error = GetLastError();
3845 todo_wine ok(!ret, "SetFileValidData succeeded\n");
3846 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
3848 ret = pSetFileValidData(handle, 4);
3849 ok(ret, "SetFileValidData failed %u\n", GetLastError());
3851 SetLastError(0xdeadbeef);
3852 ret = pSetFileValidData(handle, 8);
3853 error = GetLastError();
3854 ok(!ret, "SetFileValidData succeeded\n");
3855 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
3857 count = SetFilePointer(handle, 1024, NULL, FILE_END);
3858 ok(count != INVALID_SET_FILE_POINTER, "SetFilePointer failed %u\n", GetLastError());
3859 ret = SetEndOfFile(handle);
3860 ok(ret, "SetEndOfFile failed %u\n", GetLastError());
3862 SetLastError(0xdeadbeef);
3863 ret = pSetFileValidData(handle, 2);
3864 error = GetLastError();
3865 todo_wine ok(!ret, "SetFileValidData succeeded\n");
3866 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
3868 ret = pSetFileValidData(handle, 4);
3869 ok(ret, "SetFileValidData failed %u\n", GetLastError());
3871 ret = pSetFileValidData(handle, 8);
3872 ok(ret, "SetFileValidData failed %u\n", GetLastError());
3874 ret = pSetFileValidData(handle, 4);
3875 error = GetLastError();
3876 todo_wine ok(!ret, "SetFileValidData succeeded\n");
3877 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
3879 ret = pSetFileValidData(handle, 1024);
3880 ok(ret, "SetFileValidData failed %u\n", GetLastError());
3882 ret = pSetFileValidData(handle, 2048);
3883 error = GetLastError();
3884 ok(!ret, "SetFileValidData succeeded\n");
3885 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
3887 privs.Privileges[0].Attributes = 0;
3888 AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL);
3889 CloseHandle(token);
3890 DeleteFile(filename);
3893 static unsigned file_map_access(unsigned access)
3895 if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
3896 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
3897 if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
3898 if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS;
3899 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
3902 static BOOL is_access_compatible(unsigned obj_access, unsigned desired_access)
3904 obj_access = file_map_access(obj_access);
3905 desired_access = file_map_access(desired_access);
3906 return (obj_access & desired_access) == desired_access;
3909 static void test_file_access(void)
3911 static const struct
3913 unsigned access, create_error, write_error, read_error;
3914 } td[] =
3916 { GENERIC_READ | GENERIC_WRITE, 0, 0, 0 },
3917 { GENERIC_WRITE, 0, 0, ERROR_ACCESS_DENIED },
3918 { GENERIC_READ, 0, ERROR_ACCESS_DENIED, 0 },
3919 { FILE_READ_DATA | FILE_WRITE_DATA, 0, 0, 0 },
3920 { FILE_WRITE_DATA, 0, 0, ERROR_ACCESS_DENIED },
3921 { FILE_READ_DATA, 0, ERROR_ACCESS_DENIED, 0 },
3922 { FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED },
3923 { FILE_READ_DATA | FILE_APPEND_DATA, 0, 0, 0 },
3924 { FILE_WRITE_DATA | FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED },
3925 { 0, 0, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED },
3927 char path[MAX_PATH], fname[MAX_PATH];
3928 unsigned char buf[16];
3929 HANDLE hfile, hdup;
3930 DWORD i, j, ret, bytes;
3932 GetTempPath(MAX_PATH, path);
3933 GetTempFileName(path, "foo", 0, fname);
3935 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3937 SetLastError(0xdeadbeef);
3938 hfile = CreateFile(fname, td[i].access, 0, NULL, CREATE_ALWAYS,
3939 FILE_FLAG_DELETE_ON_CLOSE, 0);
3940 if (td[i].create_error)
3942 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
3943 ok(td[i].create_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].create_error, GetLastError());
3944 continue;
3946 else
3947 ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
3949 for (j = 0; j < sizeof(td)/sizeof(td[0]); j++)
3951 SetLastError(0xdeadbeef);
3952 ret = DuplicateHandle(GetCurrentProcess(), hfile, GetCurrentProcess(), &hdup,
3953 td[j].access, 0, 0);
3954 if (is_access_compatible(td[i].access, td[j].access))
3955 ok(ret, "DuplicateHandle(%#x => %#x) error %d\n", td[i].access, td[j].access, GetLastError());
3956 else
3958 /* FIXME: Remove once Wine is fixed */
3959 if ((td[j].access & (GENERIC_READ | GENERIC_WRITE)) ||
3960 (!(td[i].access & (GENERIC_WRITE | FILE_WRITE_DATA)) && (td[j].access & FILE_WRITE_DATA)) ||
3961 (!(td[i].access & (GENERIC_READ | FILE_READ_DATA)) && (td[j].access & FILE_READ_DATA)) ||
3962 (!(td[i].access & (GENERIC_WRITE)) && (td[j].access & FILE_APPEND_DATA)))
3964 todo_wine
3965 ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access);
3966 todo_wine
3967 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3969 else
3971 ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access);
3972 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
3975 if (ret) CloseHandle(hdup);
3978 SetLastError(0xdeadbeef);
3979 bytes = 0xdeadbeef;
3980 ret = WriteFile(hfile, "\x5e\xa7", 2, &bytes, NULL);
3981 if (td[i].write_error)
3983 ok(!ret, "%d: WriteFile should fail\n", i);
3984 ok(td[i].write_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].write_error, GetLastError());
3985 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
3987 else
3989 ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
3990 ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes);
3993 SetLastError(0xdeadbeef);
3994 ret = SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3995 ok(ret != INVALID_SET_FILE_POINTER, "SetFilePointer error %d\n", GetLastError());
3997 SetLastError(0xdeadbeef);
3998 bytes = 0xdeadbeef;
3999 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4000 if (td[i].read_error)
4002 ok(!ret, "%d: ReadFile should fail\n", i);
4003 ok(td[i].read_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].read_error, GetLastError());
4004 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
4006 else
4008 ok(ret, "%d: ReadFile error %d\n", i, GetLastError());
4009 if (td[i].write_error)
4010 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
4011 else
4013 ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes);
4014 ok(buf[0] == 0x5e && buf[1] == 0xa7, "%d: expected 5ea7, got %02x%02x\n", i, buf[0], buf[1]);
4018 CloseHandle(hfile);
4022 START_TEST(file)
4024 InitFunctionPointers();
4026 test__hread( );
4027 test__hwrite( );
4028 test__lclose( );
4029 test__lcreat( );
4030 test__llseek( );
4031 test__llopen( );
4032 test__lread( );
4033 test__lwrite( );
4034 test_GetTempFileNameA();
4035 test_CopyFileA();
4036 test_CopyFileW();
4037 test_CopyFile2();
4038 test_CreateFile();
4039 test_CreateFileA();
4040 test_CreateFileW();
4041 test_CreateFile2();
4042 test_DeleteFileA();
4043 test_DeleteFileW();
4044 test_MoveFileA();
4045 test_MoveFileW();
4046 test_FindFirstFileA();
4047 test_FindNextFileA();
4048 test_FindFirstFileExA(0);
4049 /* FindExLimitToDirectories is ignored if the file system doesn't support directory filtering */
4050 test_FindFirstFileExA(FindExSearchLimitToDirectories);
4051 test_LockFile();
4052 test_file_sharing();
4053 test_offset_in_overlapped_structure();
4054 test_MapFile();
4055 test_GetFileType();
4056 test_async_file_errors();
4057 test_read_write();
4058 test_OpenFile();
4059 test_overlapped();
4060 test_RemoveDirectory();
4061 test_ReplaceFileA();
4062 test_ReplaceFileW();
4063 test_GetFileInformationByHandleEx();
4064 test_OpenFileById();
4065 test_SetFileValidData();
4066 test_file_access();