kernel32/tests: Add some more tests for opening a file with FILE_DELETE_ON_CLOSE.
[wine/multimedia.git] / dlls / kernel32 / tests / file.c
blob643054f628457df021b4d304bc6bf3988becea7a
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 "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "wine/test.h"
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winternl.h"
38 #include "winnls.h"
39 #include "fileapi.h"
41 #ifdef WINE_NO_UNICODE_MACROS
42 #undef DeleteFile /* needed for FILE_DISPOSITION_INFO */
43 #endif
45 static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD);
46 static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID);
47 static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID);
48 static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT);
49 static BOOL (WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
50 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
51 static BOOL (WINAPI *pGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD);
52 static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD);
53 static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
54 static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*);
55 static HANDLE (WINAPI *pCreateFile2)(LPCWSTR, DWORD, DWORD, DWORD, CREATEFILE2_EXTENDED_PARAMETERS*);
56 static DWORD (WINAPI *pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
57 static DWORD (WINAPI *pGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
58 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
59 PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
60 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR*);
61 static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
62 static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD);
64 static const char filename[] = "testfile.xxx";
65 static const char sillytext[] =
66 "en larvig liten text dx \033 gx hej 84 hej 4484 ! \001\033 bla bl\na.. bla bla."
67 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
68 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
69 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
70 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
71 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
72 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
73 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
74 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
75 "sdlkfjasdlkfj a dslkj adsklf \n \nasdklf askldfa sdlkf \nsadklf asdklf asdf ";
77 struct test_list {
78 const char *file; /* file string to test */
79 const DWORD err; /* Win NT and further error code */
80 const LONG err2; /* Win 9x & ME error code or -1 */
81 const DWORD options; /* option flag to use for open */
82 const BOOL todo_flag; /* todo_wine indicator */
83 } ;
85 static void InitFunctionPointers(void)
87 HMODULE hntdll = GetModuleHandleA("ntdll");
88 HMODULE hkernel32 = GetModuleHandleA("kernel32");
90 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
91 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
92 pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
94 pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA");
95 pReplaceFileA=(void*)GetProcAddress(hkernel32, "ReplaceFileA");
96 pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW");
97 pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA");
98 pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hkernel32, "GetVolumeNameForVolumeMountPointA");
99 pQueueUserAPC = (void *) GetProcAddress(hkernel32, "QueueUserAPC");
100 pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx");
101 pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById");
102 pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
103 pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2");
104 pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2");
105 pGetFinalPathNameByHandleA = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleA");
106 pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW");
107 pSetFileInformationByHandle = (void *) GetProcAddress(hkernel32, "SetFileInformationByHandle");
110 static void test__hread( void )
112 HFILE filehandle;
113 char buffer[10000];
114 LONG bytes_read;
115 LONG bytes_wanted;
116 LONG i;
117 BOOL ret;
119 SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL); /* be sure to remove stale files */
120 DeleteFileA( filename );
121 filehandle = _lcreat( filename, 0 );
122 if (filehandle == HFILE_ERROR)
124 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
125 return;
128 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
130 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
132 filehandle = _lopen( filename, OF_READ );
134 ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError( ) );
136 bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
138 ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
140 for (bytes_wanted = 0; bytes_wanted < lstrlenA( sillytext ); bytes_wanted++)
142 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
143 ok( _hread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
144 for (i = 0; i < bytes_wanted; i++)
146 ok( buffer[i] == sillytext[i], "that's not what's written\n" );
150 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
152 ret = DeleteFileA( filename );
153 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
157 static void test__hwrite( void )
159 HFILE filehandle;
160 char buffer[10000];
161 LONG bytes_read;
162 LONG bytes_written;
163 ULONG blocks;
164 LONG i;
165 char *contents;
166 HLOCAL memory_object;
167 char checksum[1];
168 BOOL ret;
170 filehandle = _lcreat( filename, 0 );
171 if (filehandle == HFILE_ERROR)
173 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
174 return;
177 ok( HFILE_ERROR != _hwrite( filehandle, "", 0 ), "_hwrite complains\n" );
179 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
181 filehandle = _lopen( filename, OF_READ );
183 bytes_read = _hread( filehandle, buffer, 1);
185 ok( 0 == bytes_read, "file read size error\n" );
187 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
189 filehandle = _lopen( filename, OF_READWRITE );
191 bytes_written = 0;
192 checksum[0] = '\0';
193 srand( (unsigned)time( NULL ) );
194 for (blocks = 0; blocks < 100; blocks++)
196 for (i = 0; i < (LONG)sizeof( buffer ); i++)
198 buffer[i] = rand( );
199 checksum[0] = checksum[0] + buffer[i];
201 ok( HFILE_ERROR != _hwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
202 bytes_written = bytes_written + sizeof( buffer );
205 ok( HFILE_ERROR != _hwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
206 bytes_written++;
208 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
210 memory_object = LocalAlloc( LPTR, bytes_written );
212 ok( 0 != memory_object, "LocalAlloc fails. (Could be out of memory.)\n" );
214 contents = LocalLock( memory_object );
215 ok( NULL != contents, "LocalLock whines\n" );
217 filehandle = _lopen( filename, OF_READ );
219 contents = LocalLock( memory_object );
220 ok( NULL != contents, "LocalLock whines\n" );
222 ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
224 checksum[0] = '\0';
225 i = 0;
228 checksum[0] = checksum[0] + contents[i];
229 i++;
231 while (i < bytes_written - 1);
233 ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
235 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
237 ret = DeleteFileA( filename );
238 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
240 LocalFree( contents );
244 static void test__lclose( void )
246 HFILE filehandle;
247 BOOL ret;
249 filehandle = _lcreat( filename, 0 );
250 if (filehandle == HFILE_ERROR)
252 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
253 return;
256 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
258 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
260 ret = DeleteFileA( filename );
261 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
264 /* helper function for test__lcreat */
265 static void get_nt_pathW( const char *name, UNICODE_STRING *nameW )
267 UNICODE_STRING strW;
268 ANSI_STRING str;
269 NTSTATUS status;
270 BOOLEAN ret;
271 RtlInitAnsiString( &str, name );
273 status = pRtlAnsiStringToUnicodeString( &strW, &str, TRUE );
274 ok( !status, "RtlAnsiStringToUnicodeString failed with %08x\n", status );
276 ret = pRtlDosPathNameToNtPathName_U( strW.Buffer, nameW, NULL, NULL );
277 ok( ret, "RtlDosPathNameToNtPathName_U failed\n" );
279 RtlFreeUnicodeString( &strW );
282 static void test__lcreat( void )
284 UNICODE_STRING filenameW;
285 OBJECT_ATTRIBUTES attr;
286 IO_STATUS_BLOCK io;
287 HFILE filehandle;
288 char buffer[10000];
289 WIN32_FIND_DATAA search_results;
290 char slashname[] = "testfi/";
291 int err;
292 HANDLE find, file;
293 NTSTATUS status;
294 BOOL ret;
296 filehandle = _lcreat( filename, 0 );
297 if (filehandle == HFILE_ERROR)
299 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
300 return;
303 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
305 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
307 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
309 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
311 find = FindFirstFileA( filename, &search_results );
312 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
313 FindClose( find );
315 ret = DeleteFileA(filename);
316 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError());
318 filehandle = _lcreat( filename, 1 ); /* readonly */
319 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
321 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write never the less\n" );
323 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
325 find = FindFirstFileA( filename, &search_results );
326 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
327 FindClose( find );
329 SetLastError( 0xdeadbeef );
330 ok( 0 == DeleteFileA( filename ), "shouldn't be able to delete a readonly file\n" );
331 ok( GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError() );
333 ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
335 ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file!\n" );
337 filehandle = _lcreat( filename, 1 ); /* readonly */
338 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError() );
339 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen(sillytext) ),
340 "_hwrite shouldn't be able to write never the less\n" );
341 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
343 find = FindFirstFileA( filename, &search_results );
344 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
345 FindClose( find );
347 get_nt_pathW( filename, &filenameW );
348 attr.Length = sizeof(attr);
349 attr.RootDirectory = 0;
350 attr.Attributes = OBJ_CASE_INSENSITIVE;
351 attr.ObjectName = &filenameW;
352 attr.SecurityDescriptor = NULL;
353 attr.SecurityQualityOfService = NULL;
355 status = NtCreateFile( &file, GENERIC_READ | GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
356 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
357 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
358 ok( status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %08x\n", status );
359 ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
361 status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
362 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
363 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
364 todo_wine
365 ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
366 if (!status) CloseHandle( file );
368 status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
369 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
370 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_DIRECTORY_FILE, NULL, 0 );
371 todo_wine
372 ok( status == STATUS_NOT_A_DIRECTORY, "expected STATUS_NOT_A_DIRECTORY, got %08x\n", status );
373 if (!status) CloseHandle( file );
375 status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
376 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
377 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
378 todo_wine
379 ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
380 if (!status) CloseHandle( file );
382 RtlFreeUnicodeString( &filenameW );
384 todo_wine
385 ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
386 todo_wine
387 ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
388 todo_wine
389 ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file\n" );
391 filehandle = _lcreat( filename, 2 );
392 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
394 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
396 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
398 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
400 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
402 find = FindFirstFileA( filename, &search_results );
403 ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" );
404 FindClose( find );
406 ret = DeleteFileA( filename );
407 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
409 filehandle = _lcreat( filename, 4 ); /* SYSTEM file */
410 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
412 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
414 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
416 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
418 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
420 find = FindFirstFileA( filename, &search_results );
421 ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" );
422 FindClose( find );
424 ret = DeleteFileA( filename );
425 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
427 filehandle=_lcreat (slashname, 0); /* illegal name */
428 if (HFILE_ERROR==filehandle) {
429 err=GetLastError ();
430 ok (err==ERROR_INVALID_NAME || err==ERROR_PATH_NOT_FOUND,
431 "creating file \"%s\" failed with error %d\n", slashname, err);
432 } else { /* only NT succeeds */
433 _lclose(filehandle);
434 find=FindFirstFileA (slashname, &search_results);
435 if (INVALID_HANDLE_VALUE!=find)
437 ret = FindClose (find);
438 ok (0 != ret, "FindClose complains (%d)\n", GetLastError ());
439 slashname[strlen(slashname)-1]=0;
440 ok (!strcmp (slashname, search_results.cFileName),
441 "found unexpected name \"%s\"\n", search_results.cFileName);
442 ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
443 "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
444 search_results.dwFileAttributes);
446 ret = DeleteFileA( slashname );
447 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
450 filehandle=_lcreat (filename, 8); /* illegal attribute */
451 if (HFILE_ERROR==filehandle)
452 ok (0, "couldn't create volume label \"%s\"\n", filename);
453 else {
454 _lclose(filehandle);
455 find=FindFirstFileA (filename, &search_results);
456 if (INVALID_HANDLE_VALUE==find)
457 ok (0, "file \"%s\" not found\n", filename);
458 else {
459 ret = FindClose(find);
460 ok ( 0 != ret, "FindClose complains (%d)\n", GetLastError ());
461 ok (!strcmp (filename, search_results.cFileName),
462 "found unexpected name \"%s\"\n", search_results.cFileName);
463 search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
464 ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
465 "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
466 search_results.dwFileAttributes);
468 ret = DeleteFileA( filename );
469 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
474 static void test__llseek( void )
476 INT i;
477 HFILE filehandle;
478 char buffer[1];
479 LONG bytes_read;
480 BOOL ret;
482 filehandle = _lcreat( filename, 0 );
483 if (filehandle == HFILE_ERROR)
485 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
486 return;
489 for (i = 0; i < 400; i++)
491 ok( _hwrite( filehandle, sillytext, strlen( sillytext ) ) != -1, "_hwrite complains\n" );
493 ok( _llseek( filehandle, 400 * strlen( sillytext ), FILE_CURRENT ) != -1, "should be able to seek\n" );
494 ok( _llseek( filehandle, 27 + 35 * strlen( sillytext ), FILE_BEGIN ) != -1, "should be able to seek\n" );
496 bytes_read = _hread( filehandle, buffer, 1);
497 ok( 1 == bytes_read, "file read size error\n" );
498 ok( buffer[0] == sillytext[27], "_llseek error, it got lost seeking\n" );
499 ok( _llseek( filehandle, -400 * (LONG)strlen( sillytext ), FILE_END ) != -1, "should be able to seek\n" );
501 bytes_read = _hread( filehandle, buffer, 1);
502 ok( 1 == bytes_read, "file read size error\n" );
503 ok( buffer[0] == sillytext[0], "_llseek error, it got lost seeking\n" );
504 ok( _llseek( filehandle, 1000000, FILE_END ) != -1, "should be able to seek past file; poor, poor Windows programmers\n" );
505 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
507 ret = DeleteFileA( filename );
508 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
512 static void test__llopen( void )
514 HFILE filehandle;
515 UINT bytes_read;
516 char buffer[10000];
517 BOOL ret;
519 filehandle = _lcreat( filename, 0 );
520 if (filehandle == HFILE_ERROR)
522 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
523 return;
526 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
527 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
529 filehandle = _lopen( filename, OF_READ );
530 ok( HFILE_ERROR == _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write!\n" );
531 bytes_read = _hread( filehandle, buffer, strlen( sillytext ) );
532 ok( strlen( sillytext ) == bytes_read, "file read size error\n" );
533 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
535 filehandle = _lopen( filename, OF_READWRITE );
536 bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
537 ok( strlen( sillytext ) == bytes_read, "file read size error\n" );
538 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
539 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
541 filehandle = _lopen( filename, OF_WRITE );
542 ok( HFILE_ERROR == _hread( filehandle, buffer, 1 ), "you should only be able to write this file\n" );
543 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
544 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
546 ret = DeleteFileA( filename );
547 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
548 /* TODO - add tests for the SHARE modes - use two processes to pull this one off */
552 static void test__lread( void )
554 HFILE filehandle;
555 char buffer[10000];
556 UINT bytes_read;
557 UINT bytes_wanted;
558 UINT i;
559 BOOL ret;
561 filehandle = _lcreat( filename, 0 );
562 if (filehandle == HFILE_ERROR)
564 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
565 return;
568 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
570 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
572 filehandle = _lopen( filename, OF_READ );
574 ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError());
576 bytes_read = _lread( filehandle, buffer, 2 * strlen( sillytext ) );
578 ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
580 for (bytes_wanted = 0; bytes_wanted < strlen( sillytext ); bytes_wanted++)
582 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
583 ok( _lread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
584 for (i = 0; i < bytes_wanted; i++)
586 ok( buffer[i] == sillytext[i], "that's not what's written\n" );
590 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
592 ret = DeleteFileA( filename );
593 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
597 static void test__lwrite( void )
599 HFILE filehandle;
600 char buffer[10000];
601 UINT bytes_read;
602 UINT bytes_written;
603 UINT blocks;
604 INT i;
605 char *contents;
606 HLOCAL memory_object;
607 char checksum[1];
608 BOOL ret;
610 filehandle = _lcreat( filename, 0 );
611 if (filehandle == HFILE_ERROR)
613 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
614 return;
617 ok( HFILE_ERROR != _lwrite( filehandle, "", 0 ), "_hwrite complains\n" );
619 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
621 filehandle = _lopen( filename, OF_READ );
623 bytes_read = _hread( filehandle, buffer, 1);
625 ok( 0 == bytes_read, "file read size error\n" );
627 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
629 filehandle = _lopen( filename, OF_READWRITE );
631 bytes_written = 0;
632 checksum[0] = '\0';
633 srand( (unsigned)time( NULL ) );
634 for (blocks = 0; blocks < 100; blocks++)
636 for (i = 0; i < (INT)sizeof( buffer ); i++)
638 buffer[i] = rand( );
639 checksum[0] = checksum[0] + buffer[i];
641 ok( HFILE_ERROR != _lwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
642 bytes_written = bytes_written + sizeof( buffer );
645 ok( HFILE_ERROR != _lwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
646 bytes_written++;
648 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
650 memory_object = LocalAlloc( LPTR, bytes_written );
652 ok( 0 != memory_object, "LocalAlloc fails, could be out of memory\n" );
654 contents = LocalLock( memory_object );
655 ok( NULL != contents, "LocalLock whines\n" );
657 filehandle = _lopen( filename, OF_READ );
659 contents = LocalLock( memory_object );
660 ok( NULL != contents, "LocalLock whines\n" );
662 ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
664 checksum[0] = '\0';
665 i = 0;
668 checksum[0] += contents[i];
669 i++;
671 while (i < bytes_written - 1);
673 ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
675 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
677 ret = DeleteFileA( filename );
678 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
680 LocalFree( contents );
683 static void test_CopyFileA(void)
685 char temp_path[MAX_PATH];
686 char source[MAX_PATH], dest[MAX_PATH];
687 static const char prefix[] = "pfx";
688 HANDLE hfile;
689 HANDLE hmapfile;
690 FILETIME ft1, ft2;
691 char buf[10];
692 DWORD ret;
693 BOOL retok;
695 ret = GetTempPathA(MAX_PATH, temp_path);
696 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
697 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
699 ret = GetTempFileNameA(temp_path, prefix, 0, source);
700 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
702 ret = MoveFileA(source, source);
703 todo_wine ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
705 /* copying a file to itself must fail */
706 retok = CopyFileA(source, source, FALSE);
707 ok( !retok && (GetLastError() == ERROR_SHARING_VIOLATION || broken(GetLastError() == ERROR_FILE_EXISTS) /* Win 9x */),
708 "copying a file to itself didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
710 /* make the source have not zero size */
711 hfile = CreateFileA(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
712 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
713 retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL );
714 ok( retok && ret == sizeof(prefix),
715 "WriteFile error %d\n", GetLastError());
716 ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
717 /* get the file time and change it to prove the difference */
718 ret = GetFileTime(hfile, NULL, NULL, &ft1);
719 ok( ret, "GetFileTime error %d\n", GetLastError());
720 ft1.dwLowDateTime -= 600000000; /* 60 second */
721 ret = SetFileTime(hfile, NULL, NULL, &ft1);
722 ok( ret, "SetFileTime error %d\n", GetLastError());
723 GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */
724 CloseHandle(hfile);
726 ret = GetTempFileNameA(temp_path, prefix, 0, dest);
727 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
729 SetLastError(0xdeadbeef);
730 ret = CopyFileA(source, dest, TRUE);
731 ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
732 "CopyFileA: unexpected error %d\n", GetLastError());
734 ret = CopyFileA(source, dest, FALSE);
735 ok(ret, "CopyFileA: error %d\n", GetLastError());
737 /* copying from a read-locked source fails */
738 hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
739 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
740 retok = CopyFileA(source, dest, FALSE);
741 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
742 "copying from a read-locked file succeeded when it shouldn't have\n");
743 /* in addition, the source is opened before the destination */
744 retok = CopyFileA("25f99d3b-4ba4-4f66-88f5-2906886993cc", dest, FALSE);
745 ok(!retok && GetLastError() == ERROR_FILE_NOT_FOUND,
746 "copying from a file that doesn't exist failed in an unexpected way (ret=%d, err=%d)\n", retok, GetLastError());
747 CloseHandle(hfile);
749 /* copying from a r+w opened, r shared source succeeds */
750 hfile = CreateFileA(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
751 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
752 retok = CopyFileA(source, dest, FALSE);
753 ok(retok,
754 "copying from an r+w opened and r shared file failed (ret=%d, err=%d)\n", retok, GetLastError());
755 CloseHandle(hfile);
757 /* copying from a delete-locked source mostly succeeds */
758 hfile = CreateFileA(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
759 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
760 retok = CopyFileA(source, dest, FALSE);
761 ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* NT, 2000, XP */,
762 "copying from a delete-locked file failed (ret=%d, err=%d)\n", retok, GetLastError());
763 CloseHandle(hfile);
765 /* copying to a write-locked destination fails */
766 hfile = CreateFileA(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
767 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
768 retok = CopyFileA(source, dest, FALSE);
769 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
770 "copying to a write-locked file didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
771 CloseHandle(hfile);
773 /* copying to a r+w opened, w shared destination mostly succeeds */
774 hfile = CreateFileA(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
775 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
776 retok = CopyFileA(source, dest, FALSE);
777 ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */,
778 "copying to a r+w opened and w shared file failed (ret=%d, err=%d)\n", retok, GetLastError());
779 CloseHandle(hfile);
781 /* copying to a delete-locked destination fails, even when the destination is delete-shared */
782 hfile = CreateFileA(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0);
783 ok(hfile != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* Win 9x */,
784 "failed to open destination file, error %d\n", GetLastError());
785 if (hfile != INVALID_HANDLE_VALUE)
787 retok = CopyFileA(source, dest, FALSE);
788 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
789 "copying to a delete-locked shared file didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
790 CloseHandle(hfile);
793 /* copy to a file that's opened the way Wine opens the source */
794 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
795 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
796 retok = CopyFileA(source, dest, FALSE);
797 ok(retok || broken(GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */,
798 "copying to a file opened the way Wine opens the source failed (ret=%d, err=%d)\n", retok, GetLastError());
799 CloseHandle(hfile);
801 /* make sure that destination has correct size */
802 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
803 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
804 ret = GetFileSize(hfile, NULL);
805 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
807 /* make sure that destination has the same filetime */
808 ret = GetFileTime(hfile, NULL, NULL, &ft2);
809 ok( ret, "GetFileTime error %d\n", GetLastError());
810 ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
812 SetLastError(0xdeadbeef);
813 ret = CopyFileA(source, dest, FALSE);
814 ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION,
815 "CopyFileA: ret = %d, unexpected error %d\n", ret, GetLastError());
817 /* make sure that destination still has correct size */
818 ret = GetFileSize(hfile, NULL);
819 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
820 retok = ReadFile(hfile, buf, sizeof(buf), &ret, NULL);
821 ok( retok && ret == sizeof(prefix),
822 "ReadFile: error %d\n", GetLastError());
823 ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
825 /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
826 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
827 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
829 ret = CopyFileA(source, dest, FALSE);
830 ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION,
831 "CopyFileA with mapped dest file: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
833 CloseHandle(hmapfile);
834 CloseHandle(hfile);
836 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
837 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
839 /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
840 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
841 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
843 ret = CopyFileA(source, dest, FALSE);
844 ok(!ret, "CopyFileA: expected failure\n");
845 ok(GetLastError() == ERROR_USER_MAPPED_FILE ||
846 broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x */
847 "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
849 CloseHandle(hmapfile);
850 CloseHandle(hfile);
852 ret = DeleteFileA(source);
853 ok(ret, "DeleteFileA: error %d\n", GetLastError());
854 ret = DeleteFileA(dest);
855 ok(ret, "DeleteFileA: error %d\n", GetLastError());
858 static void test_CopyFileW(void)
860 WCHAR temp_path[MAX_PATH];
861 WCHAR source[MAX_PATH], dest[MAX_PATH];
862 static const WCHAR prefix[] = {'p','f','x',0};
863 DWORD ret;
865 ret = GetTempPathW(MAX_PATH, temp_path);
866 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
868 win_skip("GetTempPathW is not available\n");
869 return;
871 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
872 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
874 ret = GetTempFileNameW(temp_path, prefix, 0, source);
875 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
877 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
878 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
880 ret = CopyFileW(source, dest, TRUE);
881 ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
882 "CopyFileW: unexpected error %d\n", GetLastError());
884 ret = CopyFileW(source, dest, FALSE);
885 ok(ret, "CopyFileW: error %d\n", GetLastError());
887 ret = DeleteFileW(source);
888 ok(ret, "DeleteFileW: error %d\n", GetLastError());
889 ret = DeleteFileW(dest);
890 ok(ret, "DeleteFileW: error %d\n", GetLastError());
893 static void test_CopyFile2(void)
895 static const WCHAR doesntexistW[] = {'d','o','e','s','n','t','e','x','i','s','t',0};
896 static const WCHAR prefix[] = {'p','f','x',0};
897 WCHAR source[MAX_PATH], dest[MAX_PATH], temp_path[MAX_PATH];
898 COPYFILE2_EXTENDED_PARAMETERS params;
899 HANDLE hfile, hmapfile;
900 FILETIME ft1, ft2;
901 DWORD ret, len;
902 char buf[10];
903 HRESULT hr;
905 if (!pCopyFile2)
907 skip("CopyFile2 is not available\n");
908 return;
911 ret = GetTempPathW(MAX_PATH, temp_path);
912 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
913 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
915 ret = GetTempFileNameW(temp_path, prefix, 0, source);
916 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
918 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
919 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
921 /* fail if exists */
922 memset(&params, 0, sizeof(params));
923 params.dwSize = sizeof(params);
924 params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
926 SetLastError(0xdeadbeef);
927 hr = pCopyFile2(source, dest, &params);
928 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
929 ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
931 /* don't fail if exists */
932 params.dwSize = sizeof(params);
933 params.dwCopyFlags = 0;
935 hr = pCopyFile2(source, dest, &params);
936 ok(hr == S_OK, "CopyFile2: error 0x%08x\n", hr);
938 /* copying a file to itself must fail */
939 params.dwSize = sizeof(params);
940 params.dwCopyFlags = 0;
942 SetLastError(0xdeadbeef);
943 hr = pCopyFile2(source, source, &params);
944 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: copying a file to itself didn't fail, 0x%08x\n", hr);
945 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
947 /* make the source have not zero size */
948 hfile = CreateFileW(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
949 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
950 ret = WriteFile(hfile, prefix, sizeof(prefix), &len, NULL );
951 ok(ret && len == sizeof(prefix), "WriteFile error %d\n", GetLastError());
952 ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
954 /* get the file time and change it to prove the difference */
955 ret = GetFileTime(hfile, NULL, NULL, &ft1);
956 ok(ret, "GetFileTime error %d\n", GetLastError());
957 ft1.dwLowDateTime -= 600000000; /* 60 second */
958 ret = SetFileTime(hfile, NULL, NULL, &ft1);
959 ok(ret, "SetFileTime error %d\n", GetLastError());
960 GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */
961 CloseHandle(hfile);
963 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
964 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
966 params.dwSize = sizeof(params);
967 params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
969 SetLastError(0xdeadbeef);
970 hr = pCopyFile2(source, dest, &params);
971 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
972 ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
974 params.dwSize = sizeof(params);
975 params.dwCopyFlags = 0;
976 hr = pCopyFile2(source, dest, &params);
977 ok(ret, "CopyFile2: error 0x%08x\n", hr);
979 /* copying from a read-locked source fails */
980 hfile = CreateFileW(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
981 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
983 params.dwSize = sizeof(params);
984 params.dwCopyFlags = 0;
985 SetLastError(0xdeadbeef);
986 hr = pCopyFile2(source, dest, &params);
987 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
988 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
990 /* in addition, the source is opened before the destination */
991 params.dwSize = sizeof(params);
992 params.dwCopyFlags = 0;
993 SetLastError(0xdeadbeef);
994 hr = pCopyFile2(doesntexistW, dest, &params);
995 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
996 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "CopyFile2: last error %d\n", GetLastError());
997 CloseHandle(hfile);
999 /* copying from a r+w opened, r shared source succeeds */
1000 hfile = CreateFileW(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1001 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
1003 params.dwSize = sizeof(params);
1004 params.dwCopyFlags = 0;
1005 hr = pCopyFile2(source, dest, &params);
1006 ok(hr == S_OK, "failed 0x%08x\n", hr);
1007 CloseHandle(hfile);
1009 /* copying from a delete-locked source mostly succeeds */
1010 hfile = CreateFileW(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1011 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
1013 params.dwSize = sizeof(params);
1014 params.dwCopyFlags = 0;
1015 hr = pCopyFile2(source, dest, &params);
1016 ok(hr == S_OK, "failed 0x%08x\n", hr);
1017 CloseHandle(hfile);
1019 /* copying to a write-locked destination fails */
1020 hfile = CreateFileW(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1021 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1023 params.dwSize = sizeof(params);
1024 params.dwCopyFlags = 0;
1025 SetLastError(0xdeadbeef);
1026 hr = pCopyFile2(source, dest, FALSE);
1027 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1028 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1029 CloseHandle(hfile);
1031 /* copying to a r+w opened, w shared destination mostly succeeds */
1032 hfile = CreateFileW(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
1033 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1035 params.dwSize = sizeof(params);
1036 params.dwCopyFlags = 0;
1037 hr = pCopyFile2(source, dest, FALSE);
1038 ok(hr == S_OK, "got 0x%08x\n", hr);
1039 CloseHandle(hfile);
1041 /* copying to a delete-locked destination fails, even when the destination is delete-shared */
1042 hfile = CreateFileW(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0);
1043 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1045 params.dwSize = sizeof(params);
1046 params.dwCopyFlags = 0;
1047 SetLastError(0xdeadbeef);
1048 hr = pCopyFile2(source, dest, &params);
1049 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1050 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1051 CloseHandle(hfile);
1053 /* copy to a file that's opened the way Wine opens the source */
1054 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
1055 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1057 params.dwSize = sizeof(params);
1058 params.dwCopyFlags = 0;
1059 hr = pCopyFile2(source, dest, &params);
1060 ok(hr == S_OK, "got 0x%08x\n", hr);
1061 CloseHandle(hfile);
1063 /* make sure that destination has correct size */
1064 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1065 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
1066 ret = GetFileSize(hfile, NULL);
1067 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
1069 /* make sure that destination has the same filetime */
1070 ret = GetFileTime(hfile, NULL, NULL, &ft2);
1071 ok(ret, "GetFileTime error %d\n", GetLastError());
1072 ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
1074 params.dwSize = sizeof(params);
1075 params.dwCopyFlags = 0;
1076 SetLastError(0xdeadbeef);
1077 hr = pCopyFile2(source, dest, &params);
1078 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1079 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1081 /* make sure that destination still has correct size */
1082 ret = GetFileSize(hfile, NULL);
1083 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
1084 ret = ReadFile(hfile, buf, sizeof(buf), &len, NULL);
1085 ok(ret && len == sizeof(prefix), "ReadFile: error %d\n", GetLastError());
1086 ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
1088 /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
1089 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1090 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1092 params.dwSize = sizeof(params);
1093 params.dwCopyFlags = 0;
1094 SetLastError(0xdeadbeef);
1095 hr = pCopyFile2(source, dest, &params);
1096 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1097 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1099 CloseHandle(hmapfile);
1100 CloseHandle(hfile);
1102 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
1103 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
1105 /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
1106 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1107 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1109 params.dwSize = sizeof(params);
1110 params.dwCopyFlags = 0;
1111 hr = pCopyFile2(source, dest, &params);
1112 ok(hr == HRESULT_FROM_WIN32(ERROR_USER_MAPPED_FILE), "CopyFile2: unexpected error 0x%08x\n", hr);
1113 ok(GetLastError() == ERROR_USER_MAPPED_FILE, "CopyFile2: last error %d\n", GetLastError());
1115 CloseHandle(hmapfile);
1116 CloseHandle(hfile);
1118 DeleteFileW(source);
1119 DeleteFileW(dest);
1122 static DWORD WINAPI copy_progress_cb(LARGE_INTEGER total_size, LARGE_INTEGER total_transferred,
1123 LARGE_INTEGER stream_size, LARGE_INTEGER stream_transferred,
1124 DWORD stream, DWORD reason, HANDLE source, HANDLE dest, LPVOID userdata)
1126 ok(reason == CALLBACK_STREAM_SWITCH, "expected CALLBACK_STREAM_SWITCH, got %u\n", reason);
1127 CloseHandle(userdata);
1128 return PROGRESS_CANCEL;
1131 static void test_CopyFileEx(void)
1133 char temp_path[MAX_PATH];
1134 char source[MAX_PATH], dest[MAX_PATH];
1135 static const char prefix[] = "pfx";
1136 HANDLE hfile;
1137 DWORD ret;
1138 BOOL retok;
1140 ret = GetTempPathA(MAX_PATH, temp_path);
1141 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1142 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1144 ret = GetTempFileNameA(temp_path, prefix, 0, source);
1145 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1147 ret = GetTempFileNameA(temp_path, prefix, 0, dest);
1148 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1150 hfile = CreateFileA(dest, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
1151 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1152 SetLastError(0xdeadbeef);
1153 retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
1154 todo_wine
1155 ok(!retok, "CopyFileExA unexpectedly succeeded\n");
1156 todo_wine
1157 ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError());
1158 ok(GetFileAttributesA(dest) != INVALID_FILE_ATTRIBUTES, "file was deleted\n");
1160 hfile = CreateFileA(dest, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1161 NULL, OPEN_EXISTING, 0, 0);
1162 todo_wine
1163 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1164 SetLastError(0xdeadbeef);
1165 retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
1166 todo_wine
1167 ok(!retok, "CopyFileExA unexpectedly succeeded\n");
1168 todo_wine
1169 ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError());
1170 todo_wine
1171 ok(GetFileAttributesA(dest) == INVALID_FILE_ATTRIBUTES, "file was not deleted\n");
1173 ret = DeleteFileA(source);
1174 ok(ret, "DeleteFileA failed with error %d\n", GetLastError());
1175 ret = DeleteFileA(dest);
1176 ok(!ret, "DeleteFileA unexpectedly succeeded\n");
1180 * Debugging routine to dump a buffer in a hexdump-like fashion.
1182 static void dumpmem(unsigned char *mem, int len)
1184 int x = 0;
1185 char hex[49], *p;
1186 char txt[17], *c;
1188 while (x < len)
1190 p = hex;
1191 c = txt;
1192 do {
1193 p += sprintf(p, "%02x ", mem[x]);
1194 *c++ = (mem[x] >= 32 && mem[x] <= 127) ? mem[x] : '.';
1195 } while (++x % 16 && x < len);
1196 *c = '\0';
1197 trace("%04x: %-48s- %s\n", x, hex, txt);
1201 static void test_CreateFileA(void)
1203 HANDLE hFile;
1204 char temp_path[MAX_PATH], dirname[MAX_PATH];
1205 char filename[MAX_PATH];
1206 static const char prefix[] = "pfx";
1207 char windowsdir[MAX_PATH];
1208 char Volume_1[MAX_PATH];
1209 unsigned char buffer[512];
1210 char directory[] = "removeme";
1211 static const char nt_drive[] = "\\\\?\\A:";
1212 DWORD i, ret, len;
1213 struct test_list p[] = {
1214 {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dir as file w \ */
1215 {"", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* dir as dir w \ */
1216 {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */
1217 {"a\\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */
1218 {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */
1219 {"removeme\\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exst dir w \ */
1220 {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */
1221 {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */
1222 {"c:\\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */
1223 {"c:\\", ERROR_SUCCESS, ERROR_ACCESS_DENIED, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* root dir w \ as dir */
1224 {"\\\\?\\c:", ERROR_SUCCESS, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL,FALSE }, /* dev namespace drive */
1225 {"\\\\?\\c:\\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dev namespace drive w \ */
1226 {NULL, 0, -1, 0, FALSE}
1228 BY_HANDLE_FILE_INFORMATION Finfo;
1230 ret = GetTempPathA(MAX_PATH, temp_path);
1231 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1232 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1234 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
1235 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1237 SetLastError(0xdeadbeef);
1238 hFile = CreateFileA(filename, GENERIC_READ, 0, NULL,
1239 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1240 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
1241 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1243 SetLastError(0xdeadbeef);
1244 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1245 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1246 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1247 "hFile %p, last error %u\n", hFile, GetLastError());
1249 CloseHandle(hFile);
1251 SetLastError(0xdeadbeef);
1252 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1253 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1254 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1255 "hFile %p, last error %u\n", hFile, GetLastError());
1257 CloseHandle(hFile);
1259 ret = DeleteFileA(filename);
1260 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1262 SetLastError(0xdeadbeef);
1263 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1264 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1265 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1266 "hFile %p, last error %u\n", hFile, GetLastError());
1268 CloseHandle(hFile);
1270 ret = DeleteFileA(filename);
1271 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1273 SetLastError(0xdeadbeef);
1274 hFile = CreateFileA("c:\\*.*", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1275 ok(hFile == INVALID_HANDLE_VALUE, "hFile should have been INVALID_HANDLE_VALUE\n");
1276 ok(GetLastError() == ERROR_INVALID_NAME ||
1277 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */
1278 "LastError should have been ERROR_INVALID_NAME or ERROR_FILE_NOT_FOUND but got %u\n", GetLastError());
1280 /* get windows drive letter */
1281 ret = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
1282 ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
1283 ok(ret != 0, "GetWindowsDirectory: error %d\n", GetLastError());
1285 /* test error return codes from CreateFile for some cases */
1286 ret = GetTempPathA(MAX_PATH, temp_path);
1287 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1288 strcpy(dirname, temp_path);
1289 strcat(dirname, directory);
1290 ret = CreateDirectoryA(dirname, NULL);
1291 ok( ret, "Createdirectory failed, gle=%d\n", GetLastError() );
1292 /* set current drive & directory to known location */
1293 SetCurrentDirectoryA( temp_path );
1294 i = 0;
1295 while (p[i].file)
1297 filename[0] = 0;
1298 /* update the drive id in the table entry with the current one */
1299 if (p[i].file[1] == ':')
1301 strcpy(filename, p[i].file);
1302 filename[0] = windowsdir[0];
1304 else if (p[i].file[0] == '\\' && p[i].file[5] == ':')
1306 strcpy(filename, p[i].file);
1307 filename[4] = windowsdir[0];
1309 else
1311 /* prefix the table entry with the current temp directory */
1312 strcpy(filename, temp_path);
1313 strcat(filename, p[i].file);
1315 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1316 FILE_SHARE_READ | FILE_SHARE_WRITE,
1317 NULL, OPEN_EXISTING,
1318 p[i].options, NULL );
1319 /* if we get ACCESS_DENIED when we do not expect it, assume
1320 * no access to the volume
1322 if (hFile == INVALID_HANDLE_VALUE &&
1323 GetLastError() == ERROR_ACCESS_DENIED &&
1324 p[i].err != ERROR_ACCESS_DENIED)
1326 if (p[i].todo_flag)
1327 skip("Either no authority to volume, or is todo_wine for %s err=%d should be %d\n", filename, GetLastError(), p[i].err);
1328 else
1329 skip("Do not have authority to access volumes. Test for %s skipped\n", filename);
1331 /* otherwise validate results with expectations */
1332 else if (p[i].todo_flag)
1333 todo_wine ok(
1334 (hFile == INVALID_HANDLE_VALUE &&
1335 (p[i].err == GetLastError() || p[i].err2 == GetLastError())) ||
1336 (hFile != INVALID_HANDLE_VALUE && p[i].err == ERROR_SUCCESS),
1337 "CreateFileA failed on %s, hFile %p, err=%u, should be %u\n",
1338 filename, hFile, GetLastError(), p[i].err);
1339 else
1341 (hFile == INVALID_HANDLE_VALUE &&
1342 (p[i].err == GetLastError() || p[i].err2 == GetLastError())) ||
1343 (hFile != INVALID_HANDLE_VALUE && p[i].err == ERROR_SUCCESS),
1344 "CreateFileA failed on %s, hFile %p, err=%u, should be %u\n",
1345 filename, hFile, GetLastError(), p[i].err);
1346 if (hFile != INVALID_HANDLE_VALUE)
1347 CloseHandle( hFile );
1348 i++;
1350 ret = RemoveDirectoryA(dirname);
1351 ok(ret, "RemoveDirectoryA: error %d\n", GetLastError());
1354 /* test opening directory as a directory */
1355 hFile = CreateFileA( temp_path, GENERIC_READ,
1356 FILE_SHARE_READ,
1357 NULL,
1358 OPEN_EXISTING,
1359 FILE_FLAG_BACKUP_SEMANTICS, NULL );
1360 if (hFile != INVALID_HANDLE_VALUE && GetLastError() != ERROR_PATH_NOT_FOUND)
1362 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_SUCCESS,
1363 "CreateFileA did not work, last error %u on volume <%s>\n",
1364 GetLastError(), temp_path );
1366 if (hFile != INVALID_HANDLE_VALUE)
1368 ret = GetFileInformationByHandle( hFile, &Finfo );
1369 if (ret)
1371 ok(Finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY,
1372 "CreateFileA probably did not open temp directory %s correctly\n file information does not include FILE_ATTRIBUTE_DIRECTORY, actual=0x%08x\n",
1373 temp_path, Finfo.dwFileAttributes);
1375 CloseHandle( hFile );
1378 else
1379 skip("Probable Win9x, got ERROR_PATH_NOT_FOUND w/ FILE_FLAG_BACKUP_SEMANTICS or %s\n", temp_path);
1382 /* *** Test opening volumes/devices using drive letter *** */
1384 /* test using drive letter in non-rewrite format without trailing \ */
1385 /* this should work */
1386 strcpy(filename, nt_drive);
1387 filename[4] = windowsdir[0];
1388 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1389 FILE_SHARE_READ | FILE_SHARE_WRITE,
1390 NULL, OPEN_EXISTING,
1391 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1392 if (hFile != INVALID_HANDLE_VALUE ||
1393 (GetLastError() != ERROR_ACCESS_DENIED && GetLastError() != ERROR_BAD_NETPATH))
1395 /* if we have adm rights to volume, then try rest of tests */
1396 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1397 filename, GetLastError());
1398 if (hFile != INVALID_HANDLE_VALUE)
1400 /* if we opened the volume/device, try to read it. Since it */
1401 /* opened, we should be able to read it. We don't care about*/
1402 /* what the data is at this time. */
1403 len = 512;
1404 ret = ReadFile( hFile, buffer, len, &len, NULL );
1405 todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n",
1406 GetLastError(), ret, filename);
1407 if (ret)
1409 trace("buffer is\n");
1410 dumpmem(buffer, 64);
1412 CloseHandle( hFile );
1415 /* test using drive letter with trailing \ and in non-rewrite */
1416 /* this should not work */
1417 strcpy(filename, nt_drive);
1418 filename[4] = windowsdir[0];
1419 strcat( filename, "\\" );
1420 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1421 FILE_SHARE_READ | FILE_SHARE_WRITE,
1422 NULL, OPEN_EXISTING,
1423 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1424 todo_wine
1425 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1426 "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n",
1427 filename, GetLastError());
1428 if (hFile != INVALID_HANDLE_VALUE)
1429 CloseHandle( hFile );
1431 /* test using temp path with trailing \ and in non-rewrite as dir */
1432 /* this should work */
1433 strcpy(filename, nt_drive);
1434 filename[4] = 0;
1435 strcat( filename, temp_path );
1436 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1437 FILE_SHARE_READ | FILE_SHARE_WRITE,
1438 NULL, OPEN_EXISTING,
1439 FILE_FLAG_BACKUP_SEMANTICS, NULL );
1440 ok(hFile != INVALID_HANDLE_VALUE,
1441 "CreateFileA should have worked on %s, but got %u\n",
1442 filename, GetLastError());
1443 if (hFile != INVALID_HANDLE_VALUE)
1444 CloseHandle( hFile );
1446 /* test using drive letter without trailing \ and in device ns */
1447 /* this should work */
1448 strcpy(filename, nt_drive);
1449 filename[4] = windowsdir[0];
1450 filename[2] = '.';
1451 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1452 FILE_SHARE_READ | FILE_SHARE_WRITE,
1453 NULL, OPEN_EXISTING,
1454 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1455 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1456 filename, GetLastError());
1457 if (hFile != INVALID_HANDLE_VALUE)
1458 CloseHandle( hFile );
1460 /* If we see ERROR_BAD_NETPATH then on Win9x or WinME, so skip */
1461 else if (GetLastError() == ERROR_BAD_NETPATH)
1462 skip("Probable Win9x, got ERROR_BAD_NETPATH (53)\n");
1463 else
1464 skip("Do not have authority to access volumes. Tests skipped\n");
1467 /* *** Test opening volumes/devices using GUID *** */
1469 if (pGetVolumeNameForVolumeMountPointA)
1471 strcpy(filename, "c:\\");
1472 filename[0] = windowsdir[0];
1473 ret = pGetVolumeNameForVolumeMountPointA( filename, Volume_1, MAX_PATH );
1474 ok(ret, "GetVolumeNameForVolumeMountPointA failed, for %s, last error=%d\n", filename, GetLastError());
1475 if (ret)
1477 ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name <%s>\n", Volume_1);
1479 /* test the result of opening a unique volume name (GUID)
1480 * with the trailing \
1481 * this should error out
1483 strcpy(filename, Volume_1);
1484 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1485 FILE_SHARE_READ | FILE_SHARE_WRITE,
1486 NULL, OPEN_EXISTING,
1487 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1488 todo_wine
1489 ok(hFile == INVALID_HANDLE_VALUE,
1490 "CreateFileA should not have opened %s, hFile %p\n",
1491 filename, hFile);
1492 todo_wine
1493 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1494 "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n",
1495 filename, GetLastError());
1496 if (hFile != INVALID_HANDLE_VALUE)
1497 CloseHandle( hFile );
1499 /* test the result of opening a unique volume name (GUID)
1500 * with the temp path string as dir
1501 * this should work
1503 strcpy(filename, Volume_1);
1504 strcat(filename, temp_path+3);
1505 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1506 FILE_SHARE_READ | FILE_SHARE_WRITE,
1507 NULL, OPEN_EXISTING,
1508 FILE_FLAG_BACKUP_SEMANTICS, NULL );
1509 todo_wine
1510 ok(hFile != INVALID_HANDLE_VALUE,
1511 "CreateFileA should have opened %s, but got %u\n",
1512 filename, GetLastError());
1513 if (hFile != INVALID_HANDLE_VALUE)
1514 CloseHandle( hFile );
1516 /* test the result of opening a unique volume name (GUID)
1517 * without the trailing \ and in device namespace
1518 * this should work
1520 strcpy(filename, Volume_1);
1521 filename[2] = '.';
1522 filename[48] = 0;
1523 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1524 FILE_SHARE_READ | FILE_SHARE_WRITE,
1525 NULL, OPEN_EXISTING,
1526 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
1527 if (hFile != INVALID_HANDLE_VALUE || GetLastError() != ERROR_ACCESS_DENIED)
1529 /* if we have adm rights to volume, then try rest of tests */
1530 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1531 filename, GetLastError());
1532 if (hFile != INVALID_HANDLE_VALUE)
1534 /* if we opened the volume/device, try to read it. Since it */
1535 /* opened, we should be able to read it. We don't care about*/
1536 /* what the data is at this time. */
1537 len = 512;
1538 ret = ReadFile( hFile, buffer, len, &len, NULL );
1539 todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n",
1540 GetLastError(), ret, filename);
1541 if (ret)
1543 trace("buffer is\n");
1544 dumpmem(buffer, 64);
1546 CloseHandle( hFile );
1549 else
1550 skip("Do not have authority to access volumes. Tests skipped\n");
1552 else
1553 win_skip("GetVolumeNameForVolumeMountPointA not functioning\n");
1555 else
1556 win_skip("GetVolumeNameForVolumeMountPointA not found\n");
1559 static void test_CreateFileW(void)
1561 HANDLE hFile;
1562 WCHAR temp_path[MAX_PATH];
1563 WCHAR filename[MAX_PATH];
1564 static const WCHAR emptyW[]={'\0'};
1565 static const WCHAR prefix[] = {'p','f','x',0};
1566 static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
1567 DWORD ret;
1569 ret = GetTempPathW(MAX_PATH, temp_path);
1570 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1572 win_skip("GetTempPathW is not available\n");
1573 return;
1575 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1576 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1578 ret = GetTempFileNameW(temp_path, prefix, 0, filename);
1579 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1581 SetLastError(0xdeadbeef);
1582 hFile = CreateFileW(filename, GENERIC_READ, 0, NULL,
1583 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1584 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
1585 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1587 SetLastError(0xdeadbeef);
1588 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1589 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1590 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1591 "hFile %p, last error %u\n", hFile, GetLastError());
1593 CloseHandle(hFile);
1595 SetLastError(0xdeadbeef);
1596 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1597 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1598 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1599 "hFile %p, last error %u\n", hFile, GetLastError());
1601 CloseHandle(hFile);
1603 ret = DeleteFileW(filename);
1604 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1606 SetLastError(0xdeadbeef);
1607 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1608 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
1609 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1610 "hFile %p, last error %u\n", hFile, GetLastError());
1612 CloseHandle(hFile);
1614 ret = DeleteFileW(filename);
1615 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1617 if (0)
1619 /* this crashes on NT4.0 */
1620 hFile = CreateFileW(NULL, GENERIC_READ, 0, NULL,
1621 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1622 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1623 "CreateFileW(NULL) returned ret=%p error=%u\n",hFile,GetLastError());
1626 hFile = CreateFileW(emptyW, GENERIC_READ, 0, NULL,
1627 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
1628 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1629 "CreateFileW(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
1631 /* test the result of opening a nonexistent driver name */
1632 hFile = CreateFileW(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1633 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1634 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
1635 "CreateFileW on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
1637 ret = CreateDirectoryW(filename, NULL);
1638 ok(ret == TRUE, "couldn't create temporary directory\n");
1639 hFile = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1640 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
1641 ok(hFile != INVALID_HANDLE_VALUE,
1642 "expected CreateFile to succeed on existing directory, error: %d\n", GetLastError());
1643 CloseHandle(hFile);
1644 ret = RemoveDirectoryW(filename);
1645 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1648 static void test_CreateFile2(void)
1650 HANDLE hFile;
1651 WCHAR temp_path[MAX_PATH];
1652 WCHAR filename[MAX_PATH];
1653 CREATEFILE2_EXTENDED_PARAMETERS exparams;
1654 static const WCHAR emptyW[]={'\0'};
1655 static const WCHAR prefix[] = {'p','f','x',0};
1656 static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
1657 DWORD ret;
1659 if (!pCreateFile2)
1661 win_skip("CreateFile2 is missing\n");
1662 return;
1665 ret = GetTempPathW(MAX_PATH, temp_path);
1666 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1667 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1669 ret = GetTempFileNameW(temp_path, prefix, 0, filename);
1670 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1672 SetLastError(0xdeadbeef);
1673 exparams.dwSize = sizeof(exparams);
1674 exparams.dwFileAttributes = FILE_FLAG_RANDOM_ACCESS;
1675 exparams.dwFileFlags = 0;
1676 exparams.dwSecurityQosFlags = 0;
1677 exparams.lpSecurityAttributes = NULL;
1678 exparams.hTemplateFile = 0;
1679 hFile = pCreateFile2(filename, GENERIC_READ, 0, CREATE_NEW, &exparams);
1680 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
1681 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1683 SetLastError(0xdeadbeef);
1684 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, CREATE_ALWAYS, &exparams);
1685 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1686 "hFile %p, last error %u\n", hFile, GetLastError());
1687 CloseHandle(hFile);
1689 SetLastError(0xdeadbeef);
1690 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
1691 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
1692 "hFile %p, last error %u\n", hFile, GetLastError());
1693 CloseHandle(hFile);
1695 ret = DeleteFileW(filename);
1696 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1698 SetLastError(0xdeadbeef);
1699 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
1700 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1701 "hFile %p, last error %u\n", hFile, GetLastError());
1702 CloseHandle(hFile);
1704 ret = DeleteFileW(filename);
1705 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1707 hFile = pCreateFile2(emptyW, GENERIC_READ, 0, CREATE_NEW, &exparams);
1708 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
1709 "CreateFile2(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
1711 /* test the result of opening a nonexistent driver name */
1712 exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
1713 hFile = pCreateFile2(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &exparams);
1714 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
1715 "CreateFile2 on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
1717 ret = CreateDirectoryW(filename, NULL);
1718 ok(ret == TRUE, "couldn't create temporary directory\n");
1719 exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS;
1720 hFile = pCreateFile2(filename, GENERIC_READ | GENERIC_WRITE, 0, OPEN_ALWAYS, &exparams);
1721 todo_wine
1722 ok(hFile == INVALID_HANDLE_VALUE,
1723 "expected CreateFile2 to fail on existing directory, error: %d\n", GetLastError());
1724 CloseHandle(hFile);
1725 ret = RemoveDirectoryW(filename);
1726 ok(ret, "DeleteFileW: error %d\n", GetLastError());
1729 static void test_GetTempFileNameA(void)
1731 UINT result;
1732 char out[MAX_PATH];
1733 char expected[MAX_PATH + 10];
1734 char windowsdir[MAX_PATH + 10];
1735 char windowsdrive[3];
1737 result = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
1738 ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
1739 ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
1741 /* If the Windows directory is the root directory, it ends in backslash, not else. */
1742 if (strlen(windowsdir) != 3) /* As in "C:\" or "F:\" */
1744 strcat(windowsdir, "\\");
1747 windowsdrive[0] = windowsdir[0];
1748 windowsdrive[1] = windowsdir[1];
1749 windowsdrive[2] = '\0';
1751 result = GetTempFileNameA(windowsdrive, "abc", 1, out);
1752 ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
1753 ok(((out[0] == windowsdrive[0]) && (out[1] == ':')) && (out[2] == '\\'),
1754 "GetTempFileNameA: first three characters should be %c:\\, string was actually %s\n",
1755 windowsdrive[0], out);
1757 result = GetTempFileNameA(windowsdir, "abc", 2, out);
1758 ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
1759 expected[0] = '\0';
1760 strcat(expected, windowsdir);
1761 strcat(expected, "abc2.tmp");
1762 ok(lstrcmpiA(out, expected) == 0, "GetTempFileNameA: Unexpected output \"%s\" vs \"%s\"\n",
1763 out, expected);
1766 static void test_DeleteFileA( void )
1768 BOOL ret;
1769 char temp_path[MAX_PATH], temp_file[MAX_PATH];
1770 HANDLE hfile;
1772 ret = DeleteFileA(NULL);
1773 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER ||
1774 GetLastError() == ERROR_PATH_NOT_FOUND),
1775 "DeleteFileA(NULL) returned ret=%d error=%d\n",ret,GetLastError());
1777 ret = DeleteFileA("");
1778 ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND ||
1779 GetLastError() == ERROR_BAD_PATHNAME),
1780 "DeleteFileA(\"\") returned ret=%d error=%d\n",ret,GetLastError());
1782 ret = DeleteFileA("nul");
1783 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
1784 GetLastError() == ERROR_INVALID_PARAMETER ||
1785 GetLastError() == ERROR_ACCESS_DENIED ||
1786 GetLastError() == ERROR_INVALID_FUNCTION),
1787 "DeleteFileA(\"nul\") returned ret=%d error=%d\n",ret,GetLastError());
1789 ret = DeleteFileA("nonexist.txt");
1790 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "DeleteFileA(\"nonexist.txt\") returned ret=%d error=%d\n",ret,GetLastError());
1792 GetTempPathA(MAX_PATH, temp_path);
1793 GetTempFileNameA(temp_path, "tst", 0, temp_file);
1795 SetLastError(0xdeadbeef);
1796 hfile = CreateFileA(temp_file, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1797 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1799 SetLastError(0xdeadbeef);
1800 ret = DeleteFileA(temp_file);
1801 todo_wine
1802 ok(ret, "DeleteFile error %d\n", GetLastError());
1804 SetLastError(0xdeadbeef);
1805 ret = CloseHandle(hfile);
1806 ok(ret, "CloseHandle error %d\n", GetLastError());
1807 ret = DeleteFileA(temp_file);
1808 todo_wine
1809 ok(!ret, "DeleteFile should fail\n");
1811 SetLastError(0xdeadbeef);
1812 ret = CreateDirectoryA("testdir", NULL);
1813 ok(ret, "CreateDirectory failed, got err %d\n", GetLastError());
1814 ret = DeleteFileA("testdir");
1815 ok(!ret && GetLastError() == ERROR_ACCESS_DENIED,
1816 "Expected ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
1817 ret = RemoveDirectoryA("testdir");
1818 ok(ret, "Remove a directory failed, got error %d\n", GetLastError());
1821 static void test_DeleteFileW( void )
1823 BOOL ret;
1824 WCHAR pathW[MAX_PATH];
1825 WCHAR pathsubW[MAX_PATH];
1826 static const WCHAR dirW[] = {'d','e','l','e','t','e','f','i','l','e',0};
1827 static const WCHAR subdirW[] = {'\\','s','u','b',0};
1828 static const WCHAR emptyW[]={'\0'};
1830 ret = DeleteFileW(NULL);
1831 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1833 win_skip("DeleteFileW is not available\n");
1834 return;
1836 ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
1837 "DeleteFileW(NULL) returned ret=%d error=%d\n",ret,GetLastError());
1839 ret = DeleteFileW(emptyW);
1840 ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
1841 "DeleteFileW(\"\") returned ret=%d error=%d\n",ret,GetLastError());
1843 /* test DeleteFile on empty directory */
1844 ret = GetTempPathW(MAX_PATH, pathW);
1845 if (ret + sizeof(dirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
1847 ok(0, "MAX_PATH exceeded in constructing paths\n");
1848 return;
1850 lstrcatW(pathW, dirW);
1851 lstrcpyW(pathsubW, pathW);
1852 lstrcatW(pathsubW, subdirW);
1853 ret = CreateDirectoryW(pathW, NULL);
1854 ok(ret == TRUE, "couldn't create directory deletefile\n");
1855 ret = DeleteFileW(pathW);
1856 ok(ret == FALSE, "DeleteFile should fail for empty directories\n");
1857 ret = RemoveDirectoryW(pathW);
1858 ok(ret == TRUE, "expected to remove directory deletefile\n");
1860 /* test DeleteFile on non-empty directory */
1861 ret = CreateDirectoryW(pathW, NULL);
1862 ok(ret == TRUE, "couldn't create directory deletefile\n");
1863 ret = CreateDirectoryW(pathsubW, NULL);
1864 ok(ret == TRUE, "couldn't create directory deletefile\\sub\n");
1865 ret = DeleteFileW(pathW);
1866 ok(ret == FALSE, "DeleteFile should fail for non-empty directories\n");
1867 ret = RemoveDirectoryW(pathsubW);
1868 ok(ret == TRUE, "expected to remove directory deletefile\\sub\n");
1869 ret = RemoveDirectoryW(pathW);
1870 ok(ret == TRUE, "expected to remove directory deletefile\n");
1873 #define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
1875 static void test_MoveFileA(void)
1877 char tempdir[MAX_PATH];
1878 char source[MAX_PATH], dest[MAX_PATH];
1879 static const char prefix[] = "pfx";
1880 HANDLE hfile;
1881 HANDLE hmapfile;
1882 DWORD ret;
1883 BOOL retok;
1885 ret = GetTempPathA(MAX_PATH, tempdir);
1886 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1887 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1889 ret = GetTempFileNameA(tempdir, prefix, 0, source);
1890 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1892 ret = GetTempFileNameA(tempdir, prefix, 0, dest);
1893 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1895 ret = MoveFileA(source, dest);
1896 ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
1897 "MoveFileA: unexpected error %d\n", GetLastError());
1899 ret = DeleteFileA(dest);
1900 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1902 hfile = CreateFileA(source, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
1903 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
1905 retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL );
1906 ok( retok && ret == sizeof(prefix),
1907 "WriteFile error %d\n", GetLastError());
1909 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1910 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1912 ret = MoveFileA(source, dest);
1913 todo_wine {
1914 ok(!ret, "MoveFileA: expected failure\n");
1915 ok(GetLastError() == ERROR_SHARING_VIOLATION ||
1916 broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
1917 "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
1920 CloseHandle(hmapfile);
1921 CloseHandle(hfile);
1923 /* if MoveFile succeeded, move back to dest */
1924 if (ret) MoveFileA(dest, source);
1926 hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1927 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
1929 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1930 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1932 ret = MoveFileA(source, dest);
1933 todo_wine {
1934 ok(!ret, "MoveFileA: expected failure\n");
1935 ok(GetLastError() == ERROR_SHARING_VIOLATION ||
1936 broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
1937 "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
1940 CloseHandle(hmapfile);
1941 CloseHandle(hfile);
1943 /* if MoveFile succeeded, move back to dest */
1944 if (ret) MoveFileA(dest, source);
1946 ret = MoveFileA(source, dest);
1947 ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
1949 lstrcatA(tempdir, "Remove Me");
1950 ret = CreateDirectoryA(tempdir, NULL);
1951 ok(ret == TRUE, "CreateDirectoryA failed\n");
1953 lstrcpyA(source, dest);
1954 lstrcpyA(dest, tempdir);
1955 lstrcatA(dest, "\\wild?.*");
1956 /* FIXME: if we create a file with wildcards we can't delete it now that DeleteFile works correctly */
1957 ret = MoveFileA(source, dest);
1958 ok(!ret, "MoveFileA: shouldn't move to wildcard file\n");
1959 ok(GetLastError() == ERROR_INVALID_NAME || /* NT */
1960 GetLastError() == ERROR_FILE_NOT_FOUND, /* Win9x */
1961 "MoveFileA: with wildcards, unexpected error %d\n", GetLastError());
1962 if (ret || (GetLastError() != ERROR_INVALID_NAME))
1964 WIN32_FIND_DATAA fd;
1965 char temppath[MAX_PATH];
1966 HANDLE hFind;
1968 lstrcpyA(temppath, tempdir);
1969 lstrcatA(temppath, "\\*.*");
1970 hFind = FindFirstFileA(temppath, &fd);
1971 if (INVALID_HANDLE_VALUE != hFind)
1973 LPSTR lpName;
1976 lpName = fd.cAlternateFileName;
1977 if (!lpName[0])
1978 lpName = fd.cFileName;
1979 ok(IsDotDir(lpName), "MoveFileA: wildcards file created!\n");
1981 while (FindNextFileA(hFind, &fd));
1982 FindClose(hFind);
1985 ret = DeleteFileA(source);
1986 ok(ret, "DeleteFileA: error %d\n", GetLastError());
1987 ret = DeleteFileA(dest);
1988 ok(!ret, "DeleteFileA: error %d\n", GetLastError());
1989 ret = RemoveDirectoryA(tempdir);
1990 ok(ret, "DeleteDirectoryA: error %d\n", GetLastError());
1993 static void test_MoveFileW(void)
1995 WCHAR temp_path[MAX_PATH];
1996 WCHAR source[MAX_PATH], dest[MAX_PATH];
1997 static const WCHAR prefix[] = {'p','f','x',0};
1998 DWORD ret;
2000 ret = GetTempPathW(MAX_PATH, temp_path);
2001 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2003 win_skip("GetTempPathW is not available\n");
2004 return;
2006 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
2007 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
2009 ret = GetTempFileNameW(temp_path, prefix, 0, source);
2010 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
2012 ret = GetTempFileNameW(temp_path, prefix, 0, dest);
2013 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
2015 ret = MoveFileW(source, dest);
2016 ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
2017 "CopyFileW: unexpected error %d\n", GetLastError());
2019 ret = DeleteFileW(source);
2020 ok(ret, "DeleteFileW: error %d\n", GetLastError());
2021 ret = DeleteFileW(dest);
2022 ok(ret, "DeleteFileW: error %d\n", GetLastError());
2025 #define PATTERN_OFFSET 0x10
2027 static void test_offset_in_overlapped_structure(void)
2029 HANDLE hFile;
2030 OVERLAPPED ov;
2031 DWORD done, offset;
2032 BOOL rc;
2033 BYTE buf[256], pattern[] = "TeSt";
2034 UINT i;
2035 char temp_path[MAX_PATH], temp_fname[MAX_PATH];
2036 BOOL ret;
2038 ret =GetTempPathA(MAX_PATH, temp_path);
2039 ok( ret, "GetTempPathA error %d\n", GetLastError());
2040 ret =GetTempFileNameA(temp_path, "pfx", 0, temp_fname);
2041 ok( ret, "GetTempFileNameA error %d\n", GetLastError());
2043 /*** Write File *****************************************************/
2045 hFile = CreateFileA(temp_fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
2046 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
2048 for(i = 0; i < sizeof(buf); i++) buf[i] = i;
2049 ret = WriteFile(hFile, buf, sizeof(buf), &done, NULL);
2050 ok( ret, "WriteFile error %d\n", GetLastError());
2051 ok(done == sizeof(buf), "expected number of bytes written %u\n", done);
2053 memset(&ov, 0, sizeof(ov));
2054 S(U(ov)).Offset = PATTERN_OFFSET;
2055 S(U(ov)).OffsetHigh = 0;
2056 rc=WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
2057 /* Win 9x does not support the overlapped I/O on files */
2058 if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
2059 ok(rc, "WriteFile error %d\n", GetLastError());
2060 ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
2061 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
2062 ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
2064 S(U(ov)).Offset = sizeof(buf) * 2;
2065 S(U(ov)).OffsetHigh = 0;
2066 ret = WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
2067 ok( ret, "WriteFile error %d\n", GetLastError());
2068 ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
2069 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
2070 ok(offset == sizeof(buf) * 2 + sizeof(pattern), "wrong file offset %d\n", offset);
2073 CloseHandle(hFile);
2075 /*** Read File *****************************************************/
2077 hFile = CreateFileA(temp_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
2078 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
2080 memset(buf, 0, sizeof(buf));
2081 memset(&ov, 0, sizeof(ov));
2082 S(U(ov)).Offset = PATTERN_OFFSET;
2083 S(U(ov)).OffsetHigh = 0;
2084 rc=ReadFile(hFile, buf, sizeof(pattern), &done, &ov);
2085 /* Win 9x does not support the overlapped I/O on files */
2086 if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
2087 ok(rc, "ReadFile error %d\n", GetLastError());
2088 ok(done == sizeof(pattern), "expected number of bytes read %u\n", done);
2089 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
2090 ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
2091 ok(!memcmp(buf, pattern, sizeof(pattern)), "pattern match failed\n");
2094 CloseHandle(hFile);
2096 ret = DeleteFileA(temp_fname);
2097 ok( ret, "DeleteFileA error %d\n", GetLastError());
2100 static void test_LockFile(void)
2102 HANDLE handle, handle2;
2103 DWORD written;
2104 OVERLAPPED overlapped;
2105 int limited_LockFile;
2106 int limited_UnLockFile;
2107 BOOL ret;
2109 handle = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
2110 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2111 CREATE_ALWAYS, 0, 0 );
2112 if (handle == INVALID_HANDLE_VALUE)
2114 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2115 return;
2117 handle2 = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
2118 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2119 OPEN_EXISTING, 0, 0 );
2120 if (handle2 == INVALID_HANDLE_VALUE)
2122 ok( 0, "couldn't open file \"%s\" (err=%d)\n", filename, GetLastError() );
2123 goto cleanup;
2125 ok( WriteFile( handle, sillytext, strlen(sillytext), &written, NULL ), "write failed\n" );
2127 ok( LockFile( handle, 0, 0, 0, 0 ), "LockFile failed\n" );
2128 ok( UnlockFile( handle, 0, 0, 0, 0 ), "UnlockFile failed\n" );
2130 limited_UnLockFile = 0;
2131 if (UnlockFile( handle, 0, 0, 0, 0 ))
2133 limited_UnLockFile = 1;
2136 ok( LockFile( handle, 10, 0, 20, 0 ), "LockFile 10,20 failed\n" );
2137 /* overlapping locks must fail */
2138 ok( !LockFile( handle, 12, 0, 10, 0 ), "LockFile 12,10 succeeded\n" );
2139 ok( !LockFile( handle, 5, 0, 6, 0 ), "LockFile 5,6 succeeded\n" );
2140 /* non-overlapping locks must succeed */
2141 ok( LockFile( handle, 5, 0, 5, 0 ), "LockFile 5,5 failed\n" );
2143 ok( !UnlockFile( handle, 10, 0, 10, 0 ), "UnlockFile 10,10 succeeded\n" );
2144 ok( UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 failed\n" );
2145 ok( !UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 again succeeded\n" );
2146 ok( UnlockFile( handle, 5, 0, 5, 0 ), "UnlockFile 5,5 failed\n" );
2148 S(U(overlapped)).Offset = 100;
2149 S(U(overlapped)).OffsetHigh = 0;
2150 overlapped.hEvent = 0;
2152 /* Test for broken LockFileEx a la Windows 95 OSR2. */
2153 if (LockFileEx( handle, 0, 0, 100, 0, &overlapped ))
2155 /* LockFileEx is probably OK, test it more. */
2156 ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ),
2157 "LockFileEx 100,100 failed\n" );
2160 /* overlapping shared locks are OK */
2161 S(U(overlapped)).Offset = 150;
2162 limited_UnLockFile || ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 150,100 failed\n" );
2164 /* but exclusive is not */
2165 ok( !LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2166 0, 50, 0, &overlapped ),
2167 "LockFileEx exclusive 150,50 succeeded\n" );
2168 if (!UnlockFileEx( handle, 0, 100, 0, &overlapped ))
2169 { /* UnLockFile is capable. */
2170 S(U(overlapped)).Offset = 100;
2171 ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ),
2172 "UnlockFileEx 150,100 again succeeded\n" );
2175 /* shared lock can overlap exclusive if handles are equal */
2176 S(U(overlapped)).Offset = 300;
2177 ok( LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, &overlapped ),
2178 "LockFileEx exclusive 300,100 failed\n" );
2179 ok( !LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
2180 "LockFileEx handle2 300,100 succeeded\n" );
2181 ret = LockFileEx( handle, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped );
2182 ok( ret, "LockFileEx 300,100 failed\n" );
2183 ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2184 /* exclusive lock is removed first */
2185 ok( LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
2186 "LockFileEx handle2 300,100 failed\n" );
2187 ok( UnlockFileEx( handle2, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2188 if (ret)
2189 ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2191 ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 );
2192 if (ret)
2194 ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
2195 ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
2196 ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
2198 else /* win9x */
2199 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong LockFile error %u\n", GetLastError() );
2201 /* wrap-around lock should not do anything */
2202 /* (but still succeeds on NT4 so we don't check result) */
2203 LockFile( handle, 0, 0x10000000, 0, 0xf0000001 );
2205 limited_LockFile = 0;
2206 if (!LockFile( handle, ~0, ~0, 1, 0 ))
2208 limited_LockFile = 1;
2211 limited_UnLockFile || ok( UnlockFile( handle, ~0, ~0, 1, 0 ), "Unlockfile ~0,1 failed\n" );
2213 /* zero-byte lock */
2214 ok( LockFile( handle, 100, 0, 0, 0 ), "LockFile 100,0 failed\n" );
2215 if (!limited_LockFile) ok( !LockFile( handle, 98, 0, 4, 0 ), "LockFile 98,4 succeeded\n" );
2216 ok( LockFile( handle, 90, 0, 10, 0 ), "LockFile 90,10 failed\n" );
2217 if (!limited_LockFile) ok( !LockFile( handle, 100, 0, 10, 0 ), "LockFile 100,10 failed\n" );
2219 ok( UnlockFile( handle, 90, 0, 10, 0 ), "UnlockFile 90,10 failed\n" );
2220 ok( !UnlockFile( handle, 100, 0, 10, 0 ), "UnlockFile 100,10 succeeded\n" );
2222 ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed\n" );
2224 CloseHandle( handle2 );
2225 cleanup:
2226 CloseHandle( handle );
2227 DeleteFileA( filename );
2230 static BOOL create_fake_dll( LPCSTR filename )
2232 IMAGE_DOS_HEADER *dos;
2233 IMAGE_NT_HEADERS *nt;
2234 IMAGE_SECTION_HEADER *sec;
2235 BYTE *buffer;
2236 DWORD lfanew = sizeof(*dos);
2237 DWORD size = lfanew + sizeof(*nt) + sizeof(*sec);
2238 DWORD written;
2239 BOOL ret;
2241 HANDLE file = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2242 if (file == INVALID_HANDLE_VALUE) return FALSE;
2244 buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
2246 dos = (IMAGE_DOS_HEADER *)buffer;
2247 dos->e_magic = IMAGE_DOS_SIGNATURE;
2248 dos->e_cblp = sizeof(*dos);
2249 dos->e_cp = 1;
2250 dos->e_cparhdr = lfanew / 16;
2251 dos->e_minalloc = 0;
2252 dos->e_maxalloc = 0xffff;
2253 dos->e_ss = 0x0000;
2254 dos->e_sp = 0x00b8;
2255 dos->e_lfarlc = lfanew;
2256 dos->e_lfanew = lfanew;
2258 nt = (IMAGE_NT_HEADERS *)(buffer + lfanew);
2259 nt->Signature = IMAGE_NT_SIGNATURE;
2260 #if defined __i386__
2261 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386;
2262 #elif defined __x86_64__
2263 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64;
2264 #elif defined __powerpc__
2265 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC;
2266 #elif defined __arm__
2267 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT;
2268 #elif defined __aarch64__
2269 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64;
2270 #else
2271 # error You must specify the machine type
2272 #endif
2273 nt->FileHeader.NumberOfSections = 1;
2274 nt->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
2275 nt->FileHeader.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE;
2276 nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
2277 nt->OptionalHeader.MajorLinkerVersion = 1;
2278 nt->OptionalHeader.MinorLinkerVersion = 0;
2279 nt->OptionalHeader.ImageBase = 0x10000000;
2280 nt->OptionalHeader.SectionAlignment = 0x1000;
2281 nt->OptionalHeader.FileAlignment = 0x1000;
2282 nt->OptionalHeader.MajorOperatingSystemVersion = 1;
2283 nt->OptionalHeader.MinorOperatingSystemVersion = 0;
2284 nt->OptionalHeader.MajorImageVersion = 1;
2285 nt->OptionalHeader.MinorImageVersion = 0;
2286 nt->OptionalHeader.MajorSubsystemVersion = 4;
2287 nt->OptionalHeader.MinorSubsystemVersion = 0;
2288 nt->OptionalHeader.SizeOfImage = 0x2000;
2289 nt->OptionalHeader.SizeOfHeaders = size;
2290 nt->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
2291 nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
2293 sec = (IMAGE_SECTION_HEADER *)(nt + 1);
2294 memcpy( sec->Name, ".rodata", sizeof(".rodata") );
2295 sec->Misc.VirtualSize = 0x1000;
2296 sec->VirtualAddress = 0x1000;
2297 sec->SizeOfRawData = 0;
2298 sec->PointerToRawData = 0;
2299 sec->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
2301 ret = WriteFile( file, buffer, size, &written, NULL ) && written == size;
2302 HeapFree( GetProcessHeap(), 0, buffer );
2303 CloseHandle( file );
2304 return ret;
2307 static unsigned int map_file_access( unsigned int access )
2309 if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
2310 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
2311 if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
2312 if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS;
2313 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
2316 static BOOL is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 )
2318 access1 = map_file_access( access1 );
2319 access2 = map_file_access( access2 );
2320 access1 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE;
2321 access2 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE;
2323 if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
2324 if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
2326 if ((access1 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing2 & FILE_SHARE_READ)) return FALSE;
2327 if ((access1 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing2 & FILE_SHARE_WRITE)) return FALSE;
2328 if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return FALSE;
2329 if ((access2 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing1 & FILE_SHARE_READ)) return FALSE;
2330 if ((access2 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing1 & FILE_SHARE_WRITE)) return FALSE;
2331 if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return FALSE;
2332 return TRUE;
2335 static BOOL is_sharing_map_compatible( DWORD map_access, DWORD access2, DWORD sharing2 )
2337 if ((map_access == PAGE_READWRITE || map_access == PAGE_EXECUTE_READWRITE) &&
2338 !(sharing2 & FILE_SHARE_WRITE)) return FALSE;
2339 access2 = map_file_access( access2 );
2340 if ((map_access & SEC_IMAGE) && (access2 & FILE_WRITE_DATA)) return FALSE;
2341 return TRUE;
2344 static void test_file_sharing(void)
2346 static const DWORD access_modes[] =
2347 { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE,
2348 DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE,
2349 GENERIC_EXECUTE, GENERIC_EXECUTE | DELETE,
2350 FILE_READ_DATA, FILE_WRITE_DATA, FILE_APPEND_DATA, FILE_READ_EA, FILE_WRITE_EA,
2351 FILE_READ_DATA | FILE_EXECUTE, FILE_WRITE_DATA | FILE_EXECUTE, FILE_APPEND_DATA | FILE_EXECUTE,
2352 FILE_READ_EA | FILE_EXECUTE, FILE_WRITE_EA | FILE_EXECUTE, FILE_EXECUTE,
2353 FILE_DELETE_CHILD, FILE_READ_ATTRIBUTES, FILE_WRITE_ATTRIBUTES };
2354 static const DWORD sharing_modes[] =
2355 { 0, FILE_SHARE_READ,
2356 FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
2357 FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_DELETE,
2358 FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE };
2359 static const DWORD mapping_modes[] =
2360 { PAGE_READONLY, PAGE_WRITECOPY, PAGE_READWRITE, SEC_IMAGE | PAGE_WRITECOPY };
2361 int a1, s1, a2, s2;
2362 int ret;
2363 HANDLE h, h2;
2365 /* make sure the file exists */
2366 if (!create_fake_dll( filename ))
2368 ok(0, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError());
2369 return;
2372 for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++)
2374 for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++)
2376 SetLastError(0xdeadbeef);
2377 h = CreateFileA( filename, access_modes[a1], sharing_modes[s1],
2378 NULL, OPEN_EXISTING, 0, 0 );
2379 if (h == INVALID_HANDLE_VALUE)
2381 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2382 return;
2384 for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
2386 for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
2388 SetLastError(0xdeadbeef);
2389 h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
2390 NULL, OPEN_EXISTING, 0, 0 );
2391 ret = GetLastError();
2392 if (is_sharing_compatible( access_modes[a1], sharing_modes[s1],
2393 access_modes[a2], sharing_modes[s2] ))
2395 ok( h2 != INVALID_HANDLE_VALUE,
2396 "open failed for modes %x/%x/%x/%x\n",
2397 access_modes[a1], sharing_modes[s1],
2398 access_modes[a2], sharing_modes[s2] );
2399 ok( ret == 0, "wrong error code %d\n", ret );
2401 else
2403 ok( h2 == INVALID_HANDLE_VALUE,
2404 "open succeeded for modes %x/%x/%x/%x\n",
2405 access_modes[a1], sharing_modes[s1],
2406 access_modes[a2], sharing_modes[s2] );
2407 ok( ret == ERROR_SHARING_VIOLATION,
2408 "wrong error code %d\n", ret );
2410 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2413 CloseHandle( h );
2417 for (a1 = 0; a1 < sizeof(mapping_modes)/sizeof(mapping_modes[0]); a1++)
2419 HANDLE m;
2421 create_fake_dll( filename );
2422 SetLastError(0xdeadbeef);
2423 h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
2424 if (h == INVALID_HANDLE_VALUE)
2426 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2427 return;
2429 m = CreateFileMappingA( h, NULL, mapping_modes[a1], 0, 0, NULL );
2430 ok( m != 0, "failed to create mapping %x err %u\n", mapping_modes[a1], GetLastError() );
2431 CloseHandle( h );
2432 if (!m) continue;
2434 for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
2436 for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
2438 SetLastError(0xdeadbeef);
2439 h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
2440 NULL, OPEN_EXISTING, 0, 0 );
2442 ret = GetLastError();
2443 if (h2 == INVALID_HANDLE_VALUE)
2445 ok( !is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]),
2446 "open failed for modes map %x/%x/%x\n",
2447 mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
2448 ok( ret == ERROR_SHARING_VIOLATION,
2449 "wrong error code %d\n", ret );
2451 else
2453 if (!is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
2454 ok( broken(1), /* no checking on nt4 */
2455 "open succeeded for modes map %x/%x/%x\n",
2456 mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
2457 ok( ret == 0xdeadbeef /* Win9x */ ||
2458 ret == 0, /* XP */
2459 "wrong error code %d\n", ret );
2460 CloseHandle( h2 );
2465 /* try CREATE_ALWAYS over an existing mapping */
2466 SetLastError(0xdeadbeef);
2467 h2 = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2468 NULL, CREATE_ALWAYS, 0, 0 );
2469 ret = GetLastError();
2470 if (mapping_modes[a1] & SEC_IMAGE)
2472 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
2473 ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
2475 else
2477 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
2478 ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
2480 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2482 /* try DELETE_ON_CLOSE over an existing mapping */
2483 SetLastError(0xdeadbeef);
2484 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2485 NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2486 ret = GetLastError();
2487 if (mapping_modes[a1] & SEC_IMAGE)
2489 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
2490 ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
2492 else
2494 ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %x err %u\n", mapping_modes[a1], ret );
2496 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2498 CloseHandle( m );
2501 SetLastError(0xdeadbeef);
2502 h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0 );
2503 ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
2505 SetLastError(0xdeadbeef);
2506 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2507 ok( h2 == INVALID_HANDLE_VALUE, "CreateFileA should fail\n");
2508 ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error code %d\n", GetLastError() );
2510 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
2511 ok( h2 != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
2513 CloseHandle(h);
2514 CloseHandle(h2);
2516 DeleteFileA( filename );
2519 static char get_windows_drive(void)
2521 char windowsdir[MAX_PATH];
2522 GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
2523 return windowsdir[0];
2526 static void test_FindFirstFileA(void)
2528 HANDLE handle;
2529 WIN32_FIND_DATAA data;
2530 int err;
2531 char buffer[5] = "C:\\";
2532 char buffer2[100];
2533 char nonexistent[MAX_PATH];
2535 /* try FindFirstFileA on "C:\" */
2536 buffer[0] = get_windows_drive();
2538 SetLastError( 0xdeadbeaf );
2539 handle = FindFirstFileA(buffer, &data);
2540 err = GetLastError();
2541 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on root directory should fail\n" );
2542 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2544 /* try FindFirstFileA on "C:\*" */
2545 strcpy(buffer2, buffer);
2546 strcat(buffer2, "*");
2547 handle = FindFirstFileA(buffer2, &data);
2548 ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
2549 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2550 "FindFirstFile shouldn't return '%s' in drive root\n", data.cFileName );
2551 if (FindNextFileA( handle, &data ))
2552 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2553 "FindNextFile shouldn't return '%s' in drive root\n", data.cFileName );
2554 ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
2556 /* try FindFirstFileA on windows dir */
2557 GetWindowsDirectoryA( buffer2, sizeof(buffer2) );
2558 strcat(buffer2, "\\*");
2559 handle = FindFirstFileA(buffer2, &data);
2560 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
2561 ok( !strcmp( data.cFileName, "." ), "FindFirstFile should return '.' first\n" );
2562 ok( FindNextFileA( handle, &data ), "FindNextFile failed\n" );
2563 ok( !strcmp( data.cFileName, ".." ), "FindNextFile should return '..' as second entry\n" );
2564 while (FindNextFileA( handle, &data ))
2565 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2566 "FindNextFile shouldn't return '%s'\n", data.cFileName );
2567 ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
2569 /* try FindFirstFileA on "C:\foo\" */
2570 SetLastError( 0xdeadbeaf );
2571 if (!GetTempFileNameA( buffer, "foo", 0, nonexistent ) && GetLastError() == ERROR_ACCESS_DENIED)
2573 char tmp[MAX_PATH];
2574 GetTempPathA( sizeof(tmp), tmp );
2575 GetTempFileNameA( tmp, "foo", 0, nonexistent );
2577 DeleteFileA( nonexistent );
2578 strcpy(buffer2, nonexistent);
2579 strcat(buffer2, "\\");
2580 handle = FindFirstFileA(buffer2, &data);
2581 err = GetLastError();
2582 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2583 todo_wine {
2584 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2587 /* try FindFirstFileA without trailing backslash */
2588 SetLastError( 0xdeadbeaf );
2589 strcpy(buffer2, nonexistent);
2590 handle = FindFirstFileA(buffer2, &data);
2591 err = GetLastError();
2592 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2593 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2595 /* try FindFirstFileA on "C:\foo\bar.txt" */
2596 SetLastError( 0xdeadbeaf );
2597 strcpy(buffer2, nonexistent);
2598 strcat(buffer2, "\\bar.txt");
2599 handle = FindFirstFileA(buffer2, &data);
2600 err = GetLastError();
2601 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2602 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2604 /* try FindFirstFileA on "C:\foo\*.*" */
2605 SetLastError( 0xdeadbeaf );
2606 strcpy(buffer2, nonexistent);
2607 strcat(buffer2, "\\*.*");
2608 handle = FindFirstFileA(buffer2, &data);
2609 err = GetLastError();
2610 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2611 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2613 /* try FindFirstFileA on "foo\bar.txt" */
2614 SetLastError( 0xdeadbeaf );
2615 strcpy(buffer2, nonexistent + 3);
2616 strcat(buffer2, "\\bar.txt");
2617 handle = FindFirstFileA(buffer2, &data);
2618 err = GetLastError();
2619 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2620 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2622 /* try FindFirstFileA on "c:\nul" */
2623 SetLastError( 0xdeadbeaf );
2624 strcpy(buffer2, buffer);
2625 strcat(buffer2, "nul");
2626 handle = FindFirstFileA(buffer2, &data);
2627 err = GetLastError();
2628 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
2629 ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
2630 ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
2631 FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
2632 "wrong attributes %x\n", data.dwFileAttributes );
2633 if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
2635 ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
2636 ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
2638 SetLastError( 0xdeadbeaf );
2639 ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
2640 ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
2641 ok( FindClose( handle ), "failed to close handle\n" );
2643 /* try FindFirstFileA on "lpt1" */
2644 SetLastError( 0xdeadbeaf );
2645 strcpy(buffer2, "lpt1");
2646 handle = FindFirstFileA(buffer2, &data);
2647 err = GetLastError();
2648 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
2649 ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
2650 ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
2651 FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
2652 "wrong attributes %x\n", data.dwFileAttributes );
2653 if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
2655 ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
2656 ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
2658 SetLastError( 0xdeadbeaf );
2659 ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
2660 ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
2661 ok( FindClose( handle ), "failed to close handle\n" );
2663 /* try FindFirstFileA on "c:\nul\*" */
2664 SetLastError( 0xdeadbeaf );
2665 strcpy(buffer2, buffer);
2666 strcat(buffer2, "nul\\*");
2667 handle = FindFirstFileA(buffer2, &data);
2668 err = GetLastError();
2669 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2670 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2672 /* try FindFirstFileA on "c:\nul*" */
2673 SetLastError( 0xdeadbeaf );
2674 strcpy(buffer2, buffer);
2675 strcat(buffer2, "nul*");
2676 handle = FindFirstFileA(buffer2, &data);
2677 err = GetLastError();
2678 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2679 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2681 /* try FindFirstFileA on "c:\foo\bar\nul" */
2682 SetLastError( 0xdeadbeaf );
2683 strcpy(buffer2, buffer);
2684 strcat(buffer2, "foo\\bar\\nul");
2685 handle = FindFirstFileA(buffer2, &data);
2686 err = GetLastError();
2687 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2688 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2690 /* try FindFirstFileA on "c:\foo\nul\bar" */
2691 SetLastError( 0xdeadbeaf );
2692 strcpy(buffer2, buffer);
2693 strcat(buffer2, "foo\\nul\\bar");
2694 handle = FindFirstFileA(buffer2, &data);
2695 err = GetLastError();
2696 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2697 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2700 static void test_FindNextFileA(void)
2702 HANDLE handle;
2703 WIN32_FIND_DATAA search_results;
2704 int err;
2705 char buffer[5] = "C:\\*";
2707 buffer[0] = get_windows_drive();
2708 handle = FindFirstFileA(buffer,&search_results);
2709 ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed\n" );
2710 while (FindNextFileA(handle, &search_results))
2712 /* get to the end of the files */
2714 ok ( FindClose(handle) == TRUE, "Failed to close handle\n");
2715 err = GetLastError();
2716 ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES\n");
2719 static void test_FindFirstFileExA(FINDEX_INFO_LEVELS level, FINDEX_SEARCH_OPS search_ops, DWORD flags)
2721 WIN32_FIND_DATAA search_results;
2722 HANDLE handle;
2723 BOOL ret;
2725 if (!pFindFirstFileExA)
2727 win_skip("FindFirstFileExA() is missing\n");
2728 return;
2731 trace("Running FindFirstFileExA tests with level=%d, search_ops=%d, flags=%u\n",
2732 level, search_ops, flags);
2734 CreateDirectoryA("test-dir", NULL);
2735 _lclose(_lcreat("test-dir\\file1", 0));
2736 _lclose(_lcreat("test-dir\\file2", 0));
2737 CreateDirectoryA("test-dir\\dir1", NULL);
2738 SetLastError(0xdeadbeef);
2739 handle = pFindFirstFileExA("test-dir\\*", level, &search_results, search_ops, NULL, flags);
2740 if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2742 win_skip("FindFirstFileExA is not implemented\n");
2743 goto cleanup;
2745 if ((flags & FIND_FIRST_EX_LARGE_FETCH) && handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
2747 win_skip("FindFirstFileExA flag FIND_FIRST_EX_LARGE_FETCH not supported, skipping test\n");
2748 goto cleanup;
2750 if ((level == FindExInfoBasic) && handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
2752 win_skip("FindFirstFileExA level FindExInfoBasic not supported, skipping test\n");
2753 goto cleanup;
2756 #define CHECK_NAME(fn) (strcmp((fn), "file1") == 0 || strcmp((fn), "file2") == 0 || strcmp((fn), "dir1") == 0)
2757 #define CHECK_LEVEL(fn) (level != FindExInfoBasic || !(fn)[0])
2759 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
2760 ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
2761 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2763 ok(FindNextFileA(handle, &search_results), "Fetching second file failed\n");
2764 ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
2765 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2767 ok(FindNextFileA(handle, &search_results), "Fetching third file failed\n");
2768 ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
2769 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2771 SetLastError(0xdeadbeef);
2772 ret = FindNextFileA(handle, &search_results);
2773 if (!ret && (GetLastError() == ERROR_NO_MORE_FILES) && (search_ops == FindExSearchLimitToDirectories))
2775 skip("File system supports directory filtering\n");
2776 /* Results from the previous call are not cleared */
2777 ok(strcmp(search_results.cFileName, "dir1") == 0, "Third entry should be 'dir1' is %s\n", search_results.cFileName);
2778 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2781 else
2783 ok(ret, "Fetching fourth file failed\n");
2784 ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
2785 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2787 ok(FindNextFileA(handle, &search_results), "Fetching fifth file failed\n");
2788 ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName);
2789 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2791 ok(FindNextFileA(handle, &search_results) == FALSE, "Fetching sixth file should fail\n");
2794 #undef CHECK_NAME
2795 #undef CHECK_LEVEL
2797 FindClose( handle );
2799 /* Most Windows systems seem to ignore the FIND_FIRST_EX_CASE_SENSITIVE flag. Unofficial documentation
2800 * suggests that there are registry keys and that it might depend on the used filesystem. */
2801 SetLastError(0xdeadbeef);
2802 handle = pFindFirstFileExA("TEST-DIR\\*", level, &search_results, search_ops, NULL, flags);
2803 if (flags & FIND_FIRST_EX_CASE_SENSITIVE)
2805 ok(handle != INVALID_HANDLE_VALUE || GetLastError() == ERROR_PATH_NOT_FOUND,
2806 "Unexpected error %x, expected valid handle or ERROR_PATH_NOT_FOUND\n", GetLastError());
2807 trace("FindFirstFileExA flag FIND_FIRST_EX_CASE_SENSITIVE is %signored\n",
2808 (handle == INVALID_HANDLE_VALUE) ? "not " : "");
2810 else
2811 ok(handle != INVALID_HANDLE_VALUE, "Unexpected error %x, expected valid handle\n", GetLastError());
2812 if (handle != INVALID_HANDLE_VALUE)
2813 FindClose( handle );
2815 cleanup:
2816 DeleteFileA("test-dir\\file1");
2817 DeleteFileA("test-dir\\file2");
2818 RemoveDirectoryA("test-dir\\dir1");
2819 RemoveDirectoryA("test-dir");
2822 static int test_Mapfile_createtemp(HANDLE *handle)
2824 SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL);
2825 DeleteFileA(filename);
2826 *handle = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, 0,
2827 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2828 if (*handle != INVALID_HANDLE_VALUE) {
2830 return 1;
2833 return 0;
2836 static void test_MapFile(void)
2838 HANDLE handle;
2839 HANDLE hmap;
2841 ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
2843 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" );
2844 ok( hmap != NULL, "mapping should work, I named it!\n" );
2846 ok( CloseHandle( hmap ), "can't close mapping handle\n");
2848 /* We have to close file before we try new stuff with mapping again.
2849 Else we would always succeed on XP or block descriptors on 95. */
2850 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
2851 ok( hmap != NULL, "We should still be able to map!\n" );
2852 ok( CloseHandle( hmap ), "can't close mapping handle\n");
2853 ok( CloseHandle( handle ), "can't close file handle\n");
2854 handle = NULL;
2856 ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
2858 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
2859 ok( hmap == NULL, "mapped zero size file\n");
2860 ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
2862 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
2863 ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
2864 /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
2865 if ( hmap )
2866 CloseHandle( hmap );
2868 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
2869 ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
2870 /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
2871 if ( hmap )
2872 CloseHandle( hmap );
2874 /* On XP you can now map again, on Win 95 you cannot. */
2876 ok( CloseHandle( handle ), "can't close file handle\n");
2877 ok( DeleteFileA( filename ), "DeleteFile failed after map\n" );
2880 static void test_GetFileType(void)
2882 DWORD type, type2;
2883 HANDLE h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2884 ok( h != INVALID_HANDLE_VALUE, "open %s failed\n", filename );
2885 type = GetFileType(h);
2886 ok( type == FILE_TYPE_DISK, "expected type disk got %d\n", type );
2887 CloseHandle( h );
2888 h = CreateFileA( "nul", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
2889 ok( h != INVALID_HANDLE_VALUE, "open nul failed\n" );
2890 type = GetFileType(h);
2891 ok( type == FILE_TYPE_CHAR, "expected type char for nul got %d\n", type );
2892 CloseHandle( h );
2893 DeleteFileA( filename );
2894 h = GetStdHandle( STD_OUTPUT_HANDLE );
2895 ok( h != INVALID_HANDLE_VALUE, "GetStdHandle failed\n" );
2896 type = GetFileType( (HANDLE)STD_OUTPUT_HANDLE );
2897 type2 = GetFileType( h );
2898 ok(type == type2, "expected type %d for STD_OUTPUT_HANDLE got %d\n", type2, type);
2901 static int completion_count;
2903 static void CALLBACK FileIOComplete(DWORD dwError, DWORD dwBytes, LPOVERLAPPED ovl)
2905 /* printf("(%ld, %ld, %p { %ld, %ld, %ld, %ld, %p })\n", dwError, dwBytes, ovl, ovl->Internal, ovl->InternalHigh, ovl->Offset, ovl->OffsetHigh, ovl->hEvent);*/
2906 ReleaseSemaphore(ovl->hEvent, 1, NULL);
2907 completion_count++;
2910 static void test_async_file_errors(void)
2912 char szFile[MAX_PATH];
2913 HANDLE hSem = CreateSemaphoreW(NULL, 1, 1, NULL);
2914 HANDLE hFile;
2915 LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096);
2916 OVERLAPPED ovl;
2917 S(U(ovl)).Offset = 0;
2918 S(U(ovl)).OffsetHigh = 0;
2919 ovl.hEvent = hSem;
2920 completion_count = 0;
2921 szFile[0] = '\0';
2922 GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini"));
2923 strcat(szFile, "\\win.ini");
2924 hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2925 NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
2926 if (hFile == INVALID_HANDLE_VALUE) /* win9x doesn't like FILE_SHARE_DELETE */
2927 hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2928 NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
2929 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA(%s ...) failed\n", szFile);
2930 while (TRUE)
2932 BOOL res;
2933 DWORD count;
2934 while (WaitForSingleObjectEx(hSem, INFINITE, TRUE) == WAIT_IO_COMPLETION)
2936 res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete);
2937 /*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
2938 if (!res)
2939 break;
2940 if (!GetOverlappedResult(hFile, &ovl, &count, FALSE))
2941 break;
2942 S(U(ovl)).Offset += count;
2943 /* i/o completion routine only called if ReadFileEx returned success.
2944 * we only care about violations of this rule so undo what should have
2945 * been done */
2946 completion_count--;
2948 ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count);
2949 /*printf("Error = %ld\n", GetLastError());*/
2950 HeapFree(GetProcessHeap(), 0, lpBuffer);
2953 static BOOL user_apc_ran;
2954 static void CALLBACK user_apc(ULONG_PTR param)
2956 user_apc_ran = TRUE;
2959 static void test_read_write(void)
2961 DWORD bytes, ret, old_prot;
2962 HANDLE hFile;
2963 char temp_path[MAX_PATH];
2964 char filename[MAX_PATH];
2965 char *mem;
2966 static const char prefix[] = "pfx";
2968 ret = GetTempPathA(MAX_PATH, temp_path);
2969 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
2970 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
2972 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
2973 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
2975 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2976 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
2977 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
2979 user_apc_ran = FALSE;
2980 if (pQueueUserAPC) {
2981 trace("Queueing an user APC\n"); /* verify the file is non alerable */
2982 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
2983 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
2986 SetLastError(12345678);
2987 bytes = 12345678;
2988 ret = WriteFile(hFile, NULL, 0, &bytes, NULL);
2989 ok(ret && GetLastError() == 12345678,
2990 "ret = %d, error %d\n", ret, GetLastError());
2991 ok(!bytes, "bytes = %d\n", bytes);
2993 SetLastError(12345678);
2994 bytes = 12345678;
2995 ret = WriteFile(hFile, NULL, 10, &bytes, NULL);
2996 ok((!ret && GetLastError() == ERROR_INVALID_USER_BUFFER) || /* Win2k */
2997 (ret && GetLastError() == 12345678), /* Win9x */
2998 "ret = %d, error %d\n", ret, GetLastError());
2999 ok(!bytes || /* Win2k */
3000 bytes == 10, /* Win9x */
3001 "bytes = %d\n", bytes);
3003 /* make sure the file contains data */
3004 WriteFile(hFile, "this is the test data", 21, &bytes, NULL);
3005 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
3007 SetLastError(12345678);
3008 bytes = 12345678;
3009 ret = ReadFile(hFile, NULL, 0, &bytes, NULL);
3010 ok(ret && GetLastError() == 12345678,
3011 "ret = %d, error %d\n", ret, GetLastError());
3012 ok(!bytes, "bytes = %d\n", bytes);
3014 SetLastError(12345678);
3015 bytes = 12345678;
3016 ret = ReadFile(hFile, NULL, 10, &bytes, NULL);
3017 ok(!ret && (GetLastError() == ERROR_NOACCESS || /* Win2k */
3018 GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
3019 "ret = %d, error %d\n", ret, GetLastError());
3020 ok(!bytes, "bytes = %d\n", bytes);
3022 ok(user_apc_ran == FALSE, "UserAPC ran, file using alertable io mode\n");
3023 if (pQueueUserAPC)
3024 SleepEx(0, TRUE); /* get rid of apc */
3026 /* test passing protected memory as buffer */
3028 mem = VirtualAlloc( NULL, 0x4000, MEM_COMMIT, PAGE_READWRITE );
3029 ok( mem != NULL, "failed to allocate virtual mem error %u\n", GetLastError() );
3031 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
3032 ok( ret, "WriteFile failed error %u\n", GetLastError() );
3033 ok( bytes == 0x4000, "only wrote %x bytes\n", bytes );
3035 ret = VirtualProtect( mem + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
3036 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3038 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
3039 ok( !ret, "WriteFile succeeded\n" );
3040 ok( GetLastError() == ERROR_INVALID_USER_BUFFER ||
3041 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3042 "wrong error %u\n", GetLastError() );
3043 ok( bytes == 0, "wrote %x bytes\n", bytes );
3045 ret = WriteFile( (HANDLE)0xdead, mem, 0x4000, &bytes, NULL );
3046 ok( !ret, "WriteFile succeeded\n" );
3047 ok( GetLastError() == ERROR_INVALID_HANDLE || /* handle is checked before buffer on NT */
3048 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3049 "wrong error %u\n", GetLastError() );
3050 ok( bytes == 0, "wrote %x bytes\n", bytes );
3052 ret = VirtualProtect( mem, 0x2000, PAGE_NOACCESS, &old_prot );
3053 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3055 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
3056 ok( !ret, "WriteFile succeeded\n" );
3057 ok( GetLastError() == ERROR_INVALID_USER_BUFFER ||
3058 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3059 "wrong error %u\n", GetLastError() );
3060 ok( bytes == 0, "wrote %x bytes\n", bytes );
3062 SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
3064 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3065 ok( !ret, "ReadFile succeeded\n" );
3066 ok( GetLastError() == ERROR_NOACCESS ||
3067 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3068 "wrong error %u\n", GetLastError() );
3069 ok( bytes == 0, "read %x bytes\n", bytes );
3071 ret = VirtualProtect( mem, 0x2000, PAGE_READONLY, &old_prot );
3072 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3074 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3075 ok( !ret, "ReadFile succeeded\n" );
3076 ok( GetLastError() == ERROR_NOACCESS ||
3077 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3078 "wrong error %u\n", GetLastError() );
3079 ok( bytes == 0, "read %x bytes\n", bytes );
3081 ret = VirtualProtect( mem, 0x2000, PAGE_READWRITE, &old_prot );
3082 ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3084 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3085 ok( !ret, "ReadFile succeeded\n" );
3086 ok( GetLastError() == ERROR_NOACCESS ||
3087 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3088 "wrong error %u\n", GetLastError() );
3089 ok( bytes == 0, "read %x bytes\n", bytes );
3091 SetFilePointer( hFile, 0x1234, NULL, FILE_BEGIN );
3092 SetEndOfFile( hFile );
3093 SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
3095 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3096 ok( !ret, "ReadFile succeeded\n" );
3097 ok( GetLastError() == ERROR_NOACCESS ||
3098 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3099 "wrong error %u\n", GetLastError() );
3100 ok( bytes == 0, "read %x bytes\n", bytes );
3102 ret = ReadFile( hFile, mem, 0x2000, &bytes, NULL );
3103 ok( ret, "ReadFile failed error %u\n", GetLastError() );
3104 ok( bytes == 0x1234, "read %x bytes\n", bytes );
3106 ret = ReadFile( hFile, NULL, 1, &bytes, NULL );
3107 ok( !ret, "ReadFile succeeded\n" );
3108 ok( GetLastError() == ERROR_NOACCESS ||
3109 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3110 "wrong error %u\n", GetLastError() );
3111 ok( bytes == 0, "read %x bytes\n", bytes );
3113 VirtualFree( mem, 0, MEM_FREE );
3115 ret = CloseHandle(hFile);
3116 ok( ret, "CloseHandle: error %d\n", GetLastError());
3117 ret = DeleteFileA(filename);
3118 ok( ret, "DeleteFileA: error %d\n", GetLastError());
3121 static void test_OpenFile(void)
3123 HFILE hFile;
3124 OFSTRUCT ofs;
3125 BOOL ret;
3126 DWORD retval;
3128 static const char file[] = "regedit.exe";
3129 static const char foo[] = ".\\foo-bar-foo.baz";
3130 static const char *foo_too_long = ".\\foo-bar-foo.baz+++++++++++++++"
3131 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3132 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3133 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3134 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3135 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
3136 char buff[MAX_PATH];
3137 char buff_long[4*MAX_PATH];
3138 char filled_0xA5[OFS_MAXPATHNAME];
3139 char *p;
3140 UINT length;
3142 /* Check for existing file */
3143 if (!pGetSystemWindowsDirectoryA)
3144 length = GetWindowsDirectoryA(buff, MAX_PATH);
3145 else
3146 length = pGetSystemWindowsDirectoryA(buff, MAX_PATH);
3148 if (length + sizeof(file) < MAX_PATH)
3150 p = buff + strlen(buff);
3151 if (p > buff && p[-1] != '\\') *p++ = '\\';
3152 strcpy( p, file );
3153 memset(&ofs, 0xA5, sizeof(ofs));
3154 SetLastError(0xfaceabee);
3156 hFile = OpenFile(buff, &ofs, OF_EXIST);
3157 ok( hFile == TRUE, "%s not found : %d\n", buff, GetLastError() );
3158 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3159 "GetLastError() returns %d\n", GetLastError() );
3160 ok( ofs.cBytes == sizeof(ofs), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3161 ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3162 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3163 "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n",
3164 ofs.szPathName, buff );
3167 memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
3168 length = GetCurrentDirectoryA(MAX_PATH, buff);
3170 /* Check for nonexistent file */
3171 if (length + sizeof(foo) < MAX_PATH)
3173 p = buff + strlen(buff);
3174 if (p > buff && p[-1] != '\\') *p++ = '\\';
3175 strcpy( p, foo + 2 );
3176 memset(&ofs, 0xA5, sizeof(ofs));
3177 SetLastError(0xfaceabee);
3179 hFile = OpenFile(foo, &ofs, OF_EXIST);
3180 ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
3181 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError() returns %d\n", GetLastError() );
3182 todo_wine
3183 ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3184 ok( ofs.nErrCode == ERROR_FILE_NOT_FOUND, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3185 ok( lstrcmpiA(ofs.szPathName, buff) == 0 || strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
3186 "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n",
3187 ofs.szPathName, buff );
3190 length = GetCurrentDirectoryA(MAX_PATH, buff_long);
3191 length += lstrlenA(foo_too_long + 1);
3193 /* Check for nonexistent file with too long filename */
3194 if (length >= OFS_MAXPATHNAME && length < sizeof(buff_long))
3196 lstrcatA(buff_long, foo_too_long + 1); /* Avoid '.' during concatenation */
3197 memset(&ofs, 0xA5, sizeof(ofs));
3198 SetLastError(0xfaceabee);
3200 hFile = OpenFile(foo_too_long, &ofs, OF_EXIST);
3201 ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
3202 ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_FILENAME_EXCED_RANGE,
3203 "GetLastError() returns %d\n", GetLastError() );
3204 todo_wine
3205 ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3206 ok( ofs.nErrCode == ERROR_INVALID_DATA || ofs.nErrCode == ERROR_FILENAME_EXCED_RANGE,
3207 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3208 ok( strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
3209 "OpenFile returned '%s', but was expected to return string filled with 0xA5\n",
3210 ofs.szPathName );
3213 length = GetCurrentDirectoryA(MAX_PATH, buff) + sizeof(filename);
3215 if (length >= MAX_PATH)
3217 trace("Buffer too small, requested length = %d, but MAX_PATH = %d. Skipping test.\n", length, MAX_PATH);
3218 return;
3220 p = buff + strlen(buff);
3221 if (p > buff && p[-1] != '\\') *p++ = '\\';
3222 strcpy( p, filename );
3224 memset(&ofs, 0xA5, sizeof(ofs));
3225 SetLastError(0xfaceabee);
3226 /* Create an empty file */
3227 hFile = OpenFile(filename, &ofs, OF_CREATE);
3228 ok( hFile != HFILE_ERROR, "OpenFile failed to create nonexistent file\n" );
3229 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3230 "GetLastError() returns %d\n", GetLastError() );
3231 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3232 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3233 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3234 ret = _lclose(hFile);
3235 ok( !ret, "_lclose() returns %d\n", ret );
3236 retval = GetFileAttributesA(filename);
3237 ok( retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %d\n", GetLastError() );
3239 memset(&ofs, 0xA5, sizeof(ofs));
3240 SetLastError(0xfaceabee);
3241 /* Check various opening options: */
3242 /* for reading only, */
3243 hFile = OpenFile(filename, &ofs, OF_READ);
3244 ok( hFile != HFILE_ERROR, "OpenFile failed on read\n" );
3245 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3246 "GetLastError() returns %d\n", GetLastError() );
3247 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3248 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3249 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3250 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3251 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3252 ret = _lclose(hFile);
3253 ok( !ret, "_lclose() returns %d\n", ret );
3255 memset(&ofs, 0xA5, sizeof(ofs));
3256 SetLastError(0xfaceabee);
3257 /* for writing only, */
3258 hFile = OpenFile(filename, &ofs, OF_WRITE);
3259 ok( hFile != HFILE_ERROR, "OpenFile failed on write\n" );
3260 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3261 "GetLastError() returns %d\n", GetLastError() );
3262 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3263 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3264 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3265 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3266 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3267 ret = _lclose(hFile);
3268 ok( !ret, "_lclose() returns %d\n", ret );
3270 memset(&ofs, 0xA5, sizeof(ofs));
3271 SetLastError(0xfaceabee);
3272 /* for reading and writing, */
3273 hFile = OpenFile(filename, &ofs, OF_READWRITE);
3274 ok( hFile != HFILE_ERROR, "OpenFile failed on read/write\n" );
3275 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3276 "GetLastError() returns %d\n", GetLastError() );
3277 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3278 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3279 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3280 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3281 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3282 ret = _lclose(hFile);
3283 ok( !ret, "_lclose() returns %d\n", ret );
3285 memset(&ofs, 0xA5, sizeof(ofs));
3286 SetLastError(0xfaceabee);
3287 /* for checking file presence. */
3288 hFile = OpenFile(filename, &ofs, OF_EXIST);
3289 ok( hFile == 1, "OpenFile failed on finding our created file\n" );
3290 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3291 "GetLastError() returns %d\n", GetLastError() );
3292 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3293 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3294 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3295 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3296 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3298 memset(&ofs, 0xA5, sizeof(ofs));
3299 SetLastError(0xfaceabee);
3300 /* Delete the file and make sure it doesn't exist anymore */
3301 hFile = OpenFile(filename, &ofs, OF_DELETE);
3302 ok( hFile == 1, "OpenFile failed on delete (%d)\n", hFile );
3303 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3304 "GetLastError() returns %d\n", GetLastError() );
3305 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3306 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3307 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3308 ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3309 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3311 retval = GetFileAttributesA(filename);
3312 ok( retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file\n" );
3315 static void test_overlapped(void)
3317 OVERLAPPED ov;
3318 DWORD r, result;
3320 /* GetOverlappedResult crashes if the 2nd or 3rd param are NULL */
3321 if (0) /* tested: WinXP */
3323 GetOverlappedResult(0, NULL, &result, FALSE);
3324 GetOverlappedResult(0, &ov, NULL, FALSE);
3325 GetOverlappedResult(0, NULL, NULL, FALSE);
3328 memset( &ov, 0, sizeof ov );
3329 result = 1;
3330 r = GetOverlappedResult(0, &ov, &result, 0);
3331 if (r)
3332 ok( result == 0, "wrong result %u\n", result );
3333 else /* win9x */
3334 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3336 result = 0;
3337 ov.Internal = 0;
3338 ov.InternalHigh = 0xabcd;
3339 r = GetOverlappedResult(0, &ov, &result, 0);
3340 if (r)
3341 ok( result == 0xabcd, "wrong result %u\n", result );
3342 else /* win9x */
3343 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3345 SetLastError( 0xb00 );
3346 result = 0;
3347 ov.Internal = STATUS_INVALID_HANDLE;
3348 ov.InternalHigh = 0xabcd;
3349 r = GetOverlappedResult(0, &ov, &result, 0);
3350 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3351 ok( r == FALSE, "should return false\n");
3352 ok( result == 0xabcd || result == 0 /* win9x */, "wrong result %u\n", result );
3354 SetLastError( 0xb00 );
3355 result = 0;
3356 ov.Internal = STATUS_PENDING;
3357 ov.InternalHigh = 0xabcd;
3358 r = GetOverlappedResult(0, &ov, &result, 0);
3359 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
3360 "wrong error %u\n", GetLastError() );
3361 ok( r == FALSE, "should return false\n");
3362 ok( result == 0, "wrong result %u\n", result );
3364 SetLastError( 0xb00 );
3365 ov.hEvent = CreateEventW( NULL, 1, 1, NULL );
3366 ov.Internal = STATUS_PENDING;
3367 ov.InternalHigh = 0xabcd;
3368 r = GetOverlappedResult(0, &ov, &result, 0);
3369 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
3370 "wrong error %u\n", GetLastError() );
3371 ok( r == FALSE, "should return false\n");
3373 ResetEvent( ov.hEvent );
3375 SetLastError( 0xb00 );
3376 ov.Internal = STATUS_PENDING;
3377 ov.InternalHigh = 0;
3378 r = GetOverlappedResult(0, &ov, &result, 0);
3379 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
3380 "wrong error %u\n", GetLastError() );
3381 ok( r == FALSE, "should return false\n");
3383 r = CloseHandle( ov.hEvent );
3384 ok( r == TRUE, "close handle failed\n");
3387 static void test_RemoveDirectory(void)
3389 int rc;
3390 char directory[] = "removeme";
3392 rc = CreateDirectoryA(directory, NULL);
3393 ok( rc, "Createdirectory failed, gle=%d\n", GetLastError() );
3395 rc = SetCurrentDirectoryA(directory);
3396 ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
3398 rc = RemoveDirectoryA(".");
3399 if (!rc)
3401 rc = SetCurrentDirectoryA("..");
3402 ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
3404 rc = RemoveDirectoryA(directory);
3405 ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
3409 static BOOL check_file_time( const FILETIME *ft1, const FILETIME *ft2, UINT tolerance )
3411 ULONGLONG t1 = ((ULONGLONG)ft1->dwHighDateTime << 32) | ft1->dwLowDateTime;
3412 ULONGLONG t2 = ((ULONGLONG)ft2->dwHighDateTime << 32) | ft2->dwLowDateTime;
3413 return abs(t1 - t2) <= tolerance;
3416 static void test_ReplaceFileA(void)
3418 char replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
3419 HANDLE hReplacedFile, hReplacementFile, hBackupFile;
3420 static const char replacedData[] = "file-to-replace";
3421 static const char replacementData[] = "new-file";
3422 static const char backupData[] = "backup-file";
3423 FILETIME ftReplaced, ftReplacement, ftBackup;
3424 static const char prefix[] = "pfx";
3425 char temp_path[MAX_PATH];
3426 DWORD ret;
3427 BOOL retok, removeBackup = FALSE;
3429 if (!pReplaceFileA)
3431 win_skip("ReplaceFileA() is missing\n");
3432 return;
3435 ret = GetTempPathA(MAX_PATH, temp_path);
3436 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
3437 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
3439 ret = GetTempFileNameA(temp_path, prefix, 0, replaced);
3440 ok(ret != 0, "GetTempFileNameA error (replaced) %d\n", GetLastError());
3442 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3443 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3445 ret = GetTempFileNameA(temp_path, prefix, 0, backup);
3446 ok(ret != 0, "GetTempFileNameA error (backup) %d\n", GetLastError());
3448 /* place predictable data in the file to be replaced */
3449 hReplacedFile = CreateFileA(replaced, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3450 ok(hReplacedFile != INVALID_HANDLE_VALUE,
3451 "failed to open replaced file\n");
3452 retok = WriteFile(hReplacedFile, replacedData, sizeof(replacedData), &ret, NULL );
3453 ok( retok && ret == sizeof(replacedData),
3454 "WriteFile error (replaced) %d\n", GetLastError());
3455 ok(GetFileSize(hReplacedFile, NULL) == sizeof(replacedData),
3456 "replaced file has wrong size\n");
3457 /* place predictable data in the file to be the replacement */
3458 hReplacementFile = CreateFileA(replacement, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3459 ok(hReplacementFile != INVALID_HANDLE_VALUE,
3460 "failed to open replacement file\n");
3461 retok = WriteFile(hReplacementFile, replacementData, sizeof(replacementData), &ret, NULL );
3462 ok( retok && ret == sizeof(replacementData),
3463 "WriteFile error (replacement) %d\n", GetLastError());
3464 ok(GetFileSize(hReplacementFile, NULL) == sizeof(replacementData),
3465 "replacement file has wrong size\n");
3466 /* place predictable data in the backup file (to be over-written) */
3467 hBackupFile = CreateFileA(backup, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3468 ok(hBackupFile != INVALID_HANDLE_VALUE,
3469 "failed to open backup file\n");
3470 retok = WriteFile(hBackupFile, backupData, sizeof(backupData), &ret, NULL );
3471 ok( retok && ret == sizeof(backupData),
3472 "WriteFile error (replacement) %d\n", GetLastError());
3473 ok(GetFileSize(hBackupFile, NULL) == sizeof(backupData),
3474 "backup file has wrong size\n");
3475 /* change the filetime on the "replaced" file to ensure that it changes */
3476 ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3477 ok( ret, "GetFileTime error (replaced) %d\n", GetLastError());
3478 ftReplaced.dwLowDateTime -= 600000000; /* 60 second */
3479 ret = SetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3480 ok( ret, "SetFileTime error (replaced) %d\n", GetLastError());
3481 GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced); /* get the actual time back */
3482 CloseHandle(hReplacedFile);
3483 /* change the filetime on the backup to ensure that it changes */
3484 ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3485 ok( ret, "GetFileTime error (backup) %d\n", GetLastError());
3486 ftBackup.dwLowDateTime -= 1200000000; /* 120 second */
3487 ret = SetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3488 ok( ret, "SetFileTime error (backup) %d\n", GetLastError());
3489 GetFileTime(hBackupFile, NULL, NULL, &ftBackup); /* get the actual time back */
3490 CloseHandle(hBackupFile);
3491 /* get the filetime on the replacement file to perform checks */
3492 ret = GetFileTime(hReplacementFile, NULL, NULL, &ftReplacement);
3493 ok( ret, "GetFileTime error (replacement) %d\n", GetLastError());
3494 CloseHandle(hReplacementFile);
3496 /* perform replacement w/ backup
3497 * TODO: flags are not implemented
3499 SetLastError(0xdeadbeef);
3500 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3501 ok(ret, "ReplaceFileA: unexpected error %d\n", GetLastError());
3502 /* make sure that the backup has the size of the old "replaced" file */
3503 hBackupFile = CreateFileA(backup, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3504 ok(hBackupFile != INVALID_HANDLE_VALUE,
3505 "failed to open backup file\n");
3506 ret = GetFileSize(hBackupFile, NULL);
3507 ok(ret == sizeof(replacedData),
3508 "backup file has wrong size %d\n", ret);
3509 /* make sure that the "replaced" file has the size of the replacement file */
3510 hReplacedFile = CreateFileA(replaced, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3511 ok(hReplacedFile != INVALID_HANDLE_VALUE,
3512 "failed to open replaced file: %d\n", GetLastError());
3513 if (hReplacedFile != INVALID_HANDLE_VALUE)
3515 ret = GetFileSize(hReplacedFile, NULL);
3516 ok(ret == sizeof(replacementData),
3517 "replaced file has wrong size %d\n", ret);
3518 /* make sure that the replacement file no-longer exists */
3519 hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3520 ok(hReplacementFile == INVALID_HANDLE_VALUE,
3521 "unexpected error, replacement file should not exist %d\n", GetLastError());
3522 /* make sure that the backup has the old "replaced" filetime */
3523 ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3524 ok( ret, "GetFileTime error (backup %d\n", GetLastError());
3525 ok(check_file_time(&ftBackup, &ftReplaced, 20000000), "backup file has wrong filetime\n");
3526 CloseHandle(hBackupFile);
3527 /* make sure that the "replaced" has the old replacement filetime */
3528 ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3529 ok( ret, "GetFileTime error (backup %d\n", GetLastError());
3530 ok(check_file_time(&ftReplaced, &ftReplacement, 20000000),
3531 "replaced file has wrong filetime %x%08x / %x%08x\n",
3532 ftReplaced.dwHighDateTime, ftReplaced.dwLowDateTime,
3533 ftReplacement.dwHighDateTime, ftReplacement.dwLowDateTime );
3534 CloseHandle(hReplacedFile);
3536 else
3537 skip("couldn't open replacement file, skipping tests\n");
3539 /* re-create replacement file for pass w/o backup (blank) */
3540 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3541 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3542 /* perform replacement w/o backup
3543 * TODO: flags are not implemented
3545 SetLastError(0xdeadbeef);
3546 ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
3547 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3548 "ReplaceFileA: unexpected error %d\n", GetLastError());
3550 /* re-create replacement file for pass w/ backup (backup-file not existing) */
3551 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3552 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3553 ret = DeleteFileA(backup);
3554 ok(ret, "DeleteFileA: error (backup) %d\n", GetLastError());
3555 /* perform replacement w/ backup (no pre-existing backup)
3556 * TODO: flags are not implemented
3558 SetLastError(0xdeadbeef);
3559 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3560 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3561 "ReplaceFileA: unexpected error %d\n", GetLastError());
3562 if (ret)
3563 removeBackup = TRUE;
3565 /* re-create replacement file for pass w/ no permissions to "replaced" */
3566 ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3567 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3568 ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_READONLY);
3569 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3570 "SetFileAttributesA: error setting to read only %d\n", GetLastError());
3571 /* perform replacement w/ backup (no permission to "replaced")
3572 * TODO: flags are not implemented
3574 SetLastError(0xdeadbeef);
3575 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3576 ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED, "ReplaceFileA: unexpected error %d\n", GetLastError());
3577 /* make sure that the replacement file still exists */
3578 hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3579 ok(hReplacementFile != INVALID_HANDLE_VALUE ||
3580 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* win2k */
3581 "unexpected error, replacement file should still exist %d\n", GetLastError());
3582 CloseHandle(hReplacementFile);
3583 ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_NORMAL);
3584 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3585 "SetFileAttributesA: error setting to normal %d\n", GetLastError());
3587 /* replacement file still exists, make pass w/o "replaced" */
3588 ret = DeleteFileA(replaced);
3589 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3590 "DeleteFileA: error (replaced) %d\n", GetLastError());
3591 /* perform replacement w/ backup (no pre-existing backup or "replaced")
3592 * TODO: flags are not implemented
3594 SetLastError(0xdeadbeef);
3595 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
3596 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
3597 GetLastError() == ERROR_ACCESS_DENIED),
3598 "ReplaceFileA: unexpected error %d\n", GetLastError());
3600 /* perform replacement w/o existing "replacement" file
3601 * TODO: flags are not implemented
3603 SetLastError(0xdeadbeef);
3604 ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
3605 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
3606 GetLastError() == ERROR_ACCESS_DENIED),
3607 "ReplaceFileA: unexpected error %d\n", GetLastError());
3608 DeleteFileA( replacement );
3611 * if the first round (w/ backup) worked then as long as there is no
3612 * failure then there is no need to check this round (w/ backup is the
3613 * more complete case)
3616 /* delete temporary files, replacement and replaced are already deleted */
3617 if (removeBackup)
3619 ret = DeleteFileA(backup);
3620 ok(ret ||
3621 broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
3622 "DeleteFileA: error (backup) %d\n", GetLastError());
3627 * ReplaceFileW is a simpler case of ReplaceFileA, there is no
3628 * need to be as thorough.
3630 static void test_ReplaceFileW(void)
3632 WCHAR replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
3633 static const WCHAR prefix[] = {'p','f','x',0};
3634 WCHAR temp_path[MAX_PATH];
3635 DWORD ret;
3636 BOOL removeBackup = FALSE;
3638 if (!pReplaceFileW)
3640 win_skip("ReplaceFileW() is missing\n");
3641 return;
3644 ret = GetTempPathW(MAX_PATH, temp_path);
3645 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3647 win_skip("GetTempPathW is not available\n");
3648 return;
3650 ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
3651 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
3653 ret = GetTempFileNameW(temp_path, prefix, 0, replaced);
3654 ok(ret != 0, "GetTempFileNameW error (replaced) %d\n", GetLastError());
3656 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3657 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3659 ret = GetTempFileNameW(temp_path, prefix, 0, backup);
3660 ok(ret != 0, "GetTempFileNameW error (backup) %d\n", GetLastError());
3662 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3663 ok(ret, "ReplaceFileW: error %d\n", GetLastError());
3665 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3666 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3667 ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0);
3668 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3669 "ReplaceFileW: error %d\n", GetLastError());
3671 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3672 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3673 ret = DeleteFileW(backup);
3674 ok(ret, "DeleteFileW: error (backup) %d\n", GetLastError());
3675 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3676 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3677 "ReplaceFileW: error %d\n", GetLastError());
3679 ret = GetTempFileNameW(temp_path, prefix, 0, replacement);
3680 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError());
3681 ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_READONLY);
3682 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3683 "SetFileAttributesW: error setting to read only %d\n", GetLastError());
3685 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3686 ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED,
3687 "ReplaceFileW: unexpected error %d\n", GetLastError());
3688 ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_NORMAL);
3689 ok(ret || GetLastError() == ERROR_ACCESS_DENIED,
3690 "SetFileAttributesW: error setting to normal %d\n", GetLastError());
3691 if (ret)
3692 removeBackup = TRUE;
3694 ret = DeleteFileW(replaced);
3695 ok(ret, "DeleteFileW: error (replaced) %d\n", GetLastError());
3696 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0);
3697 ok(!ret, "ReplaceFileW: error %d\n", GetLastError());
3699 ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0);
3700 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
3701 GetLastError() == ERROR_ACCESS_DENIED),
3702 "ReplaceFileW: unexpected error %d\n", GetLastError());
3703 DeleteFileW( replacement );
3705 if (removeBackup)
3707 ret = DeleteFileW(backup);
3708 ok(ret ||
3709 broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
3710 "DeleteFileW: error (backup) %d\n", GetLastError());
3714 static void test_CreateFile(void)
3716 static const struct test_data
3718 DWORD disposition, access, error, clean_up;
3719 } td[] =
3721 /* 0 */ { 0, 0, ERROR_INVALID_PARAMETER, 0 },
3722 /* 1 */ { 0, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 },
3723 /* 2 */ { 0, GENERIC_READ|GENERIC_WRITE, ERROR_INVALID_PARAMETER, 0 },
3724 /* 3 */ { CREATE_NEW, 0, ERROR_FILE_EXISTS, 1 },
3725 /* 4 */ { CREATE_NEW, 0, 0, 1 },
3726 /* 5 */ { CREATE_NEW, GENERIC_READ, 0, 1 },
3727 /* 6 */ { CREATE_NEW, GENERIC_WRITE, 0, 1 },
3728 /* 7 */ { CREATE_NEW, GENERIC_READ|GENERIC_WRITE, 0, 0 },
3729 /* 8 */ { CREATE_ALWAYS, 0, 0, 0 },
3730 /* 9 */ { CREATE_ALWAYS, GENERIC_READ, 0, 0 },
3731 /* 10*/ { CREATE_ALWAYS, GENERIC_WRITE, 0, 0 },
3732 /* 11*/ { CREATE_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 1 },
3733 /* 12*/ { OPEN_EXISTING, 0, ERROR_FILE_NOT_FOUND, 0 },
3734 /* 13*/ { CREATE_ALWAYS, 0, 0, 0 },
3735 /* 14*/ { OPEN_EXISTING, 0, 0, 0 },
3736 /* 15*/ { OPEN_EXISTING, GENERIC_READ, 0, 0 },
3737 /* 16*/ { OPEN_EXISTING, GENERIC_WRITE, 0, 0 },
3738 /* 17*/ { OPEN_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 1 },
3739 /* 18*/ { OPEN_ALWAYS, 0, 0, 0 },
3740 /* 19*/ { OPEN_ALWAYS, GENERIC_READ, 0, 0 },
3741 /* 20*/ { OPEN_ALWAYS, GENERIC_WRITE, 0, 0 },
3742 /* 21*/ { OPEN_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 0 },
3743 /* 22*/ { TRUNCATE_EXISTING, 0, ERROR_INVALID_PARAMETER, 0 },
3744 /* 23*/ { TRUNCATE_EXISTING, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 },
3745 /* 24*/ { TRUNCATE_EXISTING, GENERIC_WRITE, 0, 0 },
3746 /* 25*/ { TRUNCATE_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 0 },
3747 /* 26*/ { TRUNCATE_EXISTING, FILE_WRITE_DATA, ERROR_INVALID_PARAMETER, 0 }
3749 char temp_path[MAX_PATH];
3750 char file_name[MAX_PATH];
3751 DWORD i, ret, written;
3752 HANDLE hfile;
3754 GetTempPathA(MAX_PATH, temp_path);
3755 GetTempFileNameA(temp_path, "tmp", 0, file_name);
3757 i = strlen(temp_path);
3758 if (i && temp_path[i - 1] == '\\') temp_path[i - 1] = 0;
3760 for (i = 0; i <= 5; i++)
3762 SetLastError(0xdeadbeef);
3763 hfile = CreateFileA(temp_path, GENERIC_READ, 0, NULL, i, 0, 0);
3764 ok(hfile == INVALID_HANDLE_VALUE, "CreateFile should fail\n");
3765 if (i == 0 || i == 5)
3767 /* FIXME: remove once Wine is fixed */
3768 if (i == 5) todo_wine
3769 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3770 else
3771 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3773 else
3775 /* FIXME: remove once Wine is fixed */
3776 if (i == 1) todo_wine
3777 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3778 else
3779 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3782 SetLastError(0xdeadbeef);
3783 hfile = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, i, 0, 0);
3784 ok(hfile == INVALID_HANDLE_VALUE, "CreateFile should fail\n");
3785 if (i == 0)
3786 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
3787 else
3789 /* FIXME: remove once Wine is fixed */
3790 if (i == 1) todo_wine
3791 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3792 else
3793 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3797 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3799 SetLastError(0xdeadbeef);
3800 hfile = CreateFileA(file_name, td[i].access, 0, NULL, td[i].disposition, 0, 0);
3801 if (!td[i].error)
3803 ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
3804 written = 0xdeadbeef;
3805 SetLastError(0xdeadbeef);
3806 ret = WriteFile(hfile, &td[i].error, sizeof(td[i].error), &written, NULL);
3807 if (td[i].access & GENERIC_WRITE)
3808 ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
3809 else
3811 ok(!ret, "%d: WriteFile should fail\n", i);
3812 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
3814 CloseHandle(hfile);
3816 else
3818 /* FIXME: remove the condition below once Wine is fixed */
3819 if (td[i].disposition == TRUNCATE_EXISTING && !(td[i].access & GENERIC_WRITE))
3821 todo_wine
3823 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
3824 ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError());
3826 CloseHandle(hfile);
3828 else
3830 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
3831 ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError());
3835 if (td[i].clean_up) DeleteFileA(file_name);
3838 DeleteFileA(file_name);
3841 static void test_GetFileInformationByHandleEx(void)
3843 int i;
3844 char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024], *strPtr;
3845 BOOL ret;
3846 DWORD ret2, written;
3847 HANDLE directory, file;
3848 FILE_ID_BOTH_DIR_INFO *bothDirInfo;
3849 FILE_BASIC_INFO *basicInfo;
3850 FILE_STANDARD_INFO *standardInfo;
3851 FILE_NAME_INFO *nameInfo;
3852 LARGE_INTEGER prevWrite;
3853 FILE_IO_PRIORITY_HINT_INFO priohintinfo;
3854 FILE_ALLOCATION_INFO allocinfo;
3855 FILE_DISPOSITION_INFO dispinfo;
3856 FILE_END_OF_FILE_INFO eofinfo;
3857 FILE_RENAME_INFO renameinfo;
3859 struct {
3860 FILE_INFO_BY_HANDLE_CLASS handleClass;
3861 void *ptr;
3862 DWORD size;
3863 DWORD errorCode;
3864 } checks[] = {
3865 {0xdeadbeef, NULL, 0, ERROR_INVALID_PARAMETER},
3866 {FileIdBothDirectoryInfo, NULL, 0, ERROR_BAD_LENGTH},
3867 {FileIdBothDirectoryInfo, NULL, sizeof(buffer), ERROR_NOACCESS},
3868 {FileIdBothDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH}};
3870 if (!pGetFileInformationByHandleEx)
3872 win_skip("GetFileInformationByHandleEx is missing.\n");
3873 return;
3876 ret2 = GetTempPathA(sizeof(tempPath), tempPath);
3877 ok(ret2, "GetFileInformationByHandleEx: GetTempPathA failed, got error %u.\n", GetLastError());
3879 /* ensure the existence of a file in the temp folder */
3880 ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
3881 ok(ret2, "GetFileInformationByHandleEx: GetTempFileNameA failed, got error %u.\n", GetLastError());
3882 ret2 = GetFileAttributesA(tempFileName);
3883 ok(ret2 != INVALID_FILE_ATTRIBUTES, "GetFileInformationByHandleEx: "
3884 "GetFileAttributesA failed to find the temp file, got error %u.\n", GetLastError());
3886 directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3887 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
3888 ok(directory != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp folder, "
3889 "got error %u.\n", GetLastError());
3891 for (i = 0; i < sizeof(checks) / sizeof(checks[0]); i += 1)
3893 SetLastError(0xdeadbeef);
3894 ret = pGetFileInformationByHandleEx(directory, checks[i].handleClass, checks[i].ptr, checks[i].size);
3895 ok(!ret && GetLastError() == checks[i].errorCode, "GetFileInformationByHandleEx: expected error %u, "
3896 "got %u.\n", checks[i].errorCode, GetLastError());
3899 while (TRUE)
3901 memset(buffer, 0xff, sizeof(buffer));
3902 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
3903 if (!ret && GetLastError() == ERROR_NO_MORE_FILES)
3904 break;
3905 ok(ret, "GetFileInformationByHandleEx: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
3906 if (!ret)
3907 break;
3908 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
3909 while (TRUE)
3911 ok(bothDirInfo->FileAttributes != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file attributes.\n");
3912 ok(bothDirInfo->FileId.u.LowPart != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file id.\n");
3913 ok(bothDirInfo->FileNameLength != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file name length.\n");
3914 if (!bothDirInfo->NextEntryOffset)
3915 break;
3916 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
3920 CloseHandle(directory);
3922 file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3923 NULL, OPEN_EXISTING, 0, NULL);
3924 ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
3925 "got error %u.\n", GetLastError());
3927 /* Test FileBasicInfo; make sure the write time changes when a file is updated */
3928 memset(buffer, 0xff, sizeof(buffer));
3929 ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer));
3930 ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError());
3931 basicInfo = (FILE_BASIC_INFO *)buffer;
3932 prevWrite = basicInfo->LastWriteTime;
3933 CloseHandle(file);
3935 Sleep(30); /* Make sure a new write time is different from the previous */
3937 /* Write something to the file, to make sure the write time has changed */
3938 file = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3939 NULL, OPEN_EXISTING, 0, NULL);
3940 ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
3941 "got error %u.\n", GetLastError());
3942 ret = WriteFile(file, tempFileName, strlen(tempFileName), &written, NULL);
3943 ok(ret, "GetFileInformationByHandleEx: Write failed\n");
3944 CloseHandle(file);
3946 file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3947 NULL, OPEN_EXISTING, 0, NULL);
3948 ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
3949 "got error %u.\n", GetLastError());
3951 memset(buffer, 0xff, sizeof(buffer));
3952 ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer));
3953 ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError());
3954 basicInfo = (FILE_BASIC_INFO *)buffer;
3955 /* Could also check that the creation time didn't change - on windows
3956 * it doesn't, but on wine, it does change even if it shouldn't. */
3957 ok(basicInfo->LastWriteTime.QuadPart != prevWrite.QuadPart,
3958 "GetFileInformationByHandleEx: last write time didn't change\n");
3960 /* Test FileStandardInfo, check some basic parameters */
3961 memset(buffer, 0xff, sizeof(buffer));
3962 ret = pGetFileInformationByHandleEx(file, FileStandardInfo, buffer, sizeof(buffer));
3963 ok(ret, "GetFileInformationByHandleEx: failed to get FileStandardInfo, %u\n", GetLastError());
3964 standardInfo = (FILE_STANDARD_INFO *)buffer;
3965 ok(standardInfo->NumberOfLinks == 1, "GetFileInformationByHandleEx: Unexpcted number of links\n");
3966 ok(standardInfo->DeletePending == FALSE, "GetFileInformationByHandleEx: Unexpcted pending delete\n");
3967 ok(standardInfo->Directory == FALSE, "GetFileInformationByHandleEx: Incorrect directory flag\n");
3969 /* Test FileNameInfo */
3970 memset(buffer, 0xff, sizeof(buffer));
3971 ret = pGetFileInformationByHandleEx(file, FileNameInfo, buffer, sizeof(buffer));
3972 ok(ret, "GetFileInformationByHandleEx: failed to get FileNameInfo, %u\n", GetLastError());
3973 nameInfo = (FILE_NAME_INFO *)buffer;
3974 strPtr = strchr(tempFileName, '\\');
3975 ok(strPtr != NULL, "GetFileInformationByHandleEx: Temp filename didn't contain backslash\n");
3976 ok(nameInfo->FileNameLength == strlen(strPtr) * 2,
3977 "GetFileInformationByHandleEx: Incorrect file name length\n");
3978 for (i = 0; i < nameInfo->FileNameLength/2; i++)
3979 ok(strPtr[i] == nameInfo->FileName[i], "Incorrect filename char %d: %c vs %c\n",
3980 i, strPtr[i], nameInfo->FileName[i]);
3982 /* invalid classes */
3983 SetLastError(0xdeadbeef);
3984 ret = pGetFileInformationByHandleEx(file, FileEndOfFileInfo, &eofinfo, sizeof(eofinfo));
3985 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3987 SetLastError(0xdeadbeef);
3988 ret = pGetFileInformationByHandleEx(file, FileIoPriorityHintInfo, &priohintinfo, sizeof(priohintinfo));
3989 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3991 SetLastError(0xdeadbeef);
3992 ret = pGetFileInformationByHandleEx(file, FileAllocationInfo, &allocinfo, sizeof(allocinfo));
3993 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3995 SetLastError(0xdeadbeef);
3996 ret = pGetFileInformationByHandleEx(file, FileDispositionInfo, &dispinfo, sizeof(dispinfo));
3997 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3999 SetLastError(0xdeadbeef);
4000 ret = pGetFileInformationByHandleEx(file, FileRenameInfo, &renameinfo, sizeof(renameinfo));
4001 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
4003 CloseHandle(file);
4004 DeleteFileA(tempFileName);
4007 static void test_OpenFileById(void)
4009 char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[256], tickCount[256];
4010 WCHAR tempFileNameW[MAX_PATH];
4011 BOOL ret, found;
4012 DWORD ret2, count, tempFileNameLen;
4013 HANDLE directory, handle, tempFile;
4014 FILE_ID_BOTH_DIR_INFO *bothDirInfo;
4015 FILE_ID_DESCRIPTOR fileIdDescr;
4017 if (!pGetFileInformationByHandleEx || !pOpenFileById)
4019 win_skip("GetFileInformationByHandleEx or OpenFileById is missing.\n");
4020 return;
4023 ret2 = GetTempPathA(sizeof(tempPath), tempPath);
4024 ok(ret2, "OpenFileById: GetTempPath failed, got error %u.\n", GetLastError());
4026 /* ensure the existence of a file in the temp folder */
4027 ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
4028 ok(ret2, "OpenFileById: GetTempFileNameA failed, got error %u.\n", GetLastError());
4029 ret2 = GetFileAttributesA(tempFileName);
4030 ok(ret2 != INVALID_FILE_ATTRIBUTES,
4031 "OpenFileById: GetFileAttributesA failed to find the temp file, got error %u\n", GetLastError());
4033 ret2 = MultiByteToWideChar(CP_ACP, 0, tempFileName + strlen(tempPath), -1, tempFileNameW, sizeof(tempFileNameW)/sizeof(tempFileNameW[0]));
4034 ok(ret2, "OpenFileById: MultiByteToWideChar failed to convert tempFileName, got error %u.\n", GetLastError());
4035 tempFileNameLen = ret2 - 1;
4037 tempFile = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4038 ok(tempFile != INVALID_HANDLE_VALUE, "OpenFileById: failed to create a temp file, "
4039 "got error %u.\n", GetLastError());
4040 ret2 = sprintf(tickCount, "%u", GetTickCount());
4041 ret = WriteFile(tempFile, tickCount, ret2, &count, NULL);
4042 ok(ret, "OpenFileById: WriteFile failed, got error %u.\n", GetLastError());
4043 CloseHandle(tempFile);
4045 directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4046 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4047 ok(directory != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder, "
4048 "got error %u.\n", GetLastError());
4050 /* get info about the temp folder itself */
4051 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
4052 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
4053 ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
4054 ok(bothDirInfo->FileNameLength == sizeof(WCHAR) && bothDirInfo->FileName[0] == '.',
4055 "OpenFileById: failed to return the temp folder at the first entry, got error %u.\n", GetLastError());
4057 /* open the temp folder itself */
4058 fileIdDescr.dwSize = sizeof(fileIdDescr);
4059 fileIdDescr.Type = FileIdType;
4060 U(fileIdDescr).FileId = bothDirInfo->FileId;
4061 handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
4062 todo_wine
4063 ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder itself, got error %u.\n", GetLastError());
4064 CloseHandle(handle);
4066 /* find the temp file in the temp folder */
4067 found = FALSE;
4068 while (!found)
4070 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
4071 ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
4072 if (!ret)
4073 break;
4074 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
4075 while (TRUE)
4077 if (tempFileNameLen == bothDirInfo->FileNameLength / sizeof(WCHAR) &&
4078 memcmp(tempFileNameW, bothDirInfo->FileName, bothDirInfo->FileNameLength) == 0)
4080 found = TRUE;
4081 break;
4083 if (!bothDirInfo->NextEntryOffset)
4084 break;
4085 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
4088 ok(found, "OpenFileById: failed to find the temp file in the temp folder.\n");
4090 SetLastError(0xdeadbeef);
4091 handle = pOpenFileById(directory, NULL, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
4092 ok(handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
4093 "OpenFileById: expected ERROR_INVALID_PARAMETER, got error %u.\n", GetLastError());
4095 fileIdDescr.dwSize = sizeof(fileIdDescr);
4096 fileIdDescr.Type = FileIdType;
4097 U(fileIdDescr).FileId = bothDirInfo->FileId;
4098 handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
4099 ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the file, got error %u.\n", GetLastError());
4101 ret = ReadFile(handle, buffer, sizeof(buffer), &count, NULL);
4102 buffer[count] = 0;
4103 ok(ret, "OpenFileById: ReadFile failed, got error %u.\n", GetLastError());
4104 ok(strcmp(tickCount, buffer) == 0, "OpenFileById: invalid contents of the temp file.\n");
4106 CloseHandle(handle);
4107 CloseHandle(directory);
4108 DeleteFileA(tempFileName);
4111 static void test_SetFileValidData(void)
4113 BOOL ret;
4114 HANDLE handle;
4115 DWORD error, count;
4116 char path[MAX_PATH], filename[MAX_PATH];
4117 TOKEN_PRIVILEGES privs;
4118 HANDLE token = NULL;
4120 if (!pSetFileValidData)
4122 win_skip("SetFileValidData is missing\n");
4123 return;
4125 GetTempPathA(sizeof(path), path);
4126 GetTempFileNameA(path, "tst", 0, filename);
4127 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
4128 WriteFile(handle, "test", sizeof("test") - 1, &count, NULL);
4129 CloseHandle(handle);
4131 SetLastError(0xdeadbeef);
4132 ret = pSetFileValidData(INVALID_HANDLE_VALUE, 0);
4133 error = GetLastError();
4134 ok(!ret, "SetFileValidData succeeded\n");
4135 ok(error == ERROR_INVALID_HANDLE, "got %u\n", error);
4137 SetLastError(0xdeadbeef);
4138 ret = pSetFileValidData(INVALID_HANDLE_VALUE, -1);
4139 error = GetLastError();
4140 ok(!ret, "SetFileValidData succeeded\n");
4141 ok(error == ERROR_INVALID_HANDLE, "got %u\n", error);
4143 /* file opened for reading */
4144 handle = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
4146 SetLastError(0xdeadbeef);
4147 ret = pSetFileValidData(handle, 0);
4148 ok(!ret, "SetFileValidData succeeded\n");
4149 error = GetLastError();
4150 ok(error == ERROR_ACCESS_DENIED, "got %u\n", error);
4152 SetLastError(0xdeadbeef);
4153 ret = pSetFileValidData(handle, -1);
4154 error = GetLastError();
4155 ok(!ret, "SetFileValidData succeeded\n");
4156 ok(error == ERROR_ACCESS_DENIED, "got %u\n", error);
4157 CloseHandle(handle);
4159 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
4161 SetLastError(0xdeadbeef);
4162 ret = pSetFileValidData(handle, 0);
4163 error = GetLastError();
4164 ok(!ret, "SetFileValidData succeeded\n");
4165 todo_wine ok(error == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", error);
4166 CloseHandle(handle);
4168 privs.PrivilegeCount = 1;
4169 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
4171 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token) ||
4172 !LookupPrivilegeValueA(NULL, SE_MANAGE_VOLUME_NAME, &privs.Privileges[0].Luid) ||
4173 !AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL) ||
4174 GetLastError() == ERROR_NOT_ALL_ASSIGNED)
4176 win_skip("cannot enable SE_MANAGE_VOLUME_NAME privilege\n");
4177 CloseHandle(token);
4178 DeleteFileA(filename);
4179 return;
4181 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
4183 SetLastError(0xdeadbeef);
4184 ret = pSetFileValidData(handle, 0);
4185 error = GetLastError();
4186 ok(!ret, "SetFileValidData succeeded\n");
4187 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
4189 SetLastError(0xdeadbeef);
4190 ret = pSetFileValidData(handle, -1);
4191 error = GetLastError();
4192 ok(!ret, "SetFileValidData succeeded\n");
4193 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
4195 SetLastError(0xdeadbeef);
4196 ret = pSetFileValidData(handle, 2);
4197 error = GetLastError();
4198 todo_wine ok(!ret, "SetFileValidData succeeded\n");
4199 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
4201 ret = pSetFileValidData(handle, 4);
4202 ok(ret, "SetFileValidData failed %u\n", GetLastError());
4204 SetLastError(0xdeadbeef);
4205 ret = pSetFileValidData(handle, 8);
4206 error = GetLastError();
4207 ok(!ret, "SetFileValidData succeeded\n");
4208 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
4210 count = SetFilePointer(handle, 1024, NULL, FILE_END);
4211 ok(count != INVALID_SET_FILE_POINTER, "SetFilePointer failed %u\n", GetLastError());
4212 ret = SetEndOfFile(handle);
4213 ok(ret, "SetEndOfFile failed %u\n", GetLastError());
4215 SetLastError(0xdeadbeef);
4216 ret = pSetFileValidData(handle, 2);
4217 error = GetLastError();
4218 todo_wine ok(!ret, "SetFileValidData succeeded\n");
4219 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
4221 ret = pSetFileValidData(handle, 4);
4222 ok(ret, "SetFileValidData failed %u\n", GetLastError());
4224 ret = pSetFileValidData(handle, 8);
4225 ok(ret, "SetFileValidData failed %u\n", GetLastError());
4227 ret = pSetFileValidData(handle, 4);
4228 error = GetLastError();
4229 todo_wine ok(!ret, "SetFileValidData succeeded\n");
4230 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
4232 ret = pSetFileValidData(handle, 1024);
4233 ok(ret, "SetFileValidData failed %u\n", GetLastError());
4235 ret = pSetFileValidData(handle, 2048);
4236 error = GetLastError();
4237 ok(!ret, "SetFileValidData succeeded\n");
4238 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
4240 privs.Privileges[0].Attributes = 0;
4241 AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL);
4243 CloseHandle(token);
4244 CloseHandle(handle);
4245 DeleteFileA(filename);
4248 static void test_WriteFileGather(void)
4250 char temp_path[MAX_PATH], filename[MAX_PATH];
4251 HANDLE hfile, hiocp1, hiocp2;
4252 DWORD ret, size;
4253 ULONG_PTR key;
4254 FILE_SEGMENT_ELEMENT fse[2];
4255 OVERLAPPED ovl, *povl = NULL;
4256 SYSTEM_INFO si;
4257 LPVOID buf = NULL;
4259 ret = GetTempPathA( MAX_PATH, temp_path );
4260 ok( ret != 0, "GetTempPathA error %d\n", GetLastError() );
4261 ok( ret < MAX_PATH, "temp path should fit into MAX_PATH\n" );
4262 ret = GetTempFileNameA( temp_path, "wfg", 0, filename );
4263 ok( ret != 0, "GetTempFileNameA error %d\n", GetLastError() );
4265 hfile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
4266 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, 0 );
4267 ok( hfile != INVALID_HANDLE_VALUE, "CreateFile failed err %u\n", GetLastError() );
4268 if (hfile == INVALID_HANDLE_VALUE) return;
4270 hiocp1 = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 999, 0 );
4271 hiocp2 = CreateIoCompletionPort( hfile, hiocp1, 999, 0 );
4272 ok( hiocp2 != 0, "CreateIoCompletionPort failed err %u\n", GetLastError() );
4274 GetSystemInfo( &si );
4275 buf = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
4276 ok( buf != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
4278 memset( &ovl, 0, sizeof(ovl) );
4279 memset( fse, 0, sizeof(fse) );
4280 fse[0].Buffer = buf;
4281 if (!WriteFileGather( hfile, fse, si.dwPageSize, NULL, &ovl ))
4282 ok( GetLastError() == ERROR_IO_PENDING, "WriteFileGather failed err %u\n", GetLastError() );
4284 ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 );
4285 ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError());
4286 ok( povl == &ovl, "wrong ovl %p\n", povl );
4288 memset( &ovl, 0, sizeof(ovl) );
4289 memset( fse, 0, sizeof(fse) );
4290 fse[0].Buffer = buf;
4291 if (!ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl ))
4292 ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() );
4294 ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 );
4295 ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError());
4296 ok( povl == &ovl, "wrong ovl %p\n", povl );
4298 CloseHandle( hfile );
4299 CloseHandle( hiocp1 );
4300 CloseHandle( hiocp2 );
4301 VirtualFree( buf, 0, MEM_RELEASE );
4302 DeleteFileA( filename );
4305 static unsigned file_map_access(unsigned access)
4307 if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
4308 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
4309 if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
4310 if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS;
4311 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
4314 static BOOL is_access_compatible(unsigned obj_access, unsigned desired_access)
4316 obj_access = file_map_access(obj_access);
4317 desired_access = file_map_access(desired_access);
4318 return (obj_access & desired_access) == desired_access;
4321 static void test_file_access(void)
4323 static const struct
4325 unsigned access, create_error, write_error, read_error;
4326 } td[] =
4328 { GENERIC_READ | GENERIC_WRITE, 0, 0, 0 },
4329 { GENERIC_WRITE, 0, 0, ERROR_ACCESS_DENIED },
4330 { GENERIC_READ, 0, ERROR_ACCESS_DENIED, 0 },
4331 { FILE_READ_DATA | FILE_WRITE_DATA, 0, 0, 0 },
4332 { FILE_WRITE_DATA, 0, 0, ERROR_ACCESS_DENIED },
4333 { FILE_READ_DATA, 0, ERROR_ACCESS_DENIED, 0 },
4334 { FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED },
4335 { FILE_READ_DATA | FILE_APPEND_DATA, 0, 0, 0 },
4336 { FILE_WRITE_DATA | FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED },
4337 { 0, 0, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED },
4339 char path[MAX_PATH], fname[MAX_PATH];
4340 unsigned char buf[16];
4341 HANDLE hfile, hdup;
4342 DWORD i, j, ret, bytes;
4344 GetTempPathA(MAX_PATH, path);
4345 GetTempFileNameA(path, "foo", 0, fname);
4347 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4349 SetLastError(0xdeadbeef);
4350 hfile = CreateFileA(fname, td[i].access, 0, NULL, CREATE_ALWAYS,
4351 FILE_FLAG_DELETE_ON_CLOSE, 0);
4352 if (td[i].create_error)
4354 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
4355 ok(td[i].create_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].create_error, GetLastError());
4356 continue;
4358 else
4359 ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
4361 for (j = 0; j < sizeof(td)/sizeof(td[0]); j++)
4363 SetLastError(0xdeadbeef);
4364 ret = DuplicateHandle(GetCurrentProcess(), hfile, GetCurrentProcess(), &hdup,
4365 td[j].access, 0, 0);
4366 if (is_access_compatible(td[i].access, td[j].access))
4367 ok(ret, "DuplicateHandle(%#x => %#x) error %d\n", td[i].access, td[j].access, GetLastError());
4368 else
4370 /* FIXME: Remove once Wine is fixed */
4371 if ((td[j].access & (GENERIC_READ | GENERIC_WRITE)) ||
4372 (!(td[i].access & (GENERIC_WRITE | FILE_WRITE_DATA)) && (td[j].access & FILE_WRITE_DATA)) ||
4373 (!(td[i].access & (GENERIC_READ | FILE_READ_DATA)) && (td[j].access & FILE_READ_DATA)) ||
4374 (!(td[i].access & (GENERIC_WRITE)) && (td[j].access & FILE_APPEND_DATA)))
4376 todo_wine
4377 ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access);
4378 todo_wine
4379 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
4381 else
4383 ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access);
4384 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
4387 if (ret) CloseHandle(hdup);
4390 SetLastError(0xdeadbeef);
4391 bytes = 0xdeadbeef;
4392 ret = WriteFile(hfile, "\x5e\xa7", 2, &bytes, NULL);
4393 if (td[i].write_error)
4395 ok(!ret, "%d: WriteFile should fail\n", i);
4396 ok(td[i].write_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].write_error, GetLastError());
4397 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
4399 else
4401 ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
4402 ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes);
4405 SetLastError(0xdeadbeef);
4406 ret = SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4407 ok(ret != INVALID_SET_FILE_POINTER, "SetFilePointer error %d\n", GetLastError());
4409 SetLastError(0xdeadbeef);
4410 bytes = 0xdeadbeef;
4411 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4412 if (td[i].read_error)
4414 ok(!ret, "%d: ReadFile should fail\n", i);
4415 ok(td[i].read_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].read_error, GetLastError());
4416 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
4418 else
4420 ok(ret, "%d: ReadFile error %d\n", i, GetLastError());
4421 if (td[i].write_error)
4422 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
4423 else
4425 ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes);
4426 ok(buf[0] == 0x5e && buf[1] == 0xa7, "%d: expected 5ea7, got %02x%02x\n", i, buf[0], buf[1]);
4430 CloseHandle(hfile);
4434 static void test_GetFinalPathNameByHandleA(void)
4436 static char prefix[] = "GetFinalPathNameByHandleA";
4437 static char dos_prefix[] = "\\\\?\\";
4438 char temp_path[MAX_PATH], test_path[MAX_PATH];
4439 char long_path[MAX_PATH], result_path[MAX_PATH];
4440 char dos_path[MAX_PATH + sizeof(dos_prefix)];
4441 HANDLE file;
4442 DWORD count;
4443 UINT ret;
4445 if (!pGetFinalPathNameByHandleA)
4447 skip("GetFinalPathNameByHandleA is missing\n");
4448 return;
4451 /* Test calling with INVALID_HANDLE_VALUE */
4452 SetLastError(0xdeadbeaf);
4453 count = pGetFinalPathNameByHandleA(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4454 ok(count == 0, "Expected length 0, got %u\n", count);
4455 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
4457 count = GetTempPathA(MAX_PATH, temp_path);
4458 ok(count, "Failed to get temp path, error %u\n", GetLastError());
4459 ret = GetTempFileNameA(temp_path, prefix, 0, test_path);
4460 ok(ret != 0, "GetTempFileNameA error %u\n", GetLastError());
4461 ret = GetLongPathNameA(test_path, long_path, MAX_PATH);
4462 ok(ret != 0, "GetLongPathNameA error %u\n", GetLastError());
4463 strcpy(dos_path, dos_prefix);
4464 strcat(dos_path, long_path);
4466 file = CreateFileA(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
4467 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
4468 ok(file != INVALID_HANDLE_VALUE, "CreateFileA error %u\n", GetLastError());
4470 /* Test VOLUME_NAME_DOS with sufficient buffer size */
4471 memset(result_path, 0x11, sizeof(result_path));
4472 count = pGetFinalPathNameByHandleA(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4473 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
4474 ok(lstrcmpiA(dos_path, result_path) == 0, "Expected %s, got %s\n", dos_path, result_path);
4476 /* Test VOLUME_NAME_DOS with insufficient buffer size */
4477 memset(result_path, 0x11, sizeof(result_path));
4478 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)-2, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4479 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
4480 ok(result_path[0] == 0x11, "Result path was modified\n");
4482 memset(result_path, 0x11, sizeof(result_path));
4483 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4484 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
4485 ok(result_path[0] == 0x11, "Result path was modified\n");
4487 memset(result_path, 0x11, sizeof(result_path));
4488 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4489 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
4490 ok(result_path[0] == 0x11, "Result path was modified\n");
4492 memset(result_path, 0x11, sizeof(result_path));
4493 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4494 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
4495 ok(result_path[0] != 0x11, "Result path was not modified\n");
4496 ok(!result_path[strlen(dos_path)], "Expected nullterminated string\n");
4497 ok(result_path[strlen(dos_path)+1] == 0x11, "Buffer overflow\n");
4499 CloseHandle(file);
4502 static void test_GetFinalPathNameByHandleW(void)
4504 static WCHAR prefix[] = {'G','e','t','F','i','n','a','l','P','a','t','h',
4505 'N','a','m','e','B','y','H','a','n','d','l','e','W','\0'};
4506 static WCHAR dos_prefix[] = {'\\','\\','?','\\','\0'};
4507 WCHAR temp_path[MAX_PATH], test_path[MAX_PATH];
4508 WCHAR long_path[MAX_PATH], result_path[MAX_PATH];
4509 WCHAR dos_path[MAX_PATH + sizeof(dos_prefix)];
4510 WCHAR drive_part[MAX_PATH];
4511 WCHAR *file_part;
4512 WCHAR volume_path[MAX_PATH + 50];
4513 WCHAR nt_path[2 * MAX_PATH];
4514 BOOL success;
4515 HANDLE file;
4516 DWORD count;
4517 UINT ret;
4519 if (!pGetFinalPathNameByHandleW)
4521 skip("GetFinalPathNameByHandleW is missing\n");
4522 return;
4525 /* Test calling with INVALID_HANDLE_VALUE */
4526 SetLastError(0xdeadbeaf);
4527 count = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4528 ok(count == 0, "Expected length 0, got %u\n", count);
4529 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
4531 count = GetTempPathW(MAX_PATH, temp_path);
4532 ok(count, "Failed to get temp path, error %u\n", GetLastError());
4533 ret = GetTempFileNameW(temp_path, prefix, 0, test_path);
4534 ok(ret != 0, "GetTempFileNameW error %u\n", GetLastError());
4535 ret = GetLongPathNameW(test_path, long_path, MAX_PATH);
4536 ok(ret != 0, "GetLongPathNameW error %u\n", GetLastError());
4537 lstrcpyW(dos_path, dos_prefix);
4538 lstrcatW(dos_path, long_path);
4540 file = CreateFileW(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
4541 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
4542 ok(file != INVALID_HANDLE_VALUE, "CreateFileW error %u\n", GetLastError());
4544 /* Test VOLUME_NAME_DOS with sufficient buffer size */
4545 memset(result_path, 0x11, sizeof(result_path));
4546 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4547 ok(count == lstrlenW(dos_path), "Expected length %u, got %u\n", lstrlenW(dos_path), count);
4548 ok(lstrcmpiW(dos_path, result_path) == 0, "Expected %s, got %s\n", wine_dbgstr_w(dos_path), wine_dbgstr_w(result_path));
4550 /* Test VOLUME_NAME_DOS with insufficient buffer size */
4551 memset(result_path, 0x11, sizeof(result_path));
4552 count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4553 ok(count == lstrlenW(dos_path) + 1, "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count);
4554 ok(result_path[0] == 0x1111, "Result path was modified\n");
4556 memset(result_path, 0x11, sizeof(result_path));
4557 count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4558 ok(count == lstrlenW(dos_path) + 1, "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count);
4559 ok(result_path[0] == 0x1111, "Result path was modified\n");
4561 memset(result_path, 0x11, sizeof(result_path));
4562 count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
4563 ok(count == lstrlenW(dos_path), "Expected length %u, got %u\n", lstrlenW(dos_path), count);
4564 ok(result_path[0] != 0x1111, "Result path was not modified\n");
4565 ok(!result_path[lstrlenW(dos_path)], "Expected nullterminated string\n");
4566 ok(result_path[lstrlenW(dos_path)+1] == 0x1111, "Buffer overflow\n");
4568 success = GetVolumePathNameW(long_path, drive_part, MAX_PATH);
4569 ok(success, "GetVolumePathNameW error %u\n", GetLastError());
4570 success = GetVolumeNameForVolumeMountPointW(drive_part, volume_path, sizeof(volume_path) / sizeof(WCHAR));
4571 ok(success, "GetVolumeNameForVolumeMountPointW error %u\n", GetLastError());
4573 /* Test for VOLUME_NAME_GUID */
4574 lstrcatW(volume_path, long_path + lstrlenW(drive_part));
4575 memset(result_path, 0x11, sizeof(result_path));
4576 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_GUID);
4577 ok(count == lstrlenW(volume_path), "Expected length %u, got %u\n", lstrlenW(volume_path), count);
4578 ok(lstrcmpiW(volume_path, result_path) == 0, "Expected %s, got %s\n",
4579 wine_dbgstr_w(volume_path), wine_dbgstr_w(result_path));
4581 /* Test for VOLUME_NAME_NONE */
4582 file_part = long_path + lstrlenW(drive_part) - 1;
4583 memset(result_path, 0x11, sizeof(result_path));
4584 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE);
4585 ok(count == lstrlenW(file_part), "Expected length %u, got %u\n", lstrlenW(file_part), count);
4586 ok(lstrcmpiW(file_part, result_path) == 0, "Expected %s, got %s\n",
4587 wine_dbgstr_w(file_part), wine_dbgstr_w(result_path));
4589 drive_part[lstrlenW(drive_part)-1] = 0;
4590 success = QueryDosDeviceW(drive_part, nt_path, sizeof(nt_path) / sizeof(WCHAR));
4591 ok(success, "QueryDosDeviceW error %u\n", GetLastError());
4593 /* Test for VOLUME_NAME_NT */
4594 lstrcatW(nt_path, file_part);
4595 memset(result_path, 0x11, sizeof(result_path));
4596 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NT);
4597 ok(count == lstrlenW(nt_path), "Expected length %u, got %u\n", lstrlenW(nt_path), count);
4598 ok(lstrcmpiW(nt_path, result_path) == 0, "Expected %s, got %s\n",
4599 wine_dbgstr_w(nt_path), wine_dbgstr_w(result_path));
4601 CloseHandle(file);
4604 static void test_SetFileInformationByHandle(void)
4606 FILE_ATTRIBUTE_TAG_INFO fileattrinfo = { 0 };
4607 FILE_REMOTE_PROTOCOL_INFO protinfo = { 0 };
4608 FILE_STANDARD_INFO stdinfo = { };
4609 FILE_COMPRESSION_INFO compressinfo;
4610 FILE_DISPOSITION_INFO dispinfo;
4611 char tempFileName[MAX_PATH];
4612 char tempPath[MAX_PATH];
4613 HANDLE file;
4614 BOOL ret;
4616 if (!pSetFileInformationByHandle)
4618 win_skip("SetFileInformationByHandle is not supported\n");
4619 return;
4622 ret = GetTempPathA(sizeof(tempPath), tempPath);
4623 ok(ret, "GetTempPathA failed, got error %u.\n", GetLastError());
4625 /* ensure the existence of a file in the temp folder */
4626 ret = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
4627 ok(ret, "GetTempFileNameA failed, got error %u.\n", GetLastError());
4629 file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4630 NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
4631 ok(file != INVALID_HANDLE_VALUE, "failed to open the temp file, error %u.\n", GetLastError());
4633 /* invalid classes */
4634 SetLastError(0xdeadbeef);
4635 ret = pSetFileInformationByHandle(file, FileStandardInfo, &stdinfo, sizeof(stdinfo));
4636 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
4638 memset(&compressinfo, 0, sizeof(compressinfo));
4639 SetLastError(0xdeadbeef);
4640 ret = pSetFileInformationByHandle(file, FileCompressionInfo, &compressinfo, sizeof(compressinfo));
4641 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
4643 SetLastError(0xdeadbeef);
4644 ret = pSetFileInformationByHandle(file, FileAttributeTagInfo, &fileattrinfo, sizeof(fileattrinfo));
4645 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
4647 memset(&protinfo, 0, sizeof(protinfo));
4648 protinfo.StructureVersion = 1;
4649 protinfo.StructureSize = sizeof(protinfo);
4650 SetLastError(0xdeadbeef);
4651 ret = pSetFileInformationByHandle(file, FileRemoteProtocolInfo, &protinfo, sizeof(protinfo));
4652 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
4654 /* test FileDispositionInfo, additional details already covered by ntdll tests */
4655 SetLastError(0xdeadbeef);
4656 ret = pSetFileInformationByHandle(file, FileDispositionInfo, &dispinfo, 0);
4657 todo_wine
4658 ok(!ret && GetLastError() == ERROR_BAD_LENGTH, "got %d, error %d\n", ret, GetLastError());
4660 dispinfo.DeleteFile = TRUE;
4661 ret = pSetFileInformationByHandle(file, FileDispositionInfo, &dispinfo, sizeof(dispinfo));
4662 ok(ret, "setting FileDispositionInfo failed, error %d\n", GetLastError());
4664 CloseHandle(file);
4667 static void test_GetFileAttributesExW(void)
4669 static const WCHAR path1[] = {'\\','\\','?','\\',0};
4670 static const WCHAR path2[] = {'\\','?','?','\\',0};
4671 static const WCHAR path3[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
4672 WIN32_FILE_ATTRIBUTE_DATA info;
4673 BOOL ret;
4675 SetLastError(0xdeadbeef);
4676 ret = GetFileAttributesExW(path1, GetFileExInfoStandard, &info);
4677 ok(!ret, "GetFileAttributesExW succeeded\n");
4678 ok(GetLastError() == ERROR_INVALID_NAME, "Expected error ERROR_INVALID_NAME, got %u\n", GetLastError());
4680 SetLastError(0xdeadbeef);
4681 ret = GetFileAttributesExW(path2, GetFileExInfoStandard, &info);
4682 ok(!ret, "GetFileAttributesExW succeeded\n");
4683 ok(GetLastError() == ERROR_INVALID_NAME, "Expected error ERROR_INVALID_NAME, got %u\n", GetLastError());
4685 SetLastError(0xdeadbeef);
4686 ret = GetFileAttributesExW(path3, GetFileExInfoStandard, &info);
4687 ok(!ret, "GetFileAttributesExW succeeded\n");
4688 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
4691 START_TEST(file)
4693 InitFunctionPointers();
4695 test__hread( );
4696 test__hwrite( );
4697 test__lclose( );
4698 test__lcreat( );
4699 test__llseek( );
4700 test__llopen( );
4701 test__lread( );
4702 test__lwrite( );
4703 test_GetTempFileNameA();
4704 test_CopyFileA();
4705 test_CopyFileW();
4706 test_CopyFile2();
4707 test_CopyFileEx();
4708 test_CreateFile();
4709 test_CreateFileA();
4710 test_CreateFileW();
4711 test_CreateFile2();
4712 test_DeleteFileA();
4713 test_DeleteFileW();
4714 test_MoveFileA();
4715 test_MoveFileW();
4716 test_FindFirstFileA();
4717 test_FindNextFileA();
4718 test_FindFirstFileExA(FindExInfoStandard, 0, 0);
4719 test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_CASE_SENSITIVE);
4720 test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_LARGE_FETCH);
4721 test_FindFirstFileExA(FindExInfoBasic, 0, 0);
4722 /* FindExLimitToDirectories is ignored if the file system doesn't support directory filtering */
4723 test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, 0);
4724 test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, FIND_FIRST_EX_CASE_SENSITIVE);
4725 test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, FIND_FIRST_EX_LARGE_FETCH);
4726 test_FindFirstFileExA(FindExInfoBasic, FindExSearchLimitToDirectories, 0);
4727 test_LockFile();
4728 test_file_sharing();
4729 test_offset_in_overlapped_structure();
4730 test_MapFile();
4731 test_GetFileType();
4732 test_async_file_errors();
4733 test_read_write();
4734 test_OpenFile();
4735 test_overlapped();
4736 test_RemoveDirectory();
4737 test_ReplaceFileA();
4738 test_ReplaceFileW();
4739 test_GetFileInformationByHandleEx();
4740 test_OpenFileById();
4741 test_SetFileValidData();
4742 test_WriteFileGather();
4743 test_file_access();
4744 test_GetFinalPathNameByHandleA();
4745 test_GetFinalPathNameByHandleW();
4746 test_SetFileInformationByHandle();
4747 test_GetFileAttributesExW();