1 /* 2 * Unit tests for file functions in Wine 3 * 4 * Copyright (c) 2002, 2004 Jakob Eriksson 5 * Copyright (c) 2008 Jeff Zaroyko 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 * 21 */ 22 23 #include "precomp.h" 24 25 #include <time.h> 26 #include <fileapi.h> 27 28 #undef DeleteFile /* needed for FILE_DISPOSITION_INFO */ 29 30 static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD); 31 static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID); 32 static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID); 33 static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT); 34 static BOOL (WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD); 35 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData); 36 static BOOL (WINAPI *pGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD); 37 static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD); 38 static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG); 39 static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*); 40 static HANDLE (WINAPI *pCreateFile2)(LPCWSTR, DWORD, DWORD, DWORD, CREATEFILE2_EXTENDED_PARAMETERS*); 41 static DWORD (WINAPI *pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD); 42 static DWORD (WINAPI *pGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD); 43 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, 44 PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG); 45 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR*); 46 static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN); 47 static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD); 48 static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ); 49 static void (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING); 50 51 static char filename[MAX_PATH]; 52 static const char sillytext[] = 53 "en larvig liten text dx \033 gx hej 84 hej 4484 ! \001\033 bla bl\na.. bla bla." 54 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 55 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 56 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 57 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 58 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 59 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 60 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 61 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3" 62 "sdlkfjasdlkfj a dslkj adsklf \n \nasdklf askldfa sdlkf \nsadklf asdklf asdf "; 63 64 struct test_list { 65 const char *file; /* file string to test */ 66 const DWORD err; /* Win NT and further error code */ 67 const LONG err2; /* Win 9x & ME error code or -1 */ 68 const DWORD options; /* option flag to use for open */ 69 const BOOL todo_flag; /* todo_wine indicator */ 70 } ; 71 72 static void InitFunctionPointers(void) 73 { 74 HMODULE hntdll = GetModuleHandleA("ntdll"); 75 HMODULE hkernel32 = GetModuleHandleA("kernel32"); 76 77 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile"); 78 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U"); 79 pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString"); 80 pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString"); 81 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString"); 82 83 pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA"); 84 pReplaceFileA=(void*)GetProcAddress(hkernel32, "ReplaceFileA"); 85 pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW"); 86 pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA"); 87 pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hkernel32, "GetVolumeNameForVolumeMountPointA"); 88 pQueueUserAPC = (void *) GetProcAddress(hkernel32, "QueueUserAPC"); 89 pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx"); 90 pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById"); 91 pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData"); 92 pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2"); 93 pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2"); 94 pGetFinalPathNameByHandleA = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleA"); 95 pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW"); 96 pSetFileInformationByHandle = (void *) GetProcAddress(hkernel32, "SetFileInformationByHandle"); 97 } 98 99 static void test__hread( void ) 100 { 101 HFILE filehandle; 102 char buffer[10000]; 103 LONG bytes_read; 104 LONG bytes_wanted; 105 LONG i; 106 BOOL ret; 107 108 SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL); /* be sure to remove stale files */ 109 DeleteFileA( filename ); 110 filehandle = _lcreat( filename, 0 ); 111 if (filehandle == HFILE_ERROR) 112 { 113 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 114 return; 115 } 116 117 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" ); 118 119 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 120 121 filehandle = _lopen( filename, OF_READ ); 122 123 ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError( ) ); 124 125 bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) ); 126 127 ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" ); 128 129 for (bytes_wanted = 0; bytes_wanted < lstrlenA( sillytext ); bytes_wanted++) 130 { 131 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" ); 132 ok( _hread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" ); 133 for (i = 0; i < bytes_wanted; i++) 134 { 135 ok( buffer[i] == sillytext[i], "that's not what's written\n" ); 136 } 137 } 138 139 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" ); 140 141 ret = DeleteFileA( filename ); 142 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) ); 143 } 144 145 146 static void test__hwrite( void ) 147 { 148 HFILE filehandle; 149 char buffer[10000]; 150 LONG bytes_read; 151 LONG bytes_written; 152 ULONG blocks; 153 LONG i; 154 char *contents; 155 HLOCAL memory_object; 156 char checksum[1]; 157 BOOL ret; 158 159 filehandle = _lcreat( filename, 0 ); 160 if (filehandle == HFILE_ERROR) 161 { 162 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 163 return; 164 } 165 166 ok( HFILE_ERROR != _hwrite( filehandle, "", 0 ), "_hwrite complains\n" ); 167 168 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 169 170 filehandle = _lopen( filename, OF_READ ); 171 172 bytes_read = _hread( filehandle, buffer, 1); 173 174 ok( 0 == bytes_read, "file read size error\n" ); 175 176 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 177 178 filehandle = _lopen( filename, OF_READWRITE ); 179 180 bytes_written = 0; 181 checksum[0] = '\0'; 182 srand( (unsigned)time( NULL ) ); 183 for (blocks = 0; blocks < 100; blocks++) 184 { 185 for (i = 0; i < (LONG)sizeof( buffer ); i++) 186 { 187 buffer[i] = rand( ); 188 checksum[0] = checksum[0] + buffer[i]; 189 } 190 ok( HFILE_ERROR != _hwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" ); 191 bytes_written = bytes_written + sizeof( buffer ); 192 } 193 194 ok( HFILE_ERROR != _hwrite( filehandle, checksum, 1 ), "_hwrite complains\n" ); 195 bytes_written++; 196 197 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" ); 198 199 memory_object = LocalAlloc( LPTR, bytes_written ); 200 201 ok( 0 != memory_object, "LocalAlloc fails. (Could be out of memory.)\n" ); 202 203 contents = LocalLock( memory_object ); 204 ok( NULL != contents, "LocalLock whines\n" ); 205 206 filehandle = _lopen( filename, OF_READ ); 207 208 contents = LocalLock( memory_object ); 209 ok( NULL != contents, "LocalLock whines\n" ); 210 211 ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" ); 212 213 checksum[0] = '\0'; 214 i = 0; 215 do 216 { 217 checksum[0] = checksum[0] + contents[i]; 218 i++; 219 } 220 while (i < bytes_written - 1); 221 222 ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" ); 223 224 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" ); 225 226 ret = DeleteFileA( filename ); 227 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) ); 228 229 LocalFree( contents ); 230 } 231 232 233 static void test__lclose( void ) 234 { 235 HFILE filehandle; 236 BOOL ret; 237 238 filehandle = _lcreat( filename, 0 ); 239 if (filehandle == HFILE_ERROR) 240 { 241 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 242 return; 243 } 244 245 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" ); 246 247 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 248 249 ret = DeleteFileA( filename ); 250 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) ); 251 } 252 253 /* helper function for test__lcreat */ 254 static void get_nt_pathW( const char *name, UNICODE_STRING *nameW ) 255 { 256 UNICODE_STRING strW; 257 ANSI_STRING str; 258 NTSTATUS status; 259 BOOLEAN ret; 260 261 pRtlInitAnsiString( &str, name ); 262 263 status = pRtlAnsiStringToUnicodeString( &strW, &str, TRUE ); 264 ok( !status, "RtlAnsiStringToUnicodeString failed with %08x\n", status ); 265 266 ret = pRtlDosPathNameToNtPathName_U( strW.Buffer, nameW, NULL, NULL ); 267 ok( ret, "RtlDosPathNameToNtPathName_U failed\n" ); 268 269 pRtlFreeUnicodeString( &strW ); 270 } 271 272 static void test__lcreat( void ) 273 { 274 UNICODE_STRING filenameW; 275 OBJECT_ATTRIBUTES attr; 276 IO_STATUS_BLOCK io; 277 HFILE filehandle; 278 char buffer[10000]; 279 WIN32_FIND_DATAA search_results; 280 char slashname[] = "testfi/"; 281 int err; 282 HANDLE find, file; 283 NTSTATUS status; 284 BOOL ret; 285 286 filehandle = _lcreat( filename, 0 ); 287 if (filehandle == HFILE_ERROR) 288 { 289 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 290 return; 291 } 292 293 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" ); 294 295 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" ); 296 297 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" ); 298 299 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 300 301 find = FindFirstFileA( filename, &search_results ); 302 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" ); 303 FindClose( find ); 304 305 ret = DeleteFileA(filename); 306 ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError()); 307 308 filehandle = _lcreat( filename, 1 ); /* readonly */ 309 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) ); 310 311 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write never the less\n" ); 312 313 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 314 315 find = FindFirstFileA( filename, &search_results ); 316 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" ); 317 FindClose( find ); 318 319 SetLastError( 0xdeadbeef ); 320 ok( 0 == DeleteFileA( filename ), "shouldn't be able to delete a readonly file\n" ); 321 ok( GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError() ); 322 323 ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" ); 324 325 ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file!\n" ); 326 327 filehandle = _lcreat( filename, 1 ); /* readonly */ 328 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError() ); 329 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen(sillytext) ), 330 "_hwrite shouldn't be able to write never the less\n" ); 331 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 332 333 find = FindFirstFileA( filename, &search_results ); 334 ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" ); 335 FindClose( find ); 336 337 get_nt_pathW( filename, &filenameW ); 338 attr.Length = sizeof(attr); 339 attr.RootDirectory = 0; 340 attr.Attributes = OBJ_CASE_INSENSITIVE; 341 attr.ObjectName = &filenameW; 342 attr.SecurityDescriptor = NULL; 343 attr.SecurityQualityOfService = NULL; 344 345 status = pNtCreateFile( &file, GENERIC_READ | GENERIC_WRITE | DELETE, &attr, &io, NULL, 0, 346 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 347 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 ); 348 ok( status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %08x\n", status ); 349 ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" ); 350 351 status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0, 352 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 353 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 ); 354 ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status ); 355 356 status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0, 357 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 358 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_DIRECTORY_FILE, NULL, 0 ); 359 ok( status == STATUS_NOT_A_DIRECTORY, "expected STATUS_NOT_A_DIRECTORY, got %08x\n", status ); 360 361 status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0, 362 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 363 FILE_OPEN_IF, 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 ); 367 368 pRtlFreeUnicodeString( &filenameW ); 369 370 todo_wine 371 ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" ); 372 todo_wine 373 ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" ); 374 todo_wine 375 ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file\n" ); 376 377 filehandle = _lcreat( filename, 2 ); 378 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) ); 379 380 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" ); 381 382 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" ); 383 384 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" ); 385 386 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 387 388 find = FindFirstFileA( filename, &search_results ); 389 ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" ); 390 FindClose( find ); 391 392 ret = DeleteFileA( filename ); 393 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 394 395 filehandle = _lcreat( filename, 4 ); /* SYSTEM file */ 396 ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) ); 397 398 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" ); 399 400 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" ); 401 402 ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" ); 403 404 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 405 406 find = FindFirstFileA( filename, &search_results ); 407 ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" ); 408 FindClose( find ); 409 410 ret = DeleteFileA( filename ); 411 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 412 413 filehandle=_lcreat (slashname, 0); /* illegal name */ 414 if (HFILE_ERROR==filehandle) { 415 err=GetLastError (); 416 ok (err==ERROR_INVALID_NAME || err==ERROR_PATH_NOT_FOUND, 417 "creating file \"%s\" failed with error %d\n", slashname, err); 418 } else { /* only NT succeeds */ 419 _lclose(filehandle); 420 find=FindFirstFileA (slashname, &search_results); 421 if (INVALID_HANDLE_VALUE!=find) 422 { 423 ret = FindClose (find); 424 ok (0 != ret, "FindClose complains (%d)\n", GetLastError ()); 425 slashname[strlen(slashname)-1]=0; 426 ok (!strcmp (slashname, search_results.cFileName), 427 "found unexpected name \"%s\"\n", search_results.cFileName); 428 ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes, 429 "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName, 430 search_results.dwFileAttributes); 431 } 432 ret = DeleteFileA( slashname ); 433 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 434 } 435 436 filehandle=_lcreat (filename, 8); /* illegal attribute */ 437 if (HFILE_ERROR==filehandle) 438 ok (0, "couldn't create volume label \"%s\"\n", filename); 439 else { 440 _lclose(filehandle); 441 find=FindFirstFileA (filename, &search_results); 442 if (INVALID_HANDLE_VALUE==find) 443 ok (0, "file \"%s\" not found\n", filename); 444 else { 445 const char *name = strrchr(filename, '\\'); 446 447 if (name) name++; 448 else name = filename; 449 450 ret = FindClose(find); 451 ok ( 0 != ret, "FindClose complains (%d)\n", GetLastError ()); 452 ok (!strcmp (name, search_results.cFileName), 453 "expected \"%s\", got \"%s\"\n", name, search_results.cFileName); 454 search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; 455 search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_COMPRESSED; 456 ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes, 457 "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName, 458 search_results.dwFileAttributes); 459 } 460 ret = DeleteFileA( filename ); 461 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 462 } 463 } 464 465 466 static void test__llseek( void ) 467 { 468 INT i; 469 HFILE filehandle; 470 char buffer[1]; 471 LONG bytes_read; 472 BOOL ret; 473 474 filehandle = _lcreat( filename, 0 ); 475 if (filehandle == HFILE_ERROR) 476 { 477 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 478 return; 479 } 480 481 for (i = 0; i < 400; i++) 482 { 483 ok( _hwrite( filehandle, sillytext, strlen( sillytext ) ) != -1, "_hwrite complains\n" ); 484 } 485 ok( _llseek( filehandle, 400 * strlen( sillytext ), FILE_CURRENT ) != -1, "should be able to seek\n" ); 486 ok( _llseek( filehandle, 27 + 35 * strlen( sillytext ), FILE_BEGIN ) != -1, "should be able to seek\n" ); 487 488 bytes_read = _hread( filehandle, buffer, 1); 489 ok( 1 == bytes_read, "file read size error\n" ); 490 ok( buffer[0] == sillytext[27], "_llseek error, it got lost seeking\n" ); 491 ok( _llseek( filehandle, -400 * (LONG)strlen( sillytext ), FILE_END ) != -1, "should be able to seek\n" ); 492 493 bytes_read = _hread( filehandle, buffer, 1); 494 ok( 1 == bytes_read, "file read size error\n" ); 495 ok( buffer[0] == sillytext[0], "_llseek error, it got lost seeking\n" ); 496 ok( _llseek( filehandle, 1000000, FILE_END ) != -1, "should be able to seek past file; poor, poor Windows programmers\n" ); 497 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 498 499 ret = DeleteFileA( filename ); 500 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 501 } 502 503 504 static void test__llopen( void ) 505 { 506 HFILE filehandle; 507 UINT bytes_read; 508 char buffer[10000]; 509 BOOL ret; 510 511 filehandle = _lcreat( filename, 0 ); 512 if (filehandle == HFILE_ERROR) 513 { 514 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 515 return; 516 } 517 518 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" ); 519 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 520 521 filehandle = _lopen( filename, OF_READ ); 522 ok( HFILE_ERROR == _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write!\n" ); 523 bytes_read = _hread( filehandle, buffer, strlen( sillytext ) ); 524 ok( strlen( sillytext ) == bytes_read, "file read size error\n" ); 525 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 526 527 filehandle = _lopen( filename, OF_READWRITE ); 528 bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) ); 529 ok( strlen( sillytext ) == bytes_read, "file read size error\n" ); 530 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" ); 531 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 532 533 filehandle = _lopen( filename, OF_WRITE ); 534 ok( HFILE_ERROR == _hread( filehandle, buffer, 1 ), "you should only be able to write this file\n" ); 535 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" ); 536 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 537 538 ret = DeleteFileA( filename ); 539 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 540 /* TODO - add tests for the SHARE modes - use two processes to pull this one off */ 541 } 542 543 544 static void test__lread( void ) 545 { 546 HFILE filehandle; 547 char buffer[10000]; 548 UINT bytes_read; 549 UINT bytes_wanted; 550 UINT i; 551 BOOL ret; 552 553 filehandle = _lcreat( filename, 0 ); 554 if (filehandle == HFILE_ERROR) 555 { 556 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 557 return; 558 } 559 560 ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" ); 561 562 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 563 564 filehandle = _lopen( filename, OF_READ ); 565 566 ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError()); 567 568 bytes_read = _lread( filehandle, buffer, 2 * strlen( sillytext ) ); 569 570 ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" ); 571 572 for (bytes_wanted = 0; bytes_wanted < strlen( sillytext ); bytes_wanted++) 573 { 574 ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" ); 575 ok( _lread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" ); 576 for (i = 0; i < bytes_wanted; i++) 577 { 578 ok( buffer[i] == sillytext[i], "that's not what's written\n" ); 579 } 580 } 581 582 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 583 584 ret = DeleteFileA( filename ); 585 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 586 } 587 588 589 static void test__lwrite( void ) 590 { 591 HFILE filehandle; 592 char buffer[10000]; 593 UINT bytes_read; 594 UINT bytes_written; 595 UINT blocks; 596 INT i; 597 char *contents; 598 HLOCAL memory_object; 599 char checksum[1]; 600 BOOL ret; 601 602 filehandle = _lcreat( filename, 0 ); 603 if (filehandle == HFILE_ERROR) 604 { 605 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 606 return; 607 } 608 609 ok( HFILE_ERROR != _lwrite( filehandle, "", 0 ), "_hwrite complains\n" ); 610 611 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 612 613 filehandle = _lopen( filename, OF_READ ); 614 615 bytes_read = _hread( filehandle, buffer, 1); 616 617 ok( 0 == bytes_read, "file read size error\n" ); 618 619 ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" ); 620 621 filehandle = _lopen( filename, OF_READWRITE ); 622 623 bytes_written = 0; 624 checksum[0] = '\0'; 625 srand( (unsigned)time( NULL ) ); 626 for (blocks = 0; blocks < 100; blocks++) 627 { 628 for (i = 0; i < (INT)sizeof( buffer ); i++) 629 { 630 buffer[i] = rand( ); 631 checksum[0] = checksum[0] + buffer[i]; 632 } 633 ok( HFILE_ERROR != _lwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" ); 634 bytes_written = bytes_written + sizeof( buffer ); 635 } 636 637 ok( HFILE_ERROR != _lwrite( filehandle, checksum, 1 ), "_hwrite complains\n" ); 638 bytes_written++; 639 640 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" ); 641 642 memory_object = LocalAlloc( LPTR, bytes_written ); 643 644 ok( 0 != memory_object, "LocalAlloc fails, could be out of memory\n" ); 645 646 contents = LocalLock( memory_object ); 647 ok( NULL != contents, "LocalLock whines\n" ); 648 649 filehandle = _lopen( filename, OF_READ ); 650 651 contents = LocalLock( memory_object ); 652 ok( NULL != contents, "LocalLock whines\n" ); 653 654 ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" ); 655 656 checksum[0] = '\0'; 657 i = 0; 658 do 659 { 660 checksum[0] += contents[i]; 661 i++; 662 } 663 while (i < bytes_written - 1); 664 665 ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" ); 666 667 ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" ); 668 669 ret = DeleteFileA( filename ); 670 ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) ); 671 672 LocalFree( contents ); 673 } 674 675 static void test_CopyFileA(void) 676 { 677 char temp_path[MAX_PATH]; 678 char source[MAX_PATH], dest[MAX_PATH]; 679 static const char prefix[] = "pfx"; 680 HANDLE hfile; 681 HANDLE hmapfile; 682 FILETIME ft1, ft2; 683 char buf[10]; 684 DWORD ret; 685 BOOL retok; 686 687 ret = GetTempPathA(MAX_PATH, temp_path); 688 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 689 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 690 691 ret = GetTempFileNameA(temp_path, prefix, 0, source); 692 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 693 694 /* copying a file to itself must fail */ 695 retok = CopyFileA(source, source, FALSE); 696 ok( !retok && (GetLastError() == ERROR_SHARING_VIOLATION || broken(GetLastError() == ERROR_FILE_EXISTS) /* Win 9x */), 697 "copying a file to itself didn't fail (ret=%d, err=%d)\n", retok, GetLastError()); 698 699 /* make the source have not zero size */ 700 hfile = CreateFileA(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); 701 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n"); 702 retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL ); 703 ok( retok && ret == sizeof(prefix), 704 "WriteFile error %d\n", GetLastError()); 705 ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n"); 706 /* get the file time and change it to prove the difference */ 707 ret = GetFileTime(hfile, NULL, NULL, &ft1); 708 ok( ret, "GetFileTime error %d\n", GetLastError()); 709 ft1.dwLowDateTime -= 600000000; /* 60 second */ 710 ret = SetFileTime(hfile, NULL, NULL, &ft1); 711 ok( ret, "SetFileTime error %d\n", GetLastError()); 712 GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */ 713 CloseHandle(hfile); 714 715 ret = GetTempFileNameA(temp_path, prefix, 0, dest); 716 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 717 718 SetLastError(0xdeadbeef); 719 ret = CopyFileA(source, dest, TRUE); 720 ok(!ret && GetLastError() == ERROR_FILE_EXISTS, 721 "CopyFileA: unexpected error %d\n", GetLastError()); 722 723 ret = CopyFileA(source, dest, FALSE); 724 ok(ret, "CopyFileA: error %d\n", GetLastError()); 725 726 /* copying from a read-locked source fails */ 727 hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 728 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); 729 retok = CopyFileA(source, dest, FALSE); 730 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION, 731 "copying from a read-locked file succeeded when it shouldn't have\n"); 732 /* in addition, the source is opened before the destination */ 733 retok = CopyFileA("25f99d3b-4ba4-4f66-88f5-2906886993cc", dest, FALSE); 734 ok(!retok && GetLastError() == ERROR_FILE_NOT_FOUND, 735 "copying from a file that doesn't exist failed in an unexpected way (ret=%d, err=%d)\n", retok, GetLastError()); 736 CloseHandle(hfile); 737 738 /* copying from a r+w opened, r shared source succeeds */ 739 hfile = CreateFileA(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 740 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); 741 retok = CopyFileA(source, dest, FALSE); 742 ok(retok, 743 "copying from an r+w opened and r shared file failed (ret=%d, err=%d)\n", retok, GetLastError()); 744 CloseHandle(hfile); 745 746 /* copying from a delete-locked source mostly succeeds */ 747 hfile = CreateFileA(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 748 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); 749 retok = CopyFileA(source, dest, FALSE); 750 ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* NT, 2000, XP */, 751 "copying from a delete-locked file failed (ret=%d, err=%d)\n", retok, GetLastError()); 752 CloseHandle(hfile); 753 754 /* copying to a write-locked destination fails */ 755 hfile = CreateFileA(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 756 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 757 retok = CopyFileA(source, dest, FALSE); 758 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION, 759 "copying to a write-locked file didn't fail (ret=%d, err=%d)\n", retok, GetLastError()); 760 CloseHandle(hfile); 761 762 /* copying to a r+w opened, w shared destination mostly succeeds */ 763 hfile = CreateFileA(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 764 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 765 retok = CopyFileA(source, dest, FALSE); 766 ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */, 767 "copying to a r+w opened and w shared file failed (ret=%d, err=%d)\n", retok, GetLastError()); 768 CloseHandle(hfile); 769 770 /* copying to a delete-locked destination fails, even when the destination is delete-shared */ 771 hfile = CreateFileA(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0); 772 ok(hfile != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* Win 9x */, 773 "failed to open destination file, error %d\n", GetLastError()); 774 if (hfile != INVALID_HANDLE_VALUE) 775 { 776 retok = CopyFileA(source, dest, FALSE); 777 ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION, 778 "copying to a delete-locked shared file didn't fail (ret=%d, err=%d)\n", retok, GetLastError()); 779 CloseHandle(hfile); 780 } 781 782 /* copy to a file that's opened the way Wine opens the source */ 783 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 784 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 785 retok = CopyFileA(source, dest, FALSE); 786 ok(retok || broken(GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */, 787 "copying to a file opened the way Wine opens the source failed (ret=%d, err=%d)\n", retok, GetLastError()); 788 CloseHandle(hfile); 789 790 /* make sure that destination has correct size */ 791 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 792 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n"); 793 ret = GetFileSize(hfile, NULL); 794 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret); 795 796 /* make sure that destination has the same filetime */ 797 ret = GetFileTime(hfile, NULL, NULL, &ft2); 798 ok( ret, "GetFileTime error %d\n", GetLastError()); 799 ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n"); 800 801 SetLastError(0xdeadbeef); 802 ret = CopyFileA(source, dest, FALSE); 803 ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION, 804 "CopyFileA: ret = %d, unexpected error %d\n", ret, GetLastError()); 805 806 /* make sure that destination still has correct size */ 807 ret = GetFileSize(hfile, NULL); 808 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret); 809 retok = ReadFile(hfile, buf, sizeof(buf), &ret, NULL); 810 ok( retok && ret == sizeof(prefix), 811 "ReadFile: error %d\n", GetLastError()); 812 ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n"); 813 814 /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */ 815 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 816 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); 817 818 ret = CopyFileA(source, dest, FALSE); 819 ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION, 820 "CopyFileA with mapped dest file: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError()); 821 822 CloseHandle(hmapfile); 823 CloseHandle(hfile); 824 825 hfile = CreateFileA(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 826 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n"); 827 828 /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */ 829 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 830 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); 831 832 ret = CopyFileA(source, dest, FALSE); 833 ok(!ret, "CopyFileA: expected failure\n"); 834 ok(GetLastError() == ERROR_USER_MAPPED_FILE || 835 broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x */ 836 "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError()); 837 838 CloseHandle(hmapfile); 839 CloseHandle(hfile); 840 841 ret = DeleteFileA(source); 842 ok(ret, "DeleteFileA: error %d\n", GetLastError()); 843 ret = DeleteFileA(dest); 844 ok(ret, "DeleteFileA: error %d\n", GetLastError()); 845 } 846 847 static void test_CopyFileW(void) 848 { 849 WCHAR temp_path[MAX_PATH]; 850 WCHAR source[MAX_PATH], dest[MAX_PATH]; 851 static const WCHAR prefix[] = {'p','f','x',0}; 852 DWORD ret; 853 854 ret = GetTempPathW(MAX_PATH, temp_path); 855 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 856 { 857 win_skip("GetTempPathW is not available\n"); 858 return; 859 } 860 ok(ret != 0, "GetTempPathW error %d\n", GetLastError()); 861 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 862 863 ret = GetTempFileNameW(temp_path, prefix, 0, source); 864 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 865 866 ret = GetTempFileNameW(temp_path, prefix, 0, dest); 867 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 868 869 ret = CopyFileW(source, dest, TRUE); 870 ok(!ret && GetLastError() == ERROR_FILE_EXISTS, 871 "CopyFileW: unexpected error %d\n", GetLastError()); 872 873 ret = CopyFileW(source, dest, FALSE); 874 ok(ret, "CopyFileW: error %d\n", GetLastError()); 875 876 ret = DeleteFileW(source); 877 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 878 ret = DeleteFileW(dest); 879 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 880 } 881 882 static void test_CopyFile2(void) 883 { 884 static const WCHAR doesntexistW[] = {'d','o','e','s','n','t','e','x','i','s','t',0}; 885 static const WCHAR prefix[] = {'p','f','x',0}; 886 WCHAR source[MAX_PATH], dest[MAX_PATH], temp_path[MAX_PATH]; 887 COPYFILE2_EXTENDED_PARAMETERS params; 888 HANDLE hfile, hmapfile; 889 FILETIME ft1, ft2; 890 DWORD ret, len; 891 char buf[10]; 892 HRESULT hr; 893 894 if (!pCopyFile2) 895 { 896 skip("CopyFile2 is not available\n"); 897 return; 898 } 899 900 ret = GetTempPathW(MAX_PATH, temp_path); 901 ok(ret != 0, "GetTempPathW error %d\n", GetLastError()); 902 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 903 904 ret = GetTempFileNameW(temp_path, prefix, 0, source); 905 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 906 907 ret = GetTempFileNameW(temp_path, prefix, 0, dest); 908 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 909 910 /* fail if exists */ 911 memset(¶ms, 0, sizeof(params)); 912 params.dwSize = sizeof(params); 913 params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS; 914 915 SetLastError(0xdeadbeef); 916 hr = pCopyFile2(source, dest, ¶ms); 917 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr); 918 ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError()); 919 920 /* don't fail if exists */ 921 params.dwSize = sizeof(params); 922 params.dwCopyFlags = 0; 923 924 hr = pCopyFile2(source, dest, ¶ms); 925 ok(hr == S_OK, "CopyFile2: error 0x%08x\n", hr); 926 927 /* copying a file to itself must fail */ 928 params.dwSize = sizeof(params); 929 params.dwCopyFlags = 0; 930 931 SetLastError(0xdeadbeef); 932 hr = pCopyFile2(source, source, ¶ms); 933 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: copying a file to itself didn't fail, 0x%08x\n", hr); 934 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); 935 936 /* make the source have not zero size */ 937 hfile = CreateFileW(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); 938 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n"); 939 ret = WriteFile(hfile, prefix, sizeof(prefix), &len, NULL ); 940 ok(ret && len == sizeof(prefix), "WriteFile error %d\n", GetLastError()); 941 ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n"); 942 943 /* get the file time and change it to prove the difference */ 944 ret = GetFileTime(hfile, NULL, NULL, &ft1); 945 ok(ret, "GetFileTime error %d\n", GetLastError()); 946 ft1.dwLowDateTime -= 600000000; /* 60 second */ 947 ret = SetFileTime(hfile, NULL, NULL, &ft1); 948 ok(ret, "SetFileTime error %d\n", GetLastError()); 949 GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */ 950 CloseHandle(hfile); 951 952 ret = GetTempFileNameW(temp_path, prefix, 0, dest); 953 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 954 955 params.dwSize = sizeof(params); 956 params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS; 957 958 SetLastError(0xdeadbeef); 959 hr = pCopyFile2(source, dest, ¶ms); 960 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr); 961 ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError()); 962 963 params.dwSize = sizeof(params); 964 params.dwCopyFlags = 0; 965 hr = pCopyFile2(source, dest, ¶ms); 966 ok(ret, "CopyFile2: error 0x%08x\n", hr); 967 968 /* copying from a read-locked source fails */ 969 hfile = CreateFileW(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 970 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); 971 972 params.dwSize = sizeof(params); 973 params.dwCopyFlags = 0; 974 SetLastError(0xdeadbeef); 975 hr = pCopyFile2(source, dest, ¶ms); 976 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); 977 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); 978 979 /* in addition, the source is opened before the destination */ 980 params.dwSize = sizeof(params); 981 params.dwCopyFlags = 0; 982 SetLastError(0xdeadbeef); 983 hr = pCopyFile2(doesntexistW, dest, ¶ms); 984 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 985 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "CopyFile2: last error %d\n", GetLastError()); 986 CloseHandle(hfile); 987 988 /* copying from a r+w opened, r shared source succeeds */ 989 hfile = CreateFileW(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 990 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); 991 992 params.dwSize = sizeof(params); 993 params.dwCopyFlags = 0; 994 hr = pCopyFile2(source, dest, ¶ms); 995 ok(hr == S_OK, "failed 0x%08x\n", hr); 996 CloseHandle(hfile); 997 998 /* copying from a delete-locked source mostly succeeds */ 999 hfile = CreateFileW(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1000 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); 1001 1002 params.dwSize = sizeof(params); 1003 params.dwCopyFlags = 0; 1004 hr = pCopyFile2(source, dest, ¶ms); 1005 ok(hr == S_OK, "failed 0x%08x\n", hr); 1006 CloseHandle(hfile); 1007 1008 /* copying to a write-locked destination fails */ 1009 hfile = CreateFileW(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1010 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 1011 1012 params.dwSize = sizeof(params); 1013 params.dwCopyFlags = 0; 1014 SetLastError(0xdeadbeef); 1015 hr = pCopyFile2(source, dest, FALSE); 1016 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); 1017 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); 1018 CloseHandle(hfile); 1019 1020 /* copying to a r+w opened, w shared destination mostly succeeds */ 1021 hfile = CreateFileW(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 1022 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 1023 1024 params.dwSize = sizeof(params); 1025 params.dwCopyFlags = 0; 1026 hr = pCopyFile2(source, dest, FALSE); 1027 ok(hr == S_OK, "got 0x%08x\n", hr); 1028 CloseHandle(hfile); 1029 1030 /* copying to a delete-locked destination fails, even when the destination is delete-shared */ 1031 hfile = CreateFileW(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0); 1032 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 1033 1034 params.dwSize = sizeof(params); 1035 params.dwCopyFlags = 0; 1036 SetLastError(0xdeadbeef); 1037 hr = pCopyFile2(source, dest, ¶ms); 1038 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); 1039 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); 1040 CloseHandle(hfile); 1041 1042 /* copy to a file that's opened the way Wine opens the source */ 1043 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 1044 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 1045 1046 params.dwSize = sizeof(params); 1047 params.dwCopyFlags = 0; 1048 hr = pCopyFile2(source, dest, ¶ms); 1049 ok(hr == S_OK, "got 0x%08x\n", hr); 1050 CloseHandle(hfile); 1051 1052 /* make sure that destination has correct size */ 1053 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1054 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n"); 1055 ret = GetFileSize(hfile, NULL); 1056 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret); 1057 1058 /* make sure that destination has the same filetime */ 1059 ret = GetFileTime(hfile, NULL, NULL, &ft2); 1060 ok(ret, "GetFileTime error %d\n", GetLastError()); 1061 ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n"); 1062 1063 params.dwSize = sizeof(params); 1064 params.dwCopyFlags = 0; 1065 SetLastError(0xdeadbeef); 1066 hr = pCopyFile2(source, dest, ¶ms); 1067 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); 1068 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); 1069 1070 /* make sure that destination still has correct size */ 1071 ret = GetFileSize(hfile, NULL); 1072 ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret); 1073 ret = ReadFile(hfile, buf, sizeof(buf), &len, NULL); 1074 ok(ret && len == sizeof(prefix), "ReadFile: error %d\n", GetLastError()); 1075 ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n"); 1076 1077 /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */ 1078 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 1079 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); 1080 1081 params.dwSize = sizeof(params); 1082 params.dwCopyFlags = 0; 1083 SetLastError(0xdeadbeef); 1084 hr = pCopyFile2(source, dest, ¶ms); 1085 ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); 1086 ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); 1087 1088 CloseHandle(hmapfile); 1089 CloseHandle(hfile); 1090 1091 hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 1092 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n"); 1093 1094 /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */ 1095 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 1096 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); 1097 1098 params.dwSize = sizeof(params); 1099 params.dwCopyFlags = 0; 1100 hr = pCopyFile2(source, dest, ¶ms); 1101 ok(hr == HRESULT_FROM_WIN32(ERROR_USER_MAPPED_FILE), "CopyFile2: unexpected error 0x%08x\n", hr); 1102 ok(GetLastError() == ERROR_USER_MAPPED_FILE, "CopyFile2: last error %d\n", GetLastError()); 1103 1104 CloseHandle(hmapfile); 1105 CloseHandle(hfile); 1106 1107 DeleteFileW(source); 1108 DeleteFileW(dest); 1109 } 1110 1111 static DWORD WINAPI copy_progress_cb(LARGE_INTEGER total_size, LARGE_INTEGER total_transferred, 1112 LARGE_INTEGER stream_size, LARGE_INTEGER stream_transferred, 1113 DWORD stream, DWORD reason, HANDLE source, HANDLE dest, LPVOID userdata) 1114 { 1115 ok(reason == CALLBACK_STREAM_SWITCH, "expected CALLBACK_STREAM_SWITCH, got %u\n", reason); 1116 CloseHandle(userdata); 1117 return PROGRESS_CANCEL; 1118 } 1119 1120 static void test_CopyFileEx(void) 1121 { 1122 char temp_path[MAX_PATH]; 1123 char source[MAX_PATH], dest[MAX_PATH]; 1124 static const char prefix[] = "pfx"; 1125 HANDLE hfile; 1126 DWORD ret; 1127 BOOL retok; 1128 1129 ret = GetTempPathA(MAX_PATH, temp_path); 1130 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 1131 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 1132 1133 ret = GetTempFileNameA(temp_path, prefix, 0, source); 1134 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 1135 1136 ret = GetTempFileNameA(temp_path, prefix, 0, dest); 1137 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 1138 1139 hfile = CreateFileA(dest, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 1140 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 1141 SetLastError(0xdeadbeef); 1142 retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0); 1143 ok(!retok, "CopyFileExA unexpectedly succeeded\n"); 1144 ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError()); 1145 ok(GetFileAttributesA(dest) != INVALID_FILE_ATTRIBUTES, "file was deleted\n"); 1146 1147 hfile = CreateFileA(dest, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_DELETE, 1148 NULL, OPEN_EXISTING, 0, 0); 1149 ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); 1150 SetLastError(0xdeadbeef); 1151 retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0); 1152 ok(!retok, "CopyFileExA unexpectedly succeeded\n"); 1153 ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError()); 1154 ok(GetFileAttributesA(dest) == INVALID_FILE_ATTRIBUTES, "file was not deleted\n"); 1155 1156 ret = DeleteFileA(source); 1157 ok(ret, "DeleteFileA failed with error %d\n", GetLastError()); 1158 ret = DeleteFileA(dest); 1159 ok(!ret, "DeleteFileA unexpectedly succeeded\n"); 1160 } 1161 1162 /* 1163 * Debugging routine to dump a buffer in a hexdump-like fashion. 1164 */ 1165 static void dumpmem(unsigned char *mem, int len) 1166 { 1167 int x = 0; 1168 char hex[49], *p; 1169 char txt[17], *c; 1170 1171 while (x < len) 1172 { 1173 p = hex; 1174 c = txt; 1175 do { 1176 p += sprintf(p, "%02x ", mem[x]); 1177 *c++ = (mem[x] >= 32 && mem[x] <= 127) ? mem[x] : '.'; 1178 } while (++x % 16 && x < len); 1179 *c = '\0'; 1180 trace("%04x: %-48s- %s\n", x, hex, txt); 1181 } 1182 } 1183 1184 static void test_CreateFileA(void) 1185 { 1186 HANDLE hFile; 1187 char temp_path[MAX_PATH], dirname[MAX_PATH]; 1188 char filename[MAX_PATH]; 1189 static const char prefix[] = "pfx"; 1190 char windowsdir[MAX_PATH]; 1191 char Volume_1[MAX_PATH]; 1192 unsigned char buffer[512]; 1193 char directory[] = "removeme"; 1194 static const char nt_drive[] = "\\\\?\\A:"; 1195 DWORD i, ret, len; 1196 static const struct test_list p[] = 1197 { 1198 {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dir as file w \ */ 1199 {"", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* dir as dir w \ */ 1200 {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */ 1201 {"a\\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */ 1202 {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */ 1203 {"removeme\\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exst dir w \ */ 1204 {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */ 1205 {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */ 1206 {"c:\\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */ 1207 {"c:\\", ERROR_SUCCESS, ERROR_ACCESS_DENIED, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* root dir w \ as dir */ 1208 {"c:c:\\windows", ERROR_INVALID_NAME, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* invalid path */ 1209 {"\\\\?\\c:", ERROR_SUCCESS, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL,FALSE }, /* dev namespace drive */ 1210 {"\\\\?\\c:\\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dev namespace drive w \ */ 1211 {NULL, 0, -1, 0, FALSE} 1212 }; 1213 BY_HANDLE_FILE_INFORMATION Finfo; 1214 WCHAR curdir[MAX_PATH]; 1215 1216 ret = GetTempPathA(MAX_PATH, temp_path); 1217 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 1218 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 1219 1220 ret = GetTempFileNameA(temp_path, prefix, 0, filename); 1221 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 1222 1223 SetLastError(0xdeadbeef); 1224 hFile = CreateFileA(filename, GENERIC_READ, 0, NULL, 1225 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0); 1226 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS, 1227 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n"); 1228 1229 SetLastError(0xdeadbeef); 1230 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 1231 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 1232 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS, 1233 "hFile %p, last error %u\n", hFile, GetLastError()); 1234 1235 CloseHandle(hFile); 1236 1237 SetLastError(0xdeadbeef); 1238 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 1239 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 1240 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS, 1241 "hFile %p, last error %u\n", hFile, GetLastError()); 1242 1243 CloseHandle(hFile); 1244 1245 ret = DeleteFileA(filename); 1246 ok(ret, "DeleteFileA: error %d\n", GetLastError()); 1247 1248 SetLastError(0xdeadbeef); 1249 hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 1250 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 1251 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0, 1252 "hFile %p, last error %u\n", hFile, GetLastError()); 1253 1254 CloseHandle(hFile); 1255 1256 ret = DeleteFileA(filename); 1257 ok(ret, "DeleteFileA: error %d\n", GetLastError()); 1258 1259 SetLastError(0xdeadbeef); 1260 hFile = CreateFileA("c:\\*.*", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1261 ok(hFile == INVALID_HANDLE_VALUE, "hFile should have been INVALID_HANDLE_VALUE\n"); 1262 ok(GetLastError() == ERROR_INVALID_NAME || 1263 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */ 1264 "LastError should have been ERROR_INVALID_NAME or ERROR_FILE_NOT_FOUND but got %u\n", GetLastError()); 1265 1266 /* get windows drive letter */ 1267 ret = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir)); 1268 ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n"); 1269 ok(ret != 0, "GetWindowsDirectory: error %d\n", GetLastError()); 1270 1271 /* test error return codes from CreateFile for some cases */ 1272 ret = GetTempPathA(MAX_PATH, temp_path); 1273 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 1274 strcpy(dirname, temp_path); 1275 strcat(dirname, directory); 1276 ret = CreateDirectoryA(dirname, NULL); 1277 ok( ret, "Createdirectory failed, gle=%d\n", GetLastError() ); 1278 /* set current drive & directory to known location */ 1279 GetCurrentDirectoryW( MAX_PATH, curdir); 1280 SetCurrentDirectoryA( temp_path ); 1281 i = 0; 1282 while (p[i].file) 1283 { 1284 filename[0] = 0; 1285 /* update the drive id in the table entry with the current one */ 1286 if (p[i].file[1] == ':') 1287 { 1288 strcpy(filename, p[i].file); 1289 filename[0] = windowsdir[0]; 1290 } 1291 else if (p[i].file[0] == '\\' && p[i].file[5] == ':') 1292 { 1293 strcpy(filename, p[i].file); 1294 filename[4] = windowsdir[0]; 1295 } 1296 else 1297 { 1298 /* prefix the table entry with the current temp directory */ 1299 strcpy(filename, temp_path); 1300 strcat(filename, p[i].file); 1301 } 1302 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1303 FILE_SHARE_READ | FILE_SHARE_WRITE, 1304 NULL, OPEN_EXISTING, 1305 p[i].options, NULL ); 1306 /* if we get ACCESS_DENIED when we do not expect it, assume 1307 * no access to the volume 1308 */ 1309 if (hFile == INVALID_HANDLE_VALUE && 1310 GetLastError() == ERROR_ACCESS_DENIED && 1311 p[i].err != ERROR_ACCESS_DENIED) 1312 { 1313 if (p[i].todo_flag) 1314 skip("Either no authority to volume, or is todo_wine for %s err=%d should be %d\n", filename, GetLastError(), p[i].err); 1315 else 1316 skip("Do not have authority to access volumes. Test for %s skipped\n", filename); 1317 } 1318 /* otherwise validate results with expectations */ 1319 else 1320 { 1321 todo_wine_if (p[i].todo_flag) 1322 ok((hFile == INVALID_HANDLE_VALUE && 1323 (p[i].err == GetLastError() || p[i].err2 == GetLastError())) || 1324 (hFile != INVALID_HANDLE_VALUE && p[i].err == ERROR_SUCCESS), 1325 "CreateFileA failed on %s, hFile %p, err=%u, should be %u\n", 1326 filename, hFile, GetLastError(), p[i].err); 1327 } 1328 if (hFile != INVALID_HANDLE_VALUE) 1329 CloseHandle( hFile ); 1330 i++; 1331 } 1332 ret = RemoveDirectoryA(dirname); 1333 ok(ret, "RemoveDirectoryA: error %d\n", GetLastError()); 1334 SetCurrentDirectoryW(curdir); 1335 1336 /* test opening directory as a directory */ 1337 hFile = CreateFileA( temp_path, GENERIC_READ, 1338 FILE_SHARE_READ, 1339 NULL, 1340 OPEN_EXISTING, 1341 FILE_FLAG_BACKUP_SEMANTICS, NULL ); 1342 if (hFile != INVALID_HANDLE_VALUE && GetLastError() != ERROR_PATH_NOT_FOUND) 1343 { 1344 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_SUCCESS, 1345 "CreateFileA did not work, last error %u on volume <%s>\n", 1346 GetLastError(), temp_path ); 1347 1348 if (hFile != INVALID_HANDLE_VALUE) 1349 { 1350 ret = GetFileInformationByHandle( hFile, &Finfo ); 1351 if (ret) 1352 { 1353 ok(Finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY, 1354 "CreateFileA probably did not open temp directory %s correctly\n file information does not include FILE_ATTRIBUTE_DIRECTORY, actual=0x%08x\n", 1355 temp_path, Finfo.dwFileAttributes); 1356 } 1357 CloseHandle( hFile ); 1358 } 1359 } 1360 else 1361 skip("Probable Win9x, got ERROR_PATH_NOT_FOUND w/ FILE_FLAG_BACKUP_SEMANTICS or %s\n", temp_path); 1362 1363 1364 /* *** Test opening volumes/devices using drive letter *** */ 1365 1366 /* test using drive letter in non-rewrite format without trailing \ */ 1367 /* this should work */ 1368 strcpy(filename, nt_drive); 1369 filename[4] = windowsdir[0]; 1370 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1371 FILE_SHARE_READ | FILE_SHARE_WRITE, 1372 NULL, OPEN_EXISTING, 1373 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL ); 1374 if (hFile != INVALID_HANDLE_VALUE || 1375 (GetLastError() != ERROR_ACCESS_DENIED && GetLastError() != ERROR_BAD_NETPATH)) 1376 { 1377 /* if we have adm rights to volume, then try rest of tests */ 1378 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n", 1379 filename, GetLastError()); 1380 if (hFile != INVALID_HANDLE_VALUE) 1381 { 1382 /* if we opened the volume/device, try to read it. Since it */ 1383 /* opened, we should be able to read it. We don't care about*/ 1384 /* what the data is at this time. */ 1385 len = 512; 1386 ret = ReadFile( hFile, buffer, len, &len, NULL ); 1387 todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n", 1388 GetLastError(), ret, filename); 1389 if (ret) 1390 { 1391 trace("buffer is\n"); 1392 dumpmem(buffer, 64); 1393 } 1394 CloseHandle( hFile ); 1395 } 1396 1397 /* test using drive letter with trailing \ and in non-rewrite */ 1398 /* this should not work */ 1399 strcpy(filename, nt_drive); 1400 filename[4] = windowsdir[0]; 1401 strcat( filename, "\\" ); 1402 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1403 FILE_SHARE_READ | FILE_SHARE_WRITE, 1404 NULL, OPEN_EXISTING, 1405 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL ); 1406 todo_wine 1407 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND, 1408 "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n", 1409 filename, GetLastError()); 1410 if (hFile != INVALID_HANDLE_VALUE) 1411 CloseHandle( hFile ); 1412 1413 /* test using temp path with trailing \ and in non-rewrite as dir */ 1414 /* this should work */ 1415 strcpy(filename, nt_drive); 1416 filename[4] = 0; 1417 strcat( filename, temp_path ); 1418 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1419 FILE_SHARE_READ | FILE_SHARE_WRITE, 1420 NULL, OPEN_EXISTING, 1421 FILE_FLAG_BACKUP_SEMANTICS, NULL ); 1422 ok(hFile != INVALID_HANDLE_VALUE, 1423 "CreateFileA should have worked on %s, but got %u\n", 1424 filename, GetLastError()); 1425 if (hFile != INVALID_HANDLE_VALUE) 1426 CloseHandle( hFile ); 1427 1428 /* test using drive letter without trailing \ and in device ns */ 1429 /* this should work */ 1430 strcpy(filename, nt_drive); 1431 filename[4] = windowsdir[0]; 1432 filename[2] = '.'; 1433 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1434 FILE_SHARE_READ | FILE_SHARE_WRITE, 1435 NULL, OPEN_EXISTING, 1436 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL ); 1437 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n", 1438 filename, GetLastError()); 1439 if (hFile != INVALID_HANDLE_VALUE) 1440 CloseHandle( hFile ); 1441 } 1442 /* If we see ERROR_BAD_NETPATH then on Win9x or WinME, so skip */ 1443 else if (GetLastError() == ERROR_BAD_NETPATH) 1444 skip("Probable Win9x, got ERROR_BAD_NETPATH (53)\n"); 1445 else 1446 skip("Do not have authority to access volumes. Tests skipped\n"); 1447 1448 1449 /* *** Test opening volumes/devices using GUID *** */ 1450 1451 if (pGetVolumeNameForVolumeMountPointA) 1452 { 1453 strcpy(filename, "c:\\"); 1454 filename[0] = windowsdir[0]; 1455 ret = pGetVolumeNameForVolumeMountPointA( filename, Volume_1, MAX_PATH ); 1456 ok(ret, "GetVolumeNameForVolumeMountPointA failed, for %s, last error=%d\n", filename, GetLastError()); 1457 if (ret) 1458 { 1459 ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name <%s>\n", Volume_1); 1460 1461 /* test the result of opening a unique volume name (GUID) 1462 * with the trailing \ 1463 * this should error out 1464 */ 1465 strcpy(filename, Volume_1); 1466 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1467 FILE_SHARE_READ | FILE_SHARE_WRITE, 1468 NULL, OPEN_EXISTING, 1469 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL ); 1470 todo_wine 1471 ok(hFile == INVALID_HANDLE_VALUE, 1472 "CreateFileA should not have opened %s, hFile %p\n", 1473 filename, hFile); 1474 todo_wine 1475 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND, 1476 "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n", 1477 filename, GetLastError()); 1478 if (hFile != INVALID_HANDLE_VALUE) 1479 CloseHandle( hFile ); 1480 1481 /* test the result of opening a unique volume name (GUID) 1482 * with the temp path string as dir 1483 * this should work 1484 */ 1485 strcpy(filename, Volume_1); 1486 strcat(filename, temp_path+3); 1487 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1488 FILE_SHARE_READ | FILE_SHARE_WRITE, 1489 NULL, OPEN_EXISTING, 1490 FILE_FLAG_BACKUP_SEMANTICS, NULL ); 1491 todo_wine 1492 ok(hFile != INVALID_HANDLE_VALUE, 1493 "CreateFileA should have opened %s, but got %u\n", 1494 filename, GetLastError()); 1495 if (hFile != INVALID_HANDLE_VALUE) 1496 CloseHandle( hFile ); 1497 1498 /* test the result of opening a unique volume name (GUID) 1499 * without the trailing \ and in device namespace 1500 * this should work 1501 */ 1502 strcpy(filename, Volume_1); 1503 filename[2] = '.'; 1504 filename[48] = 0; 1505 hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 1506 FILE_SHARE_READ | FILE_SHARE_WRITE, 1507 NULL, OPEN_EXISTING, 1508 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL ); 1509 if (hFile != INVALID_HANDLE_VALUE || GetLastError() != ERROR_ACCESS_DENIED) 1510 { 1511 /* if we have adm rights to volume, then try rest of tests */ 1512 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n", 1513 filename, GetLastError()); 1514 if (hFile != INVALID_HANDLE_VALUE) 1515 { 1516 /* if we opened the volume/device, try to read it. Since it */ 1517 /* opened, we should be able to read it. We don't care about*/ 1518 /* what the data is at this time. */ 1519 len = 512; 1520 ret = ReadFile( hFile, buffer, len, &len, NULL ); 1521 todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n", 1522 GetLastError(), ret, filename); 1523 if (ret) 1524 { 1525 trace("buffer is\n"); 1526 dumpmem(buffer, 64); 1527 } 1528 CloseHandle( hFile ); 1529 } 1530 } 1531 else 1532 skip("Do not have authority to access volumes. Tests skipped\n"); 1533 } 1534 else 1535 win_skip("GetVolumeNameForVolumeMountPointA not functioning\n"); 1536 } 1537 else 1538 win_skip("GetVolumeNameForVolumeMountPointA not found\n"); 1539 } 1540 1541 static void test_CreateFileW(void) 1542 { 1543 HANDLE hFile; 1544 WCHAR temp_path[MAX_PATH]; 1545 WCHAR filename[MAX_PATH]; 1546 static const WCHAR emptyW[]={'\0'}; 1547 static const WCHAR prefix[] = {'p','f','x',0}; 1548 static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 }; 1549 DWORD ret; 1550 1551 ret = GetTempPathW(MAX_PATH, temp_path); 1552 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1553 { 1554 win_skip("GetTempPathW is not available\n"); 1555 return; 1556 } 1557 ok(ret != 0, "GetTempPathW error %d\n", GetLastError()); 1558 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 1559 1560 ret = GetTempFileNameW(temp_path, prefix, 0, filename); 1561 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 1562 1563 SetLastError(0xdeadbeef); 1564 hFile = CreateFileW(filename, GENERIC_READ, 0, NULL, 1565 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0); 1566 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS, 1567 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n"); 1568 1569 SetLastError(0xdeadbeef); 1570 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 1571 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 1572 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS, 1573 "hFile %p, last error %u\n", hFile, GetLastError()); 1574 1575 CloseHandle(hFile); 1576 1577 SetLastError(0xdeadbeef); 1578 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 1579 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 1580 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS, 1581 "hFile %p, last error %u\n", hFile, GetLastError()); 1582 1583 CloseHandle(hFile); 1584 1585 ret = DeleteFileW(filename); 1586 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 1587 1588 SetLastError(0xdeadbeef); 1589 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 1590 OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 1591 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0, 1592 "hFile %p, last error %u\n", hFile, GetLastError()); 1593 1594 CloseHandle(hFile); 1595 1596 ret = DeleteFileW(filename); 1597 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 1598 1599 if (0) 1600 { 1601 /* this crashes on NT4.0 */ 1602 hFile = CreateFileW(NULL, GENERIC_READ, 0, NULL, 1603 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0); 1604 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND, 1605 "CreateFileW(NULL) returned ret=%p error=%u\n",hFile,GetLastError()); 1606 } 1607 1608 hFile = CreateFileW(emptyW, GENERIC_READ, 0, NULL, 1609 CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0); 1610 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND, 1611 "CreateFileW(\"\") returned ret=%p error=%d\n",hFile,GetLastError()); 1612 1613 /* test the result of opening a nonexistent driver name */ 1614 hFile = CreateFileW(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 1615 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1616 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND, 1617 "CreateFileW on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError()); 1618 1619 ret = CreateDirectoryW(filename, NULL); 1620 ok(ret == TRUE, "couldn't create temporary directory\n"); 1621 hFile = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 1622 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); 1623 ok(hFile != INVALID_HANDLE_VALUE, 1624 "expected CreateFile to succeed on existing directory, error: %d\n", GetLastError()); 1625 CloseHandle(hFile); 1626 ret = RemoveDirectoryW(filename); 1627 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 1628 } 1629 1630 static void test_CreateFile2(void) 1631 { 1632 HANDLE hFile; 1633 WCHAR temp_path[MAX_PATH]; 1634 WCHAR filename[MAX_PATH]; 1635 CREATEFILE2_EXTENDED_PARAMETERS exparams; 1636 static const WCHAR emptyW[]={'\0'}; 1637 static const WCHAR prefix[] = {'p','f','x',0}; 1638 static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 }; 1639 DWORD ret; 1640 1641 if (!pCreateFile2) 1642 { 1643 win_skip("CreateFile2 is missing\n"); 1644 return; 1645 } 1646 1647 ret = GetTempPathW(MAX_PATH, temp_path); 1648 ok(ret != 0, "GetTempPathW error %d\n", GetLastError()); 1649 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 1650 1651 ret = GetTempFileNameW(temp_path, prefix, 0, filename); 1652 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 1653 1654 SetLastError(0xdeadbeef); 1655 exparams.dwSize = sizeof(exparams); 1656 exparams.dwFileAttributes = FILE_FLAG_RANDOM_ACCESS; 1657 exparams.dwFileFlags = 0; 1658 exparams.dwSecurityQosFlags = 0; 1659 exparams.lpSecurityAttributes = NULL; 1660 exparams.hTemplateFile = 0; 1661 hFile = pCreateFile2(filename, GENERIC_READ, 0, CREATE_NEW, &exparams); 1662 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS, 1663 "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n"); 1664 1665 SetLastError(0xdeadbeef); 1666 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, CREATE_ALWAYS, &exparams); 1667 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS, 1668 "hFile %p, last error %u\n", hFile, GetLastError()); 1669 CloseHandle(hFile); 1670 1671 SetLastError(0xdeadbeef); 1672 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams); 1673 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS, 1674 "hFile %p, last error %u\n", hFile, GetLastError()); 1675 CloseHandle(hFile); 1676 1677 ret = DeleteFileW(filename); 1678 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 1679 1680 SetLastError(0xdeadbeef); 1681 hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams); 1682 ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0, 1683 "hFile %p, last error %u\n", hFile, GetLastError()); 1684 CloseHandle(hFile); 1685 1686 ret = DeleteFileW(filename); 1687 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 1688 1689 hFile = pCreateFile2(emptyW, GENERIC_READ, 0, CREATE_NEW, &exparams); 1690 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND, 1691 "CreateFile2(\"\") returned ret=%p error=%d\n",hFile,GetLastError()); 1692 1693 /* test the result of opening a nonexistent driver name */ 1694 exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; 1695 hFile = pCreateFile2(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &exparams); 1696 ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND, 1697 "CreateFile2 on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError()); 1698 1699 ret = CreateDirectoryW(filename, NULL); 1700 ok(ret == TRUE, "couldn't create temporary directory\n"); 1701 exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS; 1702 hFile = pCreateFile2(filename, GENERIC_READ | GENERIC_WRITE, 0, OPEN_ALWAYS, &exparams); 1703 todo_wine 1704 ok(hFile == INVALID_HANDLE_VALUE, 1705 "expected CreateFile2 to fail on existing directory, error: %d\n", GetLastError()); 1706 CloseHandle(hFile); 1707 ret = RemoveDirectoryW(filename); 1708 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 1709 } 1710 1711 static void test_GetTempFileNameA(void) 1712 { 1713 UINT result; 1714 char out[MAX_PATH]; 1715 char expected[MAX_PATH + 10]; 1716 char windowsdir[MAX_PATH + 10]; 1717 char windowsdrive[3]; 1718 1719 result = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir)); 1720 ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n"); 1721 ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError()); 1722 1723 /* If the Windows directory is the root directory, it ends in backslash, not else. */ 1724 if (strlen(windowsdir) != 3) /* As in "C:\" or "F:\" */ 1725 { 1726 strcat(windowsdir, "\\"); 1727 } 1728 1729 windowsdrive[0] = windowsdir[0]; 1730 windowsdrive[1] = windowsdir[1]; 1731 windowsdrive[2] = '\0'; 1732 1733 result = GetTempFileNameA(windowsdrive, "abc", 1, out); 1734 ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError()); 1735 ok(((out[0] == windowsdrive[0]) && (out[1] == ':')) && (out[2] == '\\'), 1736 "GetTempFileNameA: first three characters should be %c:\\, string was actually %s\n", 1737 windowsdrive[0], out); 1738 1739 result = GetTempFileNameA(windowsdir, "abc", 2, out); 1740 ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError()); 1741 expected[0] = '\0'; 1742 strcat(expected, windowsdir); 1743 strcat(expected, "abc2.tmp"); 1744 ok(lstrcmpiA(out, expected) == 0, "GetTempFileNameA: Unexpected output \"%s\" vs \"%s\"\n", 1745 out, expected); 1746 } 1747 1748 static void test_DeleteFileA( void ) 1749 { 1750 BOOL ret; 1751 char temp_path[MAX_PATH], temp_file[MAX_PATH]; 1752 HANDLE hfile; 1753 1754 ret = DeleteFileA(NULL); 1755 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || 1756 GetLastError() == ERROR_PATH_NOT_FOUND), 1757 "DeleteFileA(NULL) returned ret=%d error=%d\n",ret,GetLastError()); 1758 1759 ret = DeleteFileA(""); 1760 ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND || 1761 GetLastError() == ERROR_BAD_PATHNAME), 1762 "DeleteFileA(\"\") returned ret=%d error=%d\n",ret,GetLastError()); 1763 1764 ret = DeleteFileA("nul"); 1765 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND || 1766 GetLastError() == ERROR_INVALID_PARAMETER || 1767 GetLastError() == ERROR_ACCESS_DENIED || 1768 GetLastError() == ERROR_INVALID_FUNCTION), 1769 "DeleteFileA(\"nul\") returned ret=%d error=%d\n",ret,GetLastError()); 1770 1771 ret = DeleteFileA("nonexist.txt"); 1772 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "DeleteFileA(\"nonexist.txt\") returned ret=%d error=%d\n",ret,GetLastError()); 1773 1774 GetTempPathA(MAX_PATH, temp_path); 1775 GetTempFileNameA(temp_path, "tst", 0, temp_file); 1776 1777 SetLastError(0xdeadbeef); 1778 hfile = CreateFileA(temp_file, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1779 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError()); 1780 1781 SetLastError(0xdeadbeef); 1782 ret = DeleteFileA(temp_file); 1783 ok(ret, "DeleteFile error %d\n", GetLastError()); 1784 1785 SetLastError(0xdeadbeef); 1786 ret = CloseHandle(hfile); 1787 ok(ret, "CloseHandle error %d\n", GetLastError()); 1788 ret = DeleteFileA(temp_file); 1789 ok(!ret, "DeleteFile should fail\n"); 1790 1791 SetLastError(0xdeadbeef); 1792 ret = CreateDirectoryA("testdir", NULL); 1793 ok(ret, "CreateDirectory failed, got err %d\n", GetLastError()); 1794 ret = DeleteFileA("testdir"); 1795 ok(!ret && GetLastError() == ERROR_ACCESS_DENIED, 1796 "Expected ERROR_ACCESS_DENIED, got error %d\n", GetLastError()); 1797 ret = RemoveDirectoryA("testdir"); 1798 ok(ret, "Remove a directory failed, got error %d\n", GetLastError()); 1799 } 1800 1801 static void test_DeleteFileW( void ) 1802 { 1803 BOOL ret; 1804 WCHAR pathW[MAX_PATH]; 1805 WCHAR pathsubW[MAX_PATH]; 1806 static const WCHAR dirW[] = {'d','e','l','e','t','e','f','i','l','e',0}; 1807 static const WCHAR subdirW[] = {'\\','s','u','b',0}; 1808 static const WCHAR emptyW[]={'\0'}; 1809 1810 ret = DeleteFileW(NULL); 1811 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1812 { 1813 win_skip("DeleteFileW is not available\n"); 1814 return; 1815 } 1816 ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, 1817 "DeleteFileW(NULL) returned ret=%d error=%d\n",ret,GetLastError()); 1818 1819 ret = DeleteFileW(emptyW); 1820 ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, 1821 "DeleteFileW(\"\") returned ret=%d error=%d\n",ret,GetLastError()); 1822 1823 /* test DeleteFile on empty directory */ 1824 ret = GetTempPathW(MAX_PATH, pathW); 1825 if (ret + sizeof(dirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH) 1826 { 1827 ok(0, "MAX_PATH exceeded in constructing paths\n"); 1828 return; 1829 } 1830 lstrcatW(pathW, dirW); 1831 lstrcpyW(pathsubW, pathW); 1832 lstrcatW(pathsubW, subdirW); 1833 ret = CreateDirectoryW(pathW, NULL); 1834 ok(ret == TRUE, "couldn't create directory deletefile\n"); 1835 ret = DeleteFileW(pathW); 1836 ok(ret == FALSE, "DeleteFile should fail for empty directories\n"); 1837 ret = RemoveDirectoryW(pathW); 1838 ok(ret == TRUE, "expected to remove directory deletefile\n"); 1839 1840 /* test DeleteFile on non-empty directory */ 1841 ret = CreateDirectoryW(pathW, NULL); 1842 ok(ret == TRUE, "couldn't create directory deletefile\n"); 1843 ret = CreateDirectoryW(pathsubW, NULL); 1844 ok(ret == TRUE, "couldn't create directory deletefile\\sub\n"); 1845 ret = DeleteFileW(pathW); 1846 ok(ret == FALSE, "DeleteFile should fail for non-empty directories\n"); 1847 ret = RemoveDirectoryW(pathsubW); 1848 ok(ret == TRUE, "expected to remove directory deletefile\\sub\n"); 1849 ret = RemoveDirectoryW(pathW); 1850 ok(ret == TRUE, "expected to remove directory deletefile\n"); 1851 } 1852 1853 #define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0)))) 1854 1855 static void test_MoveFileA(void) 1856 { 1857 char tempdir[MAX_PATH]; 1858 char source[MAX_PATH], dest[MAX_PATH]; 1859 static const char prefix[] = "pfx"; 1860 HANDLE hfile; 1861 HANDLE hmapfile; 1862 DWORD ret; 1863 BOOL retok; 1864 1865 ret = GetTempPathA(MAX_PATH, tempdir); 1866 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 1867 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 1868 1869 ret = GetTempFileNameA(tempdir, prefix, 0, source); 1870 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 1871 1872 ret = GetTempFileNameA(tempdir, prefix, 0, dest); 1873 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 1874 1875 ret = MoveFileA(source, source); 1876 ok(ret, "MoveFileA: failed, error %d\n", GetLastError()); 1877 1878 ret = MoveFileA(source, dest); 1879 ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS, 1880 "MoveFileA: unexpected error %d\n", GetLastError()); 1881 1882 ret = DeleteFileA(dest); 1883 ok(ret, "DeleteFileA: error %d\n", GetLastError()); 1884 1885 hfile = CreateFileA(source, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 1886 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n"); 1887 1888 retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL ); 1889 ok( retok && ret == sizeof(prefix), 1890 "WriteFile error %d\n", GetLastError()); 1891 1892 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 1893 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); 1894 1895 ret = MoveFileA(source, dest); 1896 ok(!ret, "MoveFileA: expected failure\n"); 1897 ok(GetLastError() == ERROR_SHARING_VIOLATION || 1898 broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */ 1899 "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError()); 1900 1901 CloseHandle(hmapfile); 1902 CloseHandle(hfile); 1903 1904 /* if MoveFile succeeded, move back to dest */ 1905 if (ret) MoveFileA(dest, source); 1906 1907 hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1908 ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n"); 1909 1910 hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 1911 ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); 1912 1913 ret = MoveFileA(source, dest); 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()); 1918 1919 CloseHandle(hmapfile); 1920 CloseHandle(hfile); 1921 1922 /* if MoveFile succeeded, move back to dest */ 1923 if (ret) MoveFileA(dest, source); 1924 1925 ret = MoveFileA(source, dest); 1926 ok(ret, "MoveFileA: failed, error %d\n", GetLastError()); 1927 1928 lstrcatA(tempdir, "Remove Me"); 1929 ret = CreateDirectoryA(tempdir, NULL); 1930 ok(ret == TRUE, "CreateDirectoryA failed\n"); 1931 1932 lstrcpyA(source, dest); 1933 lstrcpyA(dest, tempdir); 1934 lstrcatA(dest, "\\wild?.*"); 1935 /* FIXME: if we create a file with wildcards we can't delete it now that DeleteFile works correctly */ 1936 ret = MoveFileA(source, dest); 1937 ok(!ret, "MoveFileA: shouldn't move to wildcard file\n"); 1938 ok(GetLastError() == ERROR_INVALID_NAME || /* NT */ 1939 GetLastError() == ERROR_FILE_NOT_FOUND, /* Win9x */ 1940 "MoveFileA: with wildcards, unexpected error %d\n", GetLastError()); 1941 if (ret || (GetLastError() != ERROR_INVALID_NAME)) 1942 { 1943 WIN32_FIND_DATAA fd; 1944 char temppath[MAX_PATH]; 1945 HANDLE hFind; 1946 1947 lstrcpyA(temppath, tempdir); 1948 lstrcatA(temppath, "\\*.*"); 1949 hFind = FindFirstFileA(temppath, &fd); 1950 if (INVALID_HANDLE_VALUE != hFind) 1951 { 1952 LPSTR lpName; 1953 do 1954 { 1955 lpName = fd.cAlternateFileName; 1956 if (!lpName[0]) 1957 lpName = fd.cFileName; 1958 ok(IsDotDir(lpName), "MoveFileA: wildcards file created!\n"); 1959 } 1960 while (FindNextFileA(hFind, &fd)); 1961 FindClose(hFind); 1962 } 1963 } 1964 ret = DeleteFileA(source); 1965 ok(ret, "DeleteFileA: error %d\n", GetLastError()); 1966 ret = DeleteFileA(dest); 1967 ok(!ret, "DeleteFileA: error %d\n", GetLastError()); 1968 ret = RemoveDirectoryA(tempdir); 1969 ok(ret, "DeleteDirectoryA: error %d\n", GetLastError()); 1970 } 1971 1972 static void test_MoveFileW(void) 1973 { 1974 WCHAR temp_path[MAX_PATH]; 1975 WCHAR source[MAX_PATH], dest[MAX_PATH]; 1976 static const WCHAR prefix[] = {'p','f','x',0}; 1977 DWORD ret; 1978 1979 ret = GetTempPathW(MAX_PATH, temp_path); 1980 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1981 { 1982 win_skip("GetTempPathW is not available\n"); 1983 return; 1984 } 1985 ok(ret != 0, "GetTempPathW error %d\n", GetLastError()); 1986 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 1987 1988 ret = GetTempFileNameW(temp_path, prefix, 0, source); 1989 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 1990 1991 ret = GetTempFileNameW(temp_path, prefix, 0, dest); 1992 ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); 1993 1994 ret = MoveFileW(source, dest); 1995 ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS, 1996 "CopyFileW: unexpected error %d\n", GetLastError()); 1997 1998 ret = DeleteFileW(source); 1999 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 2000 ret = DeleteFileW(dest); 2001 ok(ret, "DeleteFileW: error %d\n", GetLastError()); 2002 } 2003 2004 #define PATTERN_OFFSET 0x10 2005 2006 static void test_offset_in_overlapped_structure(void) 2007 { 2008 HANDLE hFile; 2009 OVERLAPPED ov; 2010 DWORD done, offset; 2011 BOOL rc; 2012 BYTE buf[256], pattern[] = "TeSt"; 2013 UINT i; 2014 char temp_path[MAX_PATH], temp_fname[MAX_PATH]; 2015 BOOL ret; 2016 2017 ret =GetTempPathA(MAX_PATH, temp_path); 2018 ok( ret, "GetTempPathA error %d\n", GetLastError()); 2019 ret =GetTempFileNameA(temp_path, "pfx", 0, temp_fname); 2020 ok( ret, "GetTempFileNameA error %d\n", GetLastError()); 2021 2022 /*** Write File *****************************************************/ 2023 2024 hFile = CreateFileA(temp_fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 2025 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError()); 2026 2027 for(i = 0; i < sizeof(buf); i++) buf[i] = i; 2028 ret = WriteFile(hFile, buf, sizeof(buf), &done, NULL); 2029 ok( ret, "WriteFile error %d\n", GetLastError()); 2030 ok(done == sizeof(buf), "expected number of bytes written %u\n", done); 2031 2032 memset(&ov, 0, sizeof(ov)); 2033 S(U(ov)).Offset = PATTERN_OFFSET; 2034 S(U(ov)).OffsetHigh = 0; 2035 rc=WriteFile(hFile, pattern, sizeof(pattern), &done, &ov); 2036 /* Win 9x does not support the overlapped I/O on files */ 2037 if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) { 2038 ok(rc, "WriteFile error %d\n", GetLastError()); 2039 ok(done == sizeof(pattern), "expected number of bytes written %u\n", done); 2040 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); 2041 ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset); 2042 2043 S(U(ov)).Offset = sizeof(buf) * 2; 2044 S(U(ov)).OffsetHigh = 0; 2045 ret = WriteFile(hFile, pattern, sizeof(pattern), &done, &ov); 2046 ok( ret, "WriteFile error %d\n", GetLastError()); 2047 ok(done == sizeof(pattern), "expected number of bytes written %u\n", done); 2048 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); 2049 ok(offset == sizeof(buf) * 2 + sizeof(pattern), "wrong file offset %d\n", offset); 2050 } 2051 2052 CloseHandle(hFile); 2053 2054 /*** Read File *****************************************************/ 2055 2056 hFile = CreateFileA(temp_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); 2057 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError()); 2058 2059 memset(buf, 0, sizeof(buf)); 2060 memset(&ov, 0, sizeof(ov)); 2061 S(U(ov)).Offset = PATTERN_OFFSET; 2062 S(U(ov)).OffsetHigh = 0; 2063 rc=ReadFile(hFile, buf, sizeof(pattern), &done, &ov); 2064 /* Win 9x does not support the overlapped I/O on files */ 2065 if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) { 2066 ok(rc, "ReadFile error %d\n", GetLastError()); 2067 ok(done == sizeof(pattern), "expected number of bytes read %u\n", done); 2068 offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); 2069 ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset); 2070 ok(!memcmp(buf, pattern, sizeof(pattern)), "pattern match failed\n"); 2071 } 2072 2073 CloseHandle(hFile); 2074 2075 ret = DeleteFileA(temp_fname); 2076 ok( ret, "DeleteFileA error %d\n", GetLastError()); 2077 } 2078 2079 static void test_LockFile(void) 2080 { 2081 HANDLE handle, handle2; 2082 DWORD written; 2083 OVERLAPPED overlapped; 2084 int limited_LockFile; 2085 int limited_UnLockFile; 2086 BOOL ret; 2087 2088 handle = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 2089 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 2090 CREATE_ALWAYS, 0, 0 ); 2091 if (handle == INVALID_HANDLE_VALUE) 2092 { 2093 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 2094 return; 2095 } 2096 handle2 = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 2097 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 2098 OPEN_EXISTING, 0, 0 ); 2099 if (handle2 == INVALID_HANDLE_VALUE) 2100 { 2101 ok( 0, "couldn't open file \"%s\" (err=%d)\n", filename, GetLastError() ); 2102 goto cleanup; 2103 } 2104 ok( WriteFile( handle, sillytext, strlen(sillytext), &written, NULL ), "write failed\n" ); 2105 2106 ok( LockFile( handle, 0, 0, 0, 0 ), "LockFile failed\n" ); 2107 ok( UnlockFile( handle, 0, 0, 0, 0 ), "UnlockFile failed\n" ); 2108 2109 limited_UnLockFile = 0; 2110 if (UnlockFile( handle, 0, 0, 0, 0 )) 2111 { 2112 limited_UnLockFile = 1; 2113 } 2114 2115 ok( LockFile( handle, 10, 0, 20, 0 ), "LockFile 10,20 failed\n" ); 2116 /* overlapping locks must fail */ 2117 ok( !LockFile( handle, 12, 0, 10, 0 ), "LockFile 12,10 succeeded\n" ); 2118 ok( !LockFile( handle, 5, 0, 6, 0 ), "LockFile 5,6 succeeded\n" ); 2119 /* non-overlapping locks must succeed */ 2120 ok( LockFile( handle, 5, 0, 5, 0 ), "LockFile 5,5 failed\n" ); 2121 2122 ok( !UnlockFile( handle, 10, 0, 10, 0 ), "UnlockFile 10,10 succeeded\n" ); 2123 ok( UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 failed\n" ); 2124 ok( !UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 again succeeded\n" ); 2125 ok( UnlockFile( handle, 5, 0, 5, 0 ), "UnlockFile 5,5 failed\n" ); 2126 2127 S(U(overlapped)).Offset = 100; 2128 S(U(overlapped)).OffsetHigh = 0; 2129 overlapped.hEvent = 0; 2130 2131 /* Test for broken LockFileEx a la Windows 95 OSR2. */ 2132 if (LockFileEx( handle, 0, 0, 100, 0, &overlapped )) 2133 { 2134 /* LockFileEx is probably OK, test it more. */ 2135 ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), 2136 "LockFileEx 100,100 failed\n" ); 2137 } 2138 2139 /* overlapping shared locks are OK */ 2140 S(U(overlapped)).Offset = 150; 2141 limited_UnLockFile || ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 150,100 failed\n" ); 2142 2143 /* but exclusive is not */ 2144 ok( !LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 2145 0, 50, 0, &overlapped ), 2146 "LockFileEx exclusive 150,50 succeeded\n" ); 2147 if (!UnlockFileEx( handle, 0, 100, 0, &overlapped )) 2148 { /* UnLockFile is capable. */ 2149 S(U(overlapped)).Offset = 100; 2150 ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ), 2151 "UnlockFileEx 150,100 again succeeded\n" ); 2152 } 2153 2154 /* shared lock can overlap exclusive if handles are equal */ 2155 S(U(overlapped)).Offset = 300; 2156 ok( LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, &overlapped ), 2157 "LockFileEx exclusive 300,100 failed\n" ); 2158 ok( !LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ), 2159 "LockFileEx handle2 300,100 succeeded\n" ); 2160 ret = LockFileEx( handle, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ); 2161 ok( ret, "LockFileEx 300,100 failed\n" ); 2162 ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" ); 2163 /* exclusive lock is removed first */ 2164 ok( LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ), 2165 "LockFileEx handle2 300,100 failed\n" ); 2166 ok( UnlockFileEx( handle2, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" ); 2167 if (ret) 2168 ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" ); 2169 2170 ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 ); 2171 if (ret) 2172 { 2173 ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" ); 2174 ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" ); 2175 ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" ); 2176 } 2177 else /* win9x */ 2178 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong LockFile error %u\n", GetLastError() ); 2179 2180 /* wrap-around lock should not do anything */ 2181 /* (but still succeeds on NT4 so we don't check result) */ 2182 LockFile( handle, 0, 0x10000000, 0, 0xf0000001 ); 2183 2184 limited_LockFile = 0; 2185 if (!LockFile( handle, ~0, ~0, 1, 0 )) 2186 { 2187 limited_LockFile = 1; 2188 } 2189 2190 limited_UnLockFile || ok( UnlockFile( handle, ~0, ~0, 1, 0 ), "Unlockfile ~0,1 failed\n" ); 2191 2192 /* zero-byte lock */ 2193 ok( LockFile( handle, 100, 0, 0, 0 ), "LockFile 100,0 failed\n" ); 2194 if (!limited_LockFile) ok( !LockFile( handle, 98, 0, 4, 0 ), "LockFile 98,4 succeeded\n" ); 2195 ok( LockFile( handle, 90, 0, 10, 0 ), "LockFile 90,10 failed\n" ); 2196 if (!limited_LockFile) ok( !LockFile( handle, 100, 0, 10, 0 ), "LockFile 100,10 failed\n" ); 2197 2198 ok( UnlockFile( handle, 90, 0, 10, 0 ), "UnlockFile 90,10 failed\n" ); 2199 ok( !UnlockFile( handle, 100, 0, 10, 0 ), "UnlockFile 100,10 succeeded\n" ); 2200 2201 ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed\n" ); 2202 2203 CloseHandle( handle2 ); 2204 cleanup: 2205 CloseHandle( handle ); 2206 DeleteFileA( filename ); 2207 } 2208 2209 static BOOL create_fake_dll( LPCSTR filename ) 2210 { 2211 IMAGE_DOS_HEADER *dos; 2212 IMAGE_NT_HEADERS *nt; 2213 IMAGE_SECTION_HEADER *sec; 2214 BYTE *buffer; 2215 DWORD lfanew = sizeof(*dos); 2216 DWORD size = lfanew + sizeof(*nt) + sizeof(*sec); 2217 DWORD written; 2218 BOOL ret; 2219 2220 HANDLE file = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); 2221 if (file == INVALID_HANDLE_VALUE) return FALSE; 2222 2223 buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ); 2224 2225 dos = (IMAGE_DOS_HEADER *)buffer; 2226 dos->e_magic = IMAGE_DOS_SIGNATURE; 2227 dos->e_cblp = sizeof(*dos); 2228 dos->e_cp = 1; 2229 dos->e_cparhdr = lfanew / 16; 2230 dos->e_minalloc = 0; 2231 dos->e_maxalloc = 0xffff; 2232 dos->e_ss = 0x0000; 2233 dos->e_sp = 0x00b8; 2234 dos->e_lfarlc = lfanew; 2235 dos->e_lfanew = lfanew; 2236 2237 nt = (IMAGE_NT_HEADERS *)(buffer + lfanew); 2238 nt->Signature = IMAGE_NT_SIGNATURE; 2239 #if defined __i386__ 2240 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386; 2241 #elif defined __x86_64__ 2242 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; 2243 #elif defined __powerpc__ 2244 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC; 2245 #elif defined __arm__ 2246 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; 2247 #elif defined __aarch64__ 2248 nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64; 2249 #else 2250 # error You must specify the machine type 2251 #endif 2252 nt->FileHeader.NumberOfSections = 1; 2253 nt->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 2254 nt->FileHeader.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE; 2255 nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; 2256 nt->OptionalHeader.MajorLinkerVersion = 1; 2257 nt->OptionalHeader.MinorLinkerVersion = 0; 2258 nt->OptionalHeader.ImageBase = 0x10000000; 2259 nt->OptionalHeader.SectionAlignment = 0x1000; 2260 nt->OptionalHeader.FileAlignment = 0x1000; 2261 nt->OptionalHeader.MajorOperatingSystemVersion = 1; 2262 nt->OptionalHeader.MinorOperatingSystemVersion = 0; 2263 nt->OptionalHeader.MajorImageVersion = 1; 2264 nt->OptionalHeader.MinorImageVersion = 0; 2265 nt->OptionalHeader.MajorSubsystemVersion = 4; 2266 nt->OptionalHeader.MinorSubsystemVersion = 0; 2267 nt->OptionalHeader.SizeOfImage = 0x2000; 2268 nt->OptionalHeader.SizeOfHeaders = size; 2269 nt->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; 2270 nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 2271 2272 sec = (IMAGE_SECTION_HEADER *)(nt + 1); 2273 memcpy( sec->Name, ".rodata", sizeof(".rodata") ); 2274 sec->Misc.VirtualSize = 0x1000; 2275 sec->VirtualAddress = 0x1000; 2276 sec->SizeOfRawData = 0; 2277 sec->PointerToRawData = 0; 2278 sec->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; 2279 2280 ret = WriteFile( file, buffer, size, &written, NULL ) && written == size; 2281 HeapFree( GetProcessHeap(), 0, buffer ); 2282 CloseHandle( file ); 2283 return ret; 2284 } 2285 2286 static unsigned int map_file_access( unsigned int access ) 2287 { 2288 if (access & GENERIC_READ) access |= FILE_GENERIC_READ; 2289 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE; 2290 if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE; 2291 if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS; 2292 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); 2293 } 2294 2295 static BOOL is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 ) 2296 { 2297 access1 = map_file_access( access1 ); 2298 access2 = map_file_access( access2 ); 2299 access1 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE; 2300 access2 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE; 2301 2302 if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; 2303 if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; 2304 2305 if ((access1 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing2 & FILE_SHARE_READ)) return FALSE; 2306 if ((access1 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing2 & FILE_SHARE_WRITE)) return FALSE; 2307 if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return FALSE; 2308 if ((access2 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing1 & FILE_SHARE_READ)) return FALSE; 2309 if ((access2 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing1 & FILE_SHARE_WRITE)) return FALSE; 2310 if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return FALSE; 2311 return TRUE; 2312 } 2313 2314 static BOOL is_sharing_map_compatible( DWORD map_access, DWORD access2, DWORD sharing2 ) 2315 { 2316 if ((map_access == PAGE_READWRITE || map_access == PAGE_EXECUTE_READWRITE) && 2317 !(sharing2 & FILE_SHARE_WRITE)) return FALSE; 2318 access2 = map_file_access( access2 ); 2319 if ((map_access & SEC_IMAGE) && (access2 & FILE_WRITE_DATA)) return FALSE; 2320 return TRUE; 2321 } 2322 2323 static void test_file_sharing(void) 2324 { 2325 struct mode { DWORD dw; const char* str; }; 2326 #define M(x) {x, # x} 2327 static const struct mode access_modes[] = 2328 { M(0), M(GENERIC_READ), M(GENERIC_WRITE), M(GENERIC_READ|GENERIC_WRITE), 2329 M(DELETE), M(GENERIC_READ|DELETE), M(GENERIC_WRITE|DELETE), M(GENERIC_READ|GENERIC_WRITE|DELETE), 2330 M(GENERIC_EXECUTE), M(GENERIC_EXECUTE | DELETE), 2331 M(FILE_READ_DATA), M(FILE_WRITE_DATA), M(FILE_APPEND_DATA), M(FILE_READ_EA), M(FILE_WRITE_EA), 2332 M(FILE_READ_DATA | FILE_EXECUTE), M(FILE_WRITE_DATA | FILE_EXECUTE), M(FILE_APPEND_DATA | FILE_EXECUTE), 2333 M(FILE_READ_EA | FILE_EXECUTE), M(FILE_WRITE_EA | FILE_EXECUTE), M(FILE_EXECUTE), 2334 M(FILE_DELETE_CHILD), M(FILE_READ_ATTRIBUTES), M(FILE_WRITE_ATTRIBUTES) }; 2335 static const struct mode sharing_modes[] = 2336 { M(0), M(FILE_SHARE_READ), 2337 M(FILE_SHARE_WRITE), M(FILE_SHARE_READ|FILE_SHARE_WRITE), 2338 M(FILE_SHARE_DELETE), M(FILE_SHARE_READ|FILE_SHARE_DELETE), 2339 M(FILE_SHARE_WRITE|FILE_SHARE_DELETE), M(FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE) }; 2340 static const struct mode mapping_modes[] = 2341 { M(PAGE_READONLY), M(PAGE_WRITECOPY), M(PAGE_READWRITE), M(SEC_IMAGE | PAGE_WRITECOPY) }; 2342 #undef M 2343 int a1, s1, a2, s2; 2344 int ret; 2345 HANDLE h, h2; 2346 2347 /* make sure the file exists */ 2348 if (!create_fake_dll( filename )) 2349 { 2350 ok(0, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError()); 2351 return; 2352 } 2353 2354 for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++) 2355 { 2356 for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++) 2357 { 2358 SetLastError(0xdeadbeef); 2359 h = CreateFileA( filename, access_modes[a1].dw, sharing_modes[s1].dw, 2360 NULL, OPEN_EXISTING, 0, 0 ); 2361 if (h == INVALID_HANDLE_VALUE) 2362 { 2363 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 2364 return; 2365 } 2366 for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++) 2367 { 2368 for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++) 2369 { 2370 SetLastError(0xdeadbeef); 2371 h2 = CreateFileA( filename, access_modes[a2].dw, sharing_modes[s2].dw, 2372 NULL, OPEN_EXISTING, 0, 0 ); 2373 ret = GetLastError(); 2374 if (is_sharing_compatible( access_modes[a1].dw, sharing_modes[s1].dw, 2375 access_modes[a2].dw, sharing_modes[s2].dw )) 2376 { 2377 ok( h2 != INVALID_HANDLE_VALUE, 2378 "open failed for modes %s / %s / %s / %s\n", 2379 access_modes[a1].str, sharing_modes[s1].str, 2380 access_modes[a2].str, sharing_modes[s2].str ); 2381 ok( ret == 0, "wrong error code %d\n", ret ); 2382 } 2383 else 2384 { 2385 ok( h2 == INVALID_HANDLE_VALUE, 2386 "open succeeded for modes %s / %s / %s / %s\n", 2387 access_modes[a1].str, sharing_modes[s1].str, 2388 access_modes[a2].str, sharing_modes[s2].str ); 2389 ok( ret == ERROR_SHARING_VIOLATION, 2390 "wrong error code %d\n", ret ); 2391 } 2392 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 ); 2393 } 2394 } 2395 CloseHandle( h ); 2396 } 2397 } 2398 2399 for (a1 = 0; a1 < sizeof(mapping_modes)/sizeof(mapping_modes[0]); a1++) 2400 { 2401 HANDLE m; 2402 2403 create_fake_dll( filename ); 2404 SetLastError(0xdeadbeef); 2405 h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); 2406 if (h == INVALID_HANDLE_VALUE) 2407 { 2408 ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError()); 2409 return; 2410 } 2411 m = CreateFileMappingA( h, NULL, mapping_modes[a1].dw, 0, 0, NULL ); 2412 ok( m != 0, "failed to create mapping %s err %u\n", mapping_modes[a1].str, GetLastError() ); 2413 CloseHandle( h ); 2414 if (!m) continue; 2415 2416 for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++) 2417 { 2418 for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++) 2419 { 2420 SetLastError(0xdeadbeef); 2421 h2 = CreateFileA( filename, access_modes[a2].dw, sharing_modes[s2].dw, 2422 NULL, OPEN_EXISTING, 0, 0 ); 2423 2424 ret = GetLastError(); 2425 if (h2 == INVALID_HANDLE_VALUE) 2426 { 2427 ok( !is_sharing_map_compatible(mapping_modes[a1].dw, access_modes[a2].dw, sharing_modes[s2].dw), 2428 "open failed for modes map %s / %s / %s\n", 2429 mapping_modes[a1].str, access_modes[a2].str, sharing_modes[s2].str ); 2430 ok( ret == ERROR_SHARING_VIOLATION, 2431 "wrong error code %d\n", ret ); 2432 } 2433 else 2434 { 2435 if (!is_sharing_map_compatible(mapping_modes[a1].dw, access_modes[a2].dw, sharing_modes[s2].dw)) 2436 ok( broken(1), /* no checking on nt4 */ 2437 "open succeeded for modes map %s / %s / %s\n", 2438 mapping_modes[a1].str, access_modes[a2].str, sharing_modes[s2].str ); 2439 ok( ret == 0xdeadbeef /* Win9x */ || 2440 ret == 0, /* XP */ 2441 "wrong error code %d\n", ret ); 2442 CloseHandle( h2 ); 2443 } 2444 } 2445 } 2446 2447 /* try CREATE_ALWAYS over an existing mapping */ 2448 SetLastError(0xdeadbeef); 2449 h2 = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 2450 NULL, CREATE_ALWAYS, 0, 0 ); 2451 ret = GetLastError(); 2452 if (mapping_modes[a1].dw & SEC_IMAGE) 2453 { 2454 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str ); 2455 ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %s\n", ret, mapping_modes[a1].str ); 2456 } 2457 else 2458 { 2459 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str ); 2460 ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %s\n", ret, mapping_modes[a1].str ); 2461 } 2462 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 ); 2463 2464 /* try DELETE_ON_CLOSE over an existing mapping */ 2465 SetLastError(0xdeadbeef); 2466 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 2467 NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 ); 2468 ret = GetLastError(); 2469 if (mapping_modes[a1].dw & SEC_IMAGE) 2470 { 2471 ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str ); 2472 ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %s\n", ret, mapping_modes[a1].str ); 2473 } 2474 else 2475 { 2476 ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %s err %u\n", mapping_modes[a1].str, ret ); 2477 } 2478 if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 ); 2479 2480 CloseHandle( m ); 2481 } 2482 2483 SetLastError(0xdeadbeef); 2484 h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0 ); 2485 ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() ); 2486 2487 SetLastError(0xdeadbeef); 2488 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); 2489 ok( h2 == INVALID_HANDLE_VALUE, "CreateFileA should fail\n"); 2490 ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error code %d\n", GetLastError() ); 2491 2492 h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); 2493 ok( h2 != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() ); 2494 2495 CloseHandle(h); 2496 CloseHandle(h2); 2497 2498 DeleteFileA( filename ); 2499 } 2500 2501 static char get_windows_drive(void) 2502 { 2503 char windowsdir[MAX_PATH]; 2504 GetWindowsDirectoryA(windowsdir, sizeof(windowsdir)); 2505 return windowsdir[0]; 2506 } 2507 2508 static const struct 2509 { 2510 const char *path; 2511 BOOL expected; 2512 } 2513 invalid_char_tests[] = 2514 { 2515 { "./test-dir", TRUE }, 2516 { "./test-dir/", FALSE }, 2517 { ".\\test-dir", TRUE }, 2518 { ".\\test-dir\\", FALSE }, 2519 { "/>test-dir", FALSE }, 2520 { "<\"test->dir", FALSE }, 2521 { "<test->dir", FALSE }, 2522 { "><test->dir", FALSE }, 2523 { ">>test-dir", FALSE }, 2524 { ">test->dir", FALSE }, 2525 { ">test-dir", FALSE }, 2526 { "\"test-dir\"", FALSE }, 2527 { "\"test-file\"", FALSE }, 2528 { "test-/>dir", FALSE }, 2529 { "test-dir/", FALSE }, 2530 { "test-dir//", FALSE }, 2531 { "test-dir/:", FALSE }, 2532 { "test-dir/<", TRUE }, 2533 { "test-dir/>", TRUE }, 2534 { "test-dir/\"", TRUE }, 2535 { "test-dir/\\", FALSE }, 2536 { "test-dir/|", FALSE }, 2537 { "test-dir<", TRUE }, 2538 { "test-dir</", FALSE }, 2539 { "test-dir<<", TRUE }, 2540 { "test-dir<<<><><>\"\"\"\"<<<>", TRUE }, 2541 { "test-dir<>", TRUE }, 2542 { "test-dir<\"", TRUE }, 2543 { "test-dir>", TRUE }, 2544 { "test-dir>/", FALSE }, 2545 { "test-dir><", TRUE }, 2546 { "test-dir>>", TRUE }, 2547 { "test-dir>\"", TRUE }, 2548 { "test-dir\"", TRUE }, 2549 { "test-dir\"/", FALSE }, 2550 { "test-dir\"<", TRUE }, 2551 { "test-dir\">", TRUE }, 2552 { "test-dir\"\"", TRUE }, 2553 { "test-dir\"\"\"\"\"", TRUE }, 2554 { "test-dir\\", FALSE }, 2555 { "test-dir\\/", FALSE }, 2556 { "test-dir\\<", TRUE }, 2557 { "test-dir\\>", TRUE }, 2558 { "test-dir\\\"", TRUE }, 2559 { "test-dir\\\\", FALSE }, 2560 { "test-file/", FALSE }, 2561 { "test-file/<", FALSE }, 2562 { "test-file/>", FALSE }, 2563 { "test-file/\"", FALSE }, 2564 { "test-file<", TRUE }, 2565 { "test-file<<", TRUE }, 2566 { "test-file<>", TRUE }, 2567 { "test-file<\"", TRUE }, 2568 { "test-file>", TRUE }, 2569 { "test-file><", TRUE }, 2570 { "test-file>>", TRUE }, 2571 { "test-file>\"", TRUE }, 2572 { "test-file\"", TRUE }, 2573 { "test-file\"<", TRUE }, 2574 { "test-file\">", TRUE }, 2575 { "test-file\"\"", TRUE }, 2576 { "test-file\\", FALSE }, 2577 { "test-file\\<", FALSE }, 2578 { "test-file\\>", FALSE }, 2579 { "test-file\\\"", FALSE }, 2580 }; 2581 2582 static void test_FindFirstFileA(void) 2583 { 2584 HANDLE handle; 2585 WIN32_FIND_DATAA data; 2586 int err, i; 2587 char buffer[5] = "C:\\"; 2588 char buffer2[100]; 2589 char nonexistent[MAX_PATH]; 2590 2591 /* try FindFirstFileA on "C:\" */ 2592 buffer[0] = get_windows_drive(); 2593 2594 SetLastError( 0xdeadbeaf ); 2595 handle = FindFirstFileA(buffer, &data); 2596 err = GetLastError(); 2597 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on root directory should fail\n" ); 2598 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err ); 2599 2600 /* try FindFirstFileA on "C:\*" */ 2601 strcpy(buffer2, buffer); 2602 strcat(buffer2, "*"); 2603 handle = FindFirstFileA(buffer2, &data); 2604 ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 ); 2605 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ), 2606 "FindFirstFile shouldn't return '%s' in drive root\n", data.cFileName ); 2607 if (FindNextFileA( handle, &data )) 2608 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ), 2609 "FindNextFile shouldn't return '%s' in drive root\n", data.cFileName ); 2610 ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 ); 2611 2612 /* try FindFirstFileA on windows dir */ 2613 GetWindowsDirectoryA( buffer2, sizeof(buffer2) ); 2614 strcat(buffer2, "\\*"); 2615 handle = FindFirstFileA(buffer2, &data); 2616 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 ); 2617 ok( !strcmp( data.cFileName, "." ), "FindFirstFile should return '.' first\n" ); 2618 ok( FindNextFileA( handle, &data ), "FindNextFile failed\n" ); 2619 ok( !strcmp( data.cFileName, ".." ), "FindNextFile should return '..' as second entry\n" ); 2620 while (FindNextFileA( handle, &data )) 2621 ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ), 2622 "FindNextFile shouldn't return '%s'\n", data.cFileName ); 2623 ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 ); 2624 2625 /* try FindFirstFileA on "C:\foo\" */ 2626 SetLastError( 0xdeadbeaf ); 2627 if (!GetTempFileNameA( buffer, "foo", 0, nonexistent ) && GetLastError() == ERROR_ACCESS_DENIED) 2628 { 2629 char tmp[MAX_PATH]; 2630 GetTempPathA( sizeof(tmp), tmp ); 2631 GetTempFileNameA( tmp, "foo", 0, nonexistent ); 2632 } 2633 DeleteFileA( nonexistent ); 2634 strcpy(buffer2, nonexistent); 2635 strcat(buffer2, "\\"); 2636 handle = FindFirstFileA(buffer2, &data); 2637 err = GetLastError(); 2638 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2639 todo_wine { 2640 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err ); 2641 } 2642 2643 /* try FindFirstFileA without trailing backslash */ 2644 SetLastError( 0xdeadbeaf ); 2645 strcpy(buffer2, nonexistent); 2646 handle = FindFirstFileA(buffer2, &data); 2647 err = GetLastError(); 2648 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2649 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err ); 2650 2651 /* try FindFirstFileA on "C:\foo\bar.txt" */ 2652 SetLastError( 0xdeadbeaf ); 2653 strcpy(buffer2, nonexistent); 2654 strcat(buffer2, "\\bar.txt"); 2655 handle = FindFirstFileA(buffer2, &data); 2656 err = GetLastError(); 2657 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2658 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err ); 2659 2660 /* try FindFirstFileA on "C:\foo\*.*" */ 2661 SetLastError( 0xdeadbeaf ); 2662 strcpy(buffer2, nonexistent); 2663 strcat(buffer2, "\\*.*"); 2664 handle = FindFirstFileA(buffer2, &data); 2665 err = GetLastError(); 2666 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2667 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err ); 2668 2669 /* try FindFirstFileA on "foo\bar.txt" */ 2670 SetLastError( 0xdeadbeaf ); 2671 strcpy(buffer2, nonexistent + 3); 2672 strcat(buffer2, "\\bar.txt"); 2673 handle = FindFirstFileA(buffer2, &data); 2674 err = GetLastError(); 2675 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2676 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err ); 2677 2678 /* try FindFirstFileA on "c:\nul" */ 2679 SetLastError( 0xdeadbeaf ); 2680 strcpy(buffer2, buffer); 2681 strcat(buffer2, "nul"); 2682 handle = FindFirstFileA(buffer2, &data); 2683 err = GetLastError(); 2684 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err ); 2685 ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName ); 2686 ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes || 2687 FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */, 2688 "wrong attributes %x\n", data.dwFileAttributes ); 2689 if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) 2690 { 2691 ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh ); 2692 ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow ); 2693 } 2694 SetLastError( 0xdeadbeaf ); 2695 ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" ); 2696 ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() ); 2697 ok( FindClose( handle ), "failed to close handle\n" ); 2698 2699 /* try FindFirstFileA on "lpt1" */ 2700 SetLastError( 0xdeadbeaf ); 2701 strcpy(buffer2, "lpt1"); 2702 handle = FindFirstFileA(buffer2, &data); 2703 err = GetLastError(); 2704 ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err ); 2705 ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName ); 2706 ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes || 2707 FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */, 2708 "wrong attributes %x\n", data.dwFileAttributes ); 2709 if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) 2710 { 2711 ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh ); 2712 ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow ); 2713 } 2714 SetLastError( 0xdeadbeaf ); 2715 ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" ); 2716 ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() ); 2717 ok( FindClose( handle ), "failed to close handle\n" ); 2718 2719 /* try FindFirstFileA on "c:\nul\*" */ 2720 SetLastError( 0xdeadbeaf ); 2721 strcpy(buffer2, buffer); 2722 strcat(buffer2, "nul\\*"); 2723 handle = FindFirstFileA(buffer2, &data); 2724 err = GetLastError(); 2725 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2726 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err ); 2727 2728 /* try FindFirstFileA on "c:\nul*" */ 2729 SetLastError( 0xdeadbeaf ); 2730 strcpy(buffer2, buffer); 2731 strcat(buffer2, "nul*"); 2732 handle = FindFirstFileA(buffer2, &data); 2733 err = GetLastError(); 2734 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2735 ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err ); 2736 2737 /* try FindFirstFileA on "c:\foo\bar\nul" */ 2738 SetLastError( 0xdeadbeaf ); 2739 strcpy(buffer2, buffer); 2740 strcat(buffer2, "foo\\bar\\nul"); 2741 handle = FindFirstFileA(buffer2, &data); 2742 err = GetLastError(); 2743 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2744 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err ); 2745 2746 /* try FindFirstFileA on "c:\foo\nul\bar" */ 2747 SetLastError( 0xdeadbeaf ); 2748 strcpy(buffer2, buffer); 2749 strcat(buffer2, "foo\\nul\\bar"); 2750 handle = FindFirstFileA(buffer2, &data); 2751 err = GetLastError(); 2752 ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 ); 2753 ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err ); 2754 2755 /* try FindFirstFileA with invalid characters */ 2756 CreateDirectoryA("test-dir", NULL); 2757 _lclose(_lcreat("test-file", 0)); 2758 2759 for (i = 0; i < sizeof(invalid_char_tests) / sizeof(invalid_char_tests[0]); i++) 2760 { 2761 handle = FindFirstFileA(invalid_char_tests[i].path, &data); 2762 if (invalid_char_tests[i].expected) 2763 { 2764 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileA on %s should succeed\n", 2765 invalid_char_tests[i].path); 2766 } 2767 else 2768 { 2769 ok(handle == INVALID_HANDLE_VALUE, "FindFirstFileA on %s should fail\n", 2770 invalid_char_tests[i].path); 2771 } 2772 if (handle != INVALID_HANDLE_VALUE) 2773 FindClose(handle); 2774 } 2775 2776 DeleteFileA("test-file"); 2777 RemoveDirectoryA("test-dir"); 2778 } 2779 2780 static void test_FindNextFileA(void) 2781 { 2782 HANDLE handle; 2783 WIN32_FIND_DATAA search_results; 2784 int err; 2785 char buffer[5] = "C:\\*"; 2786 2787 buffer[0] = get_windows_drive(); 2788 handle = FindFirstFileA(buffer,&search_results); 2789 ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed\n" ); 2790 while (FindNextFileA(handle, &search_results)) 2791 { 2792 /* get to the end of the files */ 2793 } 2794 ok ( FindClose(handle) == TRUE, "Failed to close handle\n"); 2795 err = GetLastError(); 2796 ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES\n"); 2797 } 2798 2799 static void test_FindFirstFileExA(FINDEX_INFO_LEVELS level, FINDEX_SEARCH_OPS search_ops, DWORD flags) 2800 { 2801 WIN32_FIND_DATAA search_results; 2802 HANDLE handle; 2803 BOOL ret; 2804 2805 if (!pFindFirstFileExA) 2806 { 2807 win_skip("FindFirstFileExA() is missing\n"); 2808 return; 2809 } 2810 2811 trace("Running FindFirstFileExA tests with level=%d, search_ops=%d, flags=%u\n", 2812 level, search_ops, flags); 2813 2814 CreateDirectoryA("test-dir", NULL); 2815 _lclose(_lcreat("test-dir\\file1", 0)); 2816 _lclose(_lcreat("test-dir\\file2", 0)); 2817 CreateDirectoryA("test-dir\\dir1", NULL); 2818 SetLastError(0xdeadbeef); 2819 handle = pFindFirstFileExA("test-dir\\*", level, &search_results, search_ops, NULL, flags); 2820 if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 2821 { 2822 win_skip("FindFirstFileExA is not implemented\n"); 2823 goto cleanup; 2824 } 2825 if ((flags & FIND_FIRST_EX_LARGE_FETCH) && handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER) 2826 { 2827 win_skip("FindFirstFileExA flag FIND_FIRST_EX_LARGE_FETCH not supported, skipping test\n"); 2828 goto cleanup; 2829 } 2830 if ((level == FindExInfoBasic) && handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER) 2831 { 2832 win_skip("FindFirstFileExA level FindExInfoBasic not supported, skipping test\n"); 2833 goto cleanup; 2834 } 2835 2836 #define CHECK_NAME(fn) (strcmp((fn), "file1") == 0 || strcmp((fn), "file2") == 0 || strcmp((fn), "dir1") == 0) 2837 #define CHECK_LEVEL(fn) (level != FindExInfoBasic || !(fn)[0]) 2838 2839 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError()); 2840 ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName); 2841 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n"); 2842 2843 ok(FindNextFileA(handle, &search_results), "Fetching second file failed\n"); 2844 ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName); 2845 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n"); 2846 2847 ok(FindNextFileA(handle, &search_results), "Fetching third file failed\n"); 2848 ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName); 2849 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n"); 2850 2851 SetLastError(0xdeadbeef); 2852 ret = FindNextFileA(handle, &search_results); 2853 if (!ret && (GetLastError() == ERROR_NO_MORE_FILES) && (search_ops == FindExSearchLimitToDirectories)) 2854 { 2855 skip("File system supports directory filtering\n"); 2856 /* Results from the previous call are not cleared */ 2857 ok(strcmp(search_results.cFileName, "dir1") == 0, "Third entry should be 'dir1' is %s\n", search_results.cFileName); 2858 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n"); 2859 2860 } 2861 else 2862 { 2863 ok(ret, "Fetching fourth file failed\n"); 2864 ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName); 2865 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n"); 2866 2867 ok(FindNextFileA(handle, &search_results), "Fetching fifth file failed\n"); 2868 ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName); 2869 ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n"); 2870 2871 ok(FindNextFileA(handle, &search_results) == FALSE, "Fetching sixth file should fail\n"); 2872 } 2873 2874 #undef CHECK_NAME 2875 #undef CHECK_LEVEL 2876 2877 FindClose( handle ); 2878 2879 /* Most Windows systems seem to ignore the FIND_FIRST_EX_CASE_SENSITIVE flag. Unofficial documentation 2880 * suggests that there are registry keys and that it might depend on the used filesystem. */ 2881 SetLastError(0xdeadbeef); 2882 handle = pFindFirstFileExA("TEST-DIR\\*", level, &search_results, search_ops, NULL, flags); 2883 if (flags & FIND_FIRST_EX_CASE_SENSITIVE) 2884 { 2885 ok(handle != INVALID_HANDLE_VALUE || GetLastError() == ERROR_PATH_NOT_FOUND, 2886 "Unexpected error %x, expected valid handle or ERROR_PATH_NOT_FOUND\n", GetLastError()); 2887 trace("FindFirstFileExA flag FIND_FIRST_EX_CASE_SENSITIVE is %signored\n", 2888 (handle == INVALID_HANDLE_VALUE) ? "not " : ""); 2889 } 2890 else 2891 ok(handle != INVALID_HANDLE_VALUE, "Unexpected error %x, expected valid handle\n", GetLastError()); 2892 if (handle != INVALID_HANDLE_VALUE) 2893 FindClose( handle ); 2894 2895 cleanup: 2896 DeleteFileA("test-dir\\file1"); 2897 DeleteFileA("test-dir\\file2"); 2898 RemoveDirectoryA("test-dir\\dir1"); 2899 RemoveDirectoryA("test-dir"); 2900 } 2901 2902 static void test_FindFirstFile_wildcards(void) 2903 { 2904 WIN32_FIND_DATAA find_data; 2905 HANDLE handle; 2906 int i; 2907 static const char* files[] = { 2908 "..a", "..a.a", ".a", ".a..a", ".a.a", ".aaa", 2909 "a", "a..a", "a.a", "a.a.a", "aa", "aaa", "aaaa" 2910 }; 2911 static const struct { 2912 int todo; 2913 const char *pattern, *result; 2914 } tests[] = { 2915 {0, "*.*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2916 {0, "*.*.", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2917 {0, ".*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa'"}, 2918 {0, "*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2919 {0, ".*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa'"}, 2920 {1, "*.", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"}, 2921 {0, "*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2922 {1, "*..*", ", '.', '..', '..a', '..a.a', '.a..a', 'a..a'"}, 2923 {1, "*..", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"}, 2924 {1, ".*.", ", '.', '..', '.a', '.aaa'"}, 2925 {0, "..*", ", '.', '..', '..a', '..a.a'"}, 2926 {0, "**", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2927 {0, "**.", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2928 {0, "*. ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2929 {1, "* .", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"}, 2930 {0, "* . ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2931 {0, "*.. ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"}, 2932 {1, "*. .", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"}, 2933 {1, "* ..", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"}, 2934 {1, " *..", ", '.aaa'"}, 2935 {0, "..* ", ", '.', '..', '..a', '..a.a'"}, 2936 {1, "?", ", '.', '..', 'a'"}, 2937 {1, "?.", ", '.', '..', 'a'"}, 2938 {1, "?. ", ", '.', '..', 'a'"}, 2939 {1, "??.", ", '.', '..', 'a', 'aa'"}, 2940 {1, "??. ", ", '.', '..', 'a', 'aa'"}, 2941 {1, "???.", ", '.', '..', 'a', 'aa', 'aaa'"}, 2942 {1, "?.??.", ", '.', '..', '.a', 'a', 'a.a'"} 2943 }; 2944 2945 CreateDirectoryA("test-dir", NULL); 2946 SetCurrentDirectoryA("test-dir"); 2947 for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) 2948 _lclose(_lcreat(files[i], 0)); 2949 2950 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) 2951 { 2952 char correct[512]; 2953 char incorrect[512]; 2954 char missing[512]; 2955 2956 strcpy(missing, tests[i].result); 2957 correct[0] = incorrect[0] = 0; 2958 2959 handle = FindFirstFileA(tests[i].pattern, &find_data); 2960 if (handle) do { 2961 char* ptr; 2962 char quoted[16]; 2963 2964 sprintf( quoted, ", '%.10s'", find_data.cFileName ); 2965 2966 if ((ptr = strstr(missing, quoted))) 2967 { 2968 int len = strlen(quoted); 2969 while ((ptr[0] = ptr[len]) != 0) 2970 ++ptr; 2971 strcat(correct, quoted); 2972 } 2973 else 2974 strcat(incorrect, quoted); 2975 } while (FindNextFileA(handle, &find_data)); 2976 FindClose(handle); 2977 2978 todo_wine_if (tests[i].todo) 2979 ok(missing[0] == 0 && incorrect[0] == 0, 2980 "FindFirstFile with '%s' found correctly %s, found incorrectly %s, and missed %s\n", 2981 tests[i].pattern, 2982 correct[0] ? correct+2 : "none", 2983 incorrect[0] ? incorrect+2 : "none", 2984 missing[0] ? missing+2 : "none"); 2985 } 2986 2987 for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) 2988 DeleteFileA(files[i]); 2989 SetCurrentDirectoryA(".."); 2990 RemoveDirectoryA("test-dir"); 2991 } 2992 2993 static int test_Mapfile_createtemp(HANDLE *handle) 2994 { 2995 SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL); 2996 DeleteFileA(filename); 2997 *handle = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, 0, 2998 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 2999 if (*handle != INVALID_HANDLE_VALUE) { 3000 3001 return 1; 3002 } 3003 3004 return 0; 3005 } 3006 3007 static void test_MapFile(void) 3008 { 3009 HANDLE handle; 3010 HANDLE hmap; 3011 3012 ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n"); 3013 3014 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" ); 3015 ok( hmap != NULL, "mapping should work, I named it!\n" ); 3016 3017 ok( CloseHandle( hmap ), "can't close mapping handle\n"); 3018 3019 /* We have to close file before we try new stuff with mapping again. 3020 Else we would always succeed on XP or block descriptors on 95. */ 3021 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL ); 3022 ok( hmap != NULL, "We should still be able to map!\n" ); 3023 ok( CloseHandle( hmap ), "can't close mapping handle\n"); 3024 ok( CloseHandle( handle ), "can't close file handle\n"); 3025 handle = NULL; 3026 3027 ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n"); 3028 3029 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL ); 3030 ok( hmap == NULL, "mapped zero size file\n"); 3031 ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n"); 3032 3033 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL ); 3034 ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n"); 3035 /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */ 3036 if ( hmap ) 3037 CloseHandle( hmap ); 3038 3039 hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL ); 3040 ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n"); 3041 /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */ 3042 if ( hmap ) 3043 CloseHandle( hmap ); 3044 3045 /* On XP you can now map again, on Win 95 you cannot. */ 3046 3047 ok( CloseHandle( handle ), "can't close file handle\n"); 3048 ok( DeleteFileA( filename ), "DeleteFile failed after map\n" ); 3049 } 3050 3051 static void test_GetFileType(void) 3052 { 3053 DWORD type, type2; 3054 HANDLE h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); 3055 ok( h != INVALID_HANDLE_VALUE, "open %s failed\n", filename ); 3056 type = GetFileType(h); 3057 ok( type == FILE_TYPE_DISK, "expected type disk got %d\n", type ); 3058 CloseHandle( h ); 3059 h = CreateFileA( "nul", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); 3060 ok( h != INVALID_HANDLE_VALUE, "open nul failed\n" ); 3061 type = GetFileType(h); 3062 ok( type == FILE_TYPE_CHAR, "expected type char for nul got %d\n", type ); 3063 CloseHandle( h ); 3064 DeleteFileA( filename ); 3065 h = GetStdHandle( STD_OUTPUT_HANDLE ); 3066 ok( h != INVALID_HANDLE_VALUE, "GetStdHandle failed\n" ); 3067 type = GetFileType( (HANDLE)STD_OUTPUT_HANDLE ); 3068 type2 = GetFileType( h ); 3069 ok(type == type2, "expected type %d for STD_OUTPUT_HANDLE got %d\n", type2, type); 3070 } 3071 3072 static int completion_count; 3073 3074 static void CALLBACK FileIOComplete(DWORD dwError, DWORD dwBytes, LPOVERLAPPED ovl) 3075 { 3076 /* printf("(%ld, %ld, %p { %ld, %ld, %ld, %ld, %p })\n", dwError, dwBytes, ovl, ovl->Internal, ovl->InternalHigh, ovl->Offset, ovl->OffsetHigh, ovl->hEvent);*/ 3077 ReleaseSemaphore(ovl->hEvent, 1, NULL); 3078 completion_count++; 3079 } 3080 3081 static void test_async_file_errors(void) 3082 { 3083 char szFile[MAX_PATH]; 3084 HANDLE hSem = CreateSemaphoreW(NULL, 1, 1, NULL); 3085 HANDLE hFile; 3086 LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096); 3087 OVERLAPPED ovl; 3088 S(U(ovl)).Offset = 0; 3089 S(U(ovl)).OffsetHigh = 0; 3090 ovl.hEvent = hSem; 3091 completion_count = 0; 3092 szFile[0] = '\0'; 3093 GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini")); 3094 strcat(szFile, "\\win.ini"); 3095 hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 3096 NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL); 3097 if (hFile == INVALID_HANDLE_VALUE) /* win9x doesn't like FILE_SHARE_DELETE */ 3098 hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 3099 NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL); 3100 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA(%s ...) failed\n", szFile); 3101 while (TRUE) 3102 { 3103 BOOL res; 3104 DWORD count; 3105 while (WaitForSingleObjectEx(hSem, INFINITE, TRUE) == WAIT_IO_COMPLETION) 3106 ; 3107 res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete); 3108 /*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/ 3109 if (!res) 3110 break; 3111 if (!GetOverlappedResult(hFile, &ovl, &count, FALSE)) 3112 break; 3113 S(U(ovl)).Offset += count; 3114 /* i/o completion routine only called if ReadFileEx returned success. 3115 * we only care about violations of this rule so undo what should have 3116 * been done */ 3117 completion_count--; 3118 } 3119 ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count); 3120 /*printf("Error = %ld\n", GetLastError());*/ 3121 HeapFree(GetProcessHeap(), 0, lpBuffer); 3122 } 3123 3124 static BOOL user_apc_ran; 3125 static void CALLBACK user_apc(ULONG_PTR param) 3126 { 3127 user_apc_ran = TRUE; 3128 } 3129 3130 static void test_read_write(void) 3131 { 3132 DWORD bytes, ret, old_prot; 3133 HANDLE hFile; 3134 char temp_path[MAX_PATH]; 3135 char filename[MAX_PATH]; 3136 char *mem; 3137 static const char prefix[] = "pfx"; 3138 3139 ret = GetTempPathA(MAX_PATH, temp_path); 3140 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 3141 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 3142 3143 ret = GetTempFileNameA(temp_path, prefix, 0, filename); 3144 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 3145 3146 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 3147 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 3148 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 3149 3150 user_apc_ran = FALSE; 3151 if (pQueueUserAPC) { 3152 trace("Queueing an user APC\n"); /* verify the file is non alerable */ 3153 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0); 3154 ok(ret, "QueueUserAPC failed: %d\n", GetLastError()); 3155 } 3156 3157 SetLastError(12345678); 3158 bytes = 12345678; 3159 ret = WriteFile(hFile, NULL, 0, &bytes, NULL); 3160 ok(ret && GetLastError() == 12345678, 3161 "ret = %d, error %d\n", ret, GetLastError()); 3162 ok(!bytes, "bytes = %d\n", bytes); 3163 3164 SetLastError(12345678); 3165 bytes = 12345678; 3166 ret = WriteFile(hFile, NULL, 10, &bytes, NULL); 3167 ok((!ret && GetLastError() == ERROR_INVALID_USER_BUFFER) || /* Win2k */ 3168 (ret && GetLastError() == 12345678), /* Win9x */ 3169 "ret = %d, error %d\n", ret, GetLastError()); 3170 ok(!bytes || /* Win2k */ 3171 bytes == 10, /* Win9x */ 3172 "bytes = %d\n", bytes); 3173 3174 /* make sure the file contains data */ 3175 WriteFile(hFile, "this is the test data", 21, &bytes, NULL); 3176 SetFilePointer(hFile, 0, NULL, FILE_BEGIN); 3177 3178 SetLastError(12345678); 3179 bytes = 12345678; 3180 ret = ReadFile(hFile, NULL, 0, &bytes, NULL); 3181 ok(ret && GetLastError() == 12345678, 3182 "ret = %d, error %d\n", ret, GetLastError()); 3183 ok(!bytes, "bytes = %d\n", bytes); 3184 3185 SetLastError(12345678); 3186 bytes = 12345678; 3187 ret = ReadFile(hFile, NULL, 10, &bytes, NULL); 3188 ok(!ret && (GetLastError() == ERROR_NOACCESS || /* Win2k */ 3189 GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ 3190 "ret = %d, error %d\n", ret, GetLastError()); 3191 ok(!bytes, "bytes = %d\n", bytes); 3192 3193 ok(user_apc_ran == FALSE, "UserAPC ran, file using alertable io mode\n"); 3194 if (pQueueUserAPC) 3195 SleepEx(0, TRUE); /* get rid of apc */ 3196 3197 /* test passing protected memory as buffer */ 3198 3199 mem = VirtualAlloc( NULL, 0x4000, MEM_COMMIT, PAGE_READWRITE ); 3200 ok( mem != NULL, "failed to allocate virtual mem error %u\n", GetLastError() ); 3201 3202 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL ); 3203 ok( ret, "WriteFile failed error %u\n", GetLastError() ); 3204 ok( bytes == 0x4000, "only wrote %x bytes\n", bytes ); 3205 3206 ret = VirtualProtect( mem + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot ); 3207 ok( ret, "VirtualProtect failed error %u\n", GetLastError() ); 3208 3209 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL ); 3210 ok( !ret, "WriteFile succeeded\n" ); 3211 ok( GetLastError() == ERROR_INVALID_USER_BUFFER || 3212 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3213 "wrong error %u\n", GetLastError() ); 3214 ok( bytes == 0, "wrote %x bytes\n", bytes ); 3215 3216 ret = WriteFile( (HANDLE)0xdead, mem, 0x4000, &bytes, NULL ); 3217 ok( !ret, "WriteFile succeeded\n" ); 3218 ok( GetLastError() == ERROR_INVALID_HANDLE || /* handle is checked before buffer on NT */ 3219 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3220 "wrong error %u\n", GetLastError() ); 3221 ok( bytes == 0, "wrote %x bytes\n", bytes ); 3222 3223 ret = VirtualProtect( mem, 0x2000, PAGE_NOACCESS, &old_prot ); 3224 ok( ret, "VirtualProtect failed error %u\n", GetLastError() ); 3225 3226 ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL ); 3227 ok( !ret, "WriteFile succeeded\n" ); 3228 ok( GetLastError() == ERROR_INVALID_USER_BUFFER || 3229 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3230 "wrong error %u\n", GetLastError() ); 3231 ok( bytes == 0, "wrote %x bytes\n", bytes ); 3232 3233 SetFilePointer( hFile, 0, NULL, FILE_BEGIN ); 3234 3235 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL ); 3236 ok( !ret, "ReadFile succeeded\n" ); 3237 ok( GetLastError() == ERROR_NOACCESS || 3238 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3239 "wrong error %u\n", GetLastError() ); 3240 ok( bytes == 0, "read %x bytes\n", bytes ); 3241 3242 ret = VirtualProtect( mem, 0x2000, PAGE_READONLY, &old_prot ); 3243 ok( ret, "VirtualProtect failed error %u\n", GetLastError() ); 3244 3245 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL ); 3246 ok( !ret, "ReadFile succeeded\n" ); 3247 ok( GetLastError() == ERROR_NOACCESS || 3248 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3249 "wrong error %u\n", GetLastError() ); 3250 ok( bytes == 0, "read %x bytes\n", bytes ); 3251 3252 ret = VirtualProtect( mem, 0x2000, PAGE_READWRITE, &old_prot ); 3253 ok( ret, "VirtualProtect failed error %u\n", GetLastError() ); 3254 3255 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL ); 3256 ok( !ret, "ReadFile succeeded\n" ); 3257 ok( GetLastError() == ERROR_NOACCESS || 3258 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3259 "wrong error %u\n", GetLastError() ); 3260 ok( bytes == 0, "read %x bytes\n", bytes ); 3261 3262 SetFilePointer( hFile, 0x1234, NULL, FILE_BEGIN ); 3263 SetEndOfFile( hFile ); 3264 SetFilePointer( hFile, 0, NULL, FILE_BEGIN ); 3265 3266 ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL ); 3267 ok( !ret, "ReadFile succeeded\n" ); 3268 ok( GetLastError() == ERROR_NOACCESS || 3269 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3270 "wrong error %u\n", GetLastError() ); 3271 ok( bytes == 0, "read %x bytes\n", bytes ); 3272 3273 ret = ReadFile( hFile, mem, 0x2000, &bytes, NULL ); 3274 ok( ret, "ReadFile failed error %u\n", GetLastError() ); 3275 ok( bytes == 0x1234, "read %x bytes\n", bytes ); 3276 3277 ret = ReadFile( hFile, NULL, 1, &bytes, NULL ); 3278 ok( !ret, "ReadFile succeeded\n" ); 3279 ok( GetLastError() == ERROR_NOACCESS || 3280 GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ 3281 "wrong error %u\n", GetLastError() ); 3282 ok( bytes == 0, "read %x bytes\n", bytes ); 3283 3284 VirtualFree( mem, 0, MEM_RELEASE ); 3285 3286 ret = CloseHandle(hFile); 3287 ok( ret, "CloseHandle: error %d\n", GetLastError()); 3288 ret = DeleteFileA(filename); 3289 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 3290 } 3291 3292 static void test_OpenFile(void) 3293 { 3294 HFILE hFile; 3295 OFSTRUCT ofs; 3296 BOOL ret; 3297 DWORD retval; 3298 3299 static const char file[] = "regedit.exe"; 3300 static const char foo[] = ".\\foo-bar-foo.baz"; 3301 static const char *foo_too_long = ".\\foo-bar-foo.baz+++++++++++++++" 3302 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" 3303 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" 3304 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" 3305 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" 3306 "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; 3307 char buff[MAX_PATH]; 3308 char buff_long[4*MAX_PATH]; 3309 char filled_0xA5[OFS_MAXPATHNAME]; 3310 char *p; 3311 UINT length; 3312 3313 /* Check for existing file */ 3314 if (!pGetSystemWindowsDirectoryA) 3315 length = GetWindowsDirectoryA(buff, MAX_PATH); 3316 else 3317 length = pGetSystemWindowsDirectoryA(buff, MAX_PATH); 3318 3319 if (length + sizeof(file) < MAX_PATH) 3320 { 3321 p = buff + strlen(buff); 3322 if (p > buff && p[-1] != '\\') *p++ = '\\'; 3323 strcpy( p, file ); 3324 memset(&ofs, 0xA5, sizeof(ofs)); 3325 SetLastError(0xfaceabee); 3326 3327 hFile = OpenFile(buff, &ofs, OF_EXIST); 3328 ok( hFile == TRUE, "%s not found : %d\n", buff, GetLastError() ); 3329 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 3330 "GetLastError() returns %d\n", GetLastError() ); 3331 ok( ofs.cBytes == sizeof(ofs), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3332 ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3333 ok( lstrcmpiA(ofs.szPathName, buff) == 0, 3334 "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n", 3335 ofs.szPathName, buff ); 3336 } 3337 3338 memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME); 3339 length = GetCurrentDirectoryA(MAX_PATH, buff); 3340 3341 /* Check for nonexistent file */ 3342 if (length + sizeof(foo) < MAX_PATH) 3343 { 3344 p = buff + strlen(buff); 3345 if (p > buff && p[-1] != '\\') *p++ = '\\'; 3346 strcpy( p, foo + 2 ); 3347 memset(&ofs, 0xA5, sizeof(ofs)); 3348 SetLastError(0xfaceabee); 3349 3350 hFile = OpenFile(foo, &ofs, OF_EXIST); 3351 ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError()); 3352 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError() returns %d\n", GetLastError() ); 3353 todo_wine 3354 ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3355 ok( ofs.nErrCode == ERROR_FILE_NOT_FOUND, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3356 ok( lstrcmpiA(ofs.szPathName, buff) == 0 || strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, 3357 "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n", 3358 ofs.szPathName, buff ); 3359 } 3360 3361 length = GetCurrentDirectoryA(MAX_PATH, buff_long); 3362 length += lstrlenA(foo_too_long + 1); 3363 3364 /* Check for nonexistent file with too long filename */ 3365 if (length >= OFS_MAXPATHNAME && length < sizeof(buff_long)) 3366 { 3367 lstrcatA(buff_long, foo_too_long + 1); /* Avoid '.' during concatenation */ 3368 memset(&ofs, 0xA5, sizeof(ofs)); 3369 SetLastError(0xfaceabee); 3370 3371 hFile = OpenFile(foo_too_long, &ofs, OF_EXIST); 3372 ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError()); 3373 ok( GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_FILENAME_EXCED_RANGE, 3374 "GetLastError() returns %d\n", GetLastError() ); 3375 todo_wine 3376 ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3377 ok( ofs.nErrCode == ERROR_INVALID_DATA || ofs.nErrCode == ERROR_FILENAME_EXCED_RANGE, 3378 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3379 ok( strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, 3380 "OpenFile returned '%s', but was expected to return string filled with 0xA5\n", 3381 ofs.szPathName ); 3382 } 3383 3384 length = GetCurrentDirectoryA(MAX_PATH, buff) + sizeof(filename); 3385 3386 if (length >= MAX_PATH) 3387 { 3388 trace("Buffer too small, requested length = %d, but MAX_PATH = %d. Skipping test.\n", length, MAX_PATH); 3389 return; 3390 } 3391 p = buff + strlen(buff); 3392 if (p > buff && p[-1] != '\\') *p++ = '\\'; 3393 strcpy( p, filename ); 3394 3395 memset(&ofs, 0xA5, sizeof(ofs)); 3396 SetLastError(0xfaceabee); 3397 /* Create an empty file */ 3398 hFile = OpenFile(filename, &ofs, OF_CREATE); 3399 ok( hFile != HFILE_ERROR, "OpenFile failed to create nonexistent file\n" ); 3400 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 3401 "GetLastError() returns %d\n", GetLastError() ); 3402 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3403 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */, 3404 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3405 ret = _lclose(hFile); 3406 ok( !ret, "_lclose() returns %d\n", ret ); 3407 retval = GetFileAttributesA(filename); 3408 ok( retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %d\n", GetLastError() ); 3409 3410 memset(&ofs, 0xA5, sizeof(ofs)); 3411 SetLastError(0xfaceabee); 3412 /* Check various opening options: */ 3413 /* for reading only, */ 3414 hFile = OpenFile(filename, &ofs, OF_READ); 3415 ok( hFile != HFILE_ERROR, "OpenFile failed on read\n" ); 3416 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 3417 "GetLastError() returns %d\n", GetLastError() ); 3418 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3419 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */, 3420 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3421 ok( lstrcmpiA(ofs.szPathName, buff) == 0, 3422 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff ); 3423 ret = _lclose(hFile); 3424 ok( !ret, "_lclose() returns %d\n", ret ); 3425 3426 memset(&ofs, 0xA5, sizeof(ofs)); 3427 SetLastError(0xfaceabee); 3428 /* for writing only, */ 3429 hFile = OpenFile(filename, &ofs, OF_WRITE); 3430 ok( hFile != HFILE_ERROR, "OpenFile failed on write\n" ); 3431 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 3432 "GetLastError() returns %d\n", GetLastError() ); 3433 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3434 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */, 3435 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3436 ok( lstrcmpiA(ofs.szPathName, buff) == 0, 3437 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff ); 3438 ret = _lclose(hFile); 3439 ok( !ret, "_lclose() returns %d\n", ret ); 3440 3441 memset(&ofs, 0xA5, sizeof(ofs)); 3442 SetLastError(0xfaceabee); 3443 /* for reading and writing, */ 3444 hFile = OpenFile(filename, &ofs, OF_READWRITE); 3445 ok( hFile != HFILE_ERROR, "OpenFile failed on read/write\n" ); 3446 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 3447 "GetLastError() returns %d\n", GetLastError() ); 3448 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3449 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */, 3450 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3451 ok( lstrcmpiA(ofs.szPathName, buff) == 0, 3452 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff ); 3453 ret = _lclose(hFile); 3454 ok( !ret, "_lclose() returns %d\n", ret ); 3455 3456 memset(&ofs, 0xA5, sizeof(ofs)); 3457 SetLastError(0xfaceabee); 3458 /* for checking file presence. */ 3459 hFile = OpenFile(filename, &ofs, OF_EXIST); 3460 ok( hFile == 1, "OpenFile failed on finding our created file\n" ); 3461 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 3462 "GetLastError() returns %d\n", GetLastError() ); 3463 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3464 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */, 3465 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3466 ok( lstrcmpiA(ofs.szPathName, buff) == 0, 3467 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff ); 3468 3469 memset(&ofs, 0xA5, sizeof(ofs)); 3470 SetLastError(0xfaceabee); 3471 /* Delete the file and make sure it doesn't exist anymore */ 3472 hFile = OpenFile(filename, &ofs, OF_DELETE); 3473 ok( hFile == 1, "OpenFile failed on delete (%d)\n", hFile ); 3474 ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS, 3475 "GetLastError() returns %d\n", GetLastError() ); 3476 ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes ); 3477 ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */, 3478 "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode ); 3479 ok( lstrcmpiA(ofs.szPathName, buff) == 0, 3480 "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff ); 3481 3482 retval = GetFileAttributesA(filename); 3483 ok( retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file\n" ); 3484 } 3485 3486 static void test_overlapped(void) 3487 { 3488 OVERLAPPED ov; 3489 DWORD r, result; 3490 3491 /* GetOverlappedResult crashes if the 2nd or 3rd param are NULL */ 3492 if (0) /* tested: WinXP */ 3493 { 3494 GetOverlappedResult(0, NULL, &result, FALSE); 3495 GetOverlappedResult(0, &ov, NULL, FALSE); 3496 GetOverlappedResult(0, NULL, NULL, FALSE); 3497 } 3498 3499 memset( &ov, 0, sizeof ov ); 3500 result = 1; 3501 r = GetOverlappedResult(0, &ov, &result, 0); 3502 if (r) 3503 ok( result == 0, "wrong result %u\n", result ); 3504 else /* win9x */ 3505 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() ); 3506 3507 result = 0; 3508 ov.Internal = 0; 3509 ov.InternalHigh = 0xabcd; 3510 r = GetOverlappedResult(0, &ov, &result, 0); 3511 if (r) 3512 ok( result == 0xabcd, "wrong result %u\n", result ); 3513 else /* win9x */ 3514 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() ); 3515 3516 SetLastError( 0xb00 ); 3517 result = 0; 3518 ov.Internal = STATUS_INVALID_HANDLE; 3519 ov.InternalHigh = 0xabcd; 3520 r = GetOverlappedResult(0, &ov, &result, 0); 3521 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() ); 3522 ok( r == FALSE, "should return false\n"); 3523 ok( result == 0xabcd || result == 0 /* win9x */, "wrong result %u\n", result ); 3524 3525 SetLastError( 0xb00 ); 3526 result = 0; 3527 ov.Internal = STATUS_PENDING; 3528 ov.InternalHigh = 0xabcd; 3529 r = GetOverlappedResult(0, &ov, &result, 0); 3530 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */, 3531 "wrong error %u\n", GetLastError() ); 3532 ok( r == FALSE, "should return false\n"); 3533 ok( result == 0, "wrong result %u\n", result ); 3534 3535 SetLastError( 0xb00 ); 3536 ov.hEvent = CreateEventW( NULL, 1, 1, NULL ); 3537 ov.Internal = STATUS_PENDING; 3538 ov.InternalHigh = 0xabcd; 3539 r = GetOverlappedResult(0, &ov, &result, 0); 3540 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */, 3541 "wrong error %u\n", GetLastError() ); 3542 ok( r == FALSE, "should return false\n"); 3543 3544 r = GetOverlappedResult( 0, &ov, &result, TRUE ); 3545 ok( r == TRUE, "should return TRUE\n" ); 3546 ok( result == 0xabcd, "wrong result %u\n", result ); 3547 ok( ov.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", ov.Internal ); 3548 3549 ResetEvent( ov.hEvent ); 3550 3551 SetLastError( 0xb00 ); 3552 ov.Internal = STATUS_PENDING; 3553 ov.InternalHigh = 0; 3554 r = GetOverlappedResult(0, &ov, &result, 0); 3555 ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */, 3556 "wrong error %u\n", GetLastError() ); 3557 ok( r == FALSE, "should return false\n"); 3558 3559 r = CloseHandle( ov.hEvent ); 3560 ok( r == TRUE, "close handle failed\n"); 3561 } 3562 3563 static void test_RemoveDirectory(void) 3564 { 3565 int rc; 3566 char directory[] = "removeme"; 3567 3568 rc = CreateDirectoryA(directory, NULL); 3569 ok( rc, "Createdirectory failed, gle=%d\n", GetLastError() ); 3570 3571 rc = SetCurrentDirectoryA(directory); 3572 ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() ); 3573 3574 rc = RemoveDirectoryA("."); 3575 if (!rc) 3576 { 3577 rc = SetCurrentDirectoryA(".."); 3578 ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() ); 3579 3580 rc = RemoveDirectoryA(directory); 3581 ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() ); 3582 } 3583 } 3584 3585 static BOOL check_file_time( const FILETIME *ft1, const FILETIME *ft2, UINT tolerance ) 3586 { 3587 ULONGLONG t1 = ((ULONGLONG)ft1->dwHighDateTime << 32) | ft1->dwLowDateTime; 3588 ULONGLONG t2 = ((ULONGLONG)ft2->dwHighDateTime << 32) | ft2->dwLowDateTime; 3589 return abs(t1 - t2) <= tolerance; 3590 } 3591 3592 static void test_ReplaceFileA(void) 3593 { 3594 char replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH]; 3595 HANDLE hReplacedFile, hReplacementFile, hBackupFile; 3596 static const char replacedData[] = "file-to-replace"; 3597 static const char replacementData[] = "new-file"; 3598 static const char backupData[] = "backup-file"; 3599 FILETIME ftReplaced, ftReplacement, ftBackup; 3600 static const char prefix[] = "pfx"; 3601 char temp_path[MAX_PATH]; 3602 DWORD ret; 3603 BOOL retok, removeBackup = FALSE; 3604 3605 if (!pReplaceFileA) 3606 { 3607 win_skip("ReplaceFileA() is missing\n"); 3608 return; 3609 } 3610 3611 ret = GetTempPathA(MAX_PATH, temp_path); 3612 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 3613 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 3614 3615 ret = GetTempFileNameA(temp_path, prefix, 0, replaced); 3616 ok(ret != 0, "GetTempFileNameA error (replaced) %d\n", GetLastError()); 3617 3618 ret = GetTempFileNameA(temp_path, prefix, 0, replacement); 3619 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError()); 3620 3621 ret = GetTempFileNameA(temp_path, prefix, 0, backup); 3622 ok(ret != 0, "GetTempFileNameA error (backup) %d\n", GetLastError()); 3623 3624 /* place predictable data in the file to be replaced */ 3625 hReplacedFile = CreateFileA(replaced, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); 3626 ok(hReplacedFile != INVALID_HANDLE_VALUE, 3627 "failed to open replaced file\n"); 3628 retok = WriteFile(hReplacedFile, replacedData, sizeof(replacedData), &ret, NULL ); 3629 ok( retok && ret == sizeof(replacedData), 3630 "WriteFile error (replaced) %d\n", GetLastError()); 3631 ok(GetFileSize(hReplacedFile, NULL) == sizeof(replacedData), 3632 "replaced file has wrong size\n"); 3633 /* place predictable data in the file to be the replacement */ 3634 hReplacementFile = CreateFileA(replacement, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); 3635 ok(hReplacementFile != INVALID_HANDLE_VALUE, 3636 "failed to open replacement file\n"); 3637 retok = WriteFile(hReplacementFile, replacementData, sizeof(replacementData), &ret, NULL ); 3638 ok( retok && ret == sizeof(replacementData), 3639 "WriteFile error (replacement) %d\n", GetLastError()); 3640 ok(GetFileSize(hReplacementFile, NULL) == sizeof(replacementData), 3641 "replacement file has wrong size\n"); 3642 /* place predictable data in the backup file (to be over-written) */ 3643 hBackupFile = CreateFileA(backup, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); 3644 ok(hBackupFile != INVALID_HANDLE_VALUE, 3645 "failed to open backup file\n"); 3646 retok = WriteFile(hBackupFile, backupData, sizeof(backupData), &ret, NULL ); 3647 ok( retok && ret == sizeof(backupData), 3648 "WriteFile error (replacement) %d\n", GetLastError()); 3649 ok(GetFileSize(hBackupFile, NULL) == sizeof(backupData), 3650 "backup file has wrong size\n"); 3651 /* change the filetime on the "replaced" file to ensure that it changes */ 3652 ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced); 3653 ok( ret, "GetFileTime error (replaced) %d\n", GetLastError()); 3654 ftReplaced.dwLowDateTime -= 600000000; /* 60 second */ 3655 ret = SetFileTime(hReplacedFile, NULL, NULL, &ftReplaced); 3656 ok( ret, "SetFileTime error (replaced) %d\n", GetLastError()); 3657 GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced); /* get the actual time back */ 3658 CloseHandle(hReplacedFile); 3659 /* change the filetime on the backup to ensure that it changes */ 3660 ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup); 3661 ok( ret, "GetFileTime error (backup) %d\n", GetLastError()); 3662 ftBackup.dwLowDateTime -= 1200000000; /* 120 second */ 3663 ret = SetFileTime(hBackupFile, NULL, NULL, &ftBackup); 3664 ok( ret, "SetFileTime error (backup) %d\n", GetLastError()); 3665 GetFileTime(hBackupFile, NULL, NULL, &ftBackup); /* get the actual time back */ 3666 CloseHandle(hBackupFile); 3667 /* get the filetime on the replacement file to perform checks */ 3668 ret = GetFileTime(hReplacementFile, NULL, NULL, &ftReplacement); 3669 ok( ret, "GetFileTime error (replacement) %d\n", GetLastError()); 3670 CloseHandle(hReplacementFile); 3671 3672 /* perform replacement w/ backup 3673 * TODO: flags are not implemented 3674 */ 3675 SetLastError(0xdeadbeef); 3676 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0); 3677 ok(ret, "ReplaceFileA: unexpected error %d\n", GetLastError()); 3678 /* make sure that the backup has the size of the old "replaced" file */ 3679 hBackupFile = CreateFileA(backup, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 3680 ok(hBackupFile != INVALID_HANDLE_VALUE, 3681 "failed to open backup file\n"); 3682 ret = GetFileSize(hBackupFile, NULL); 3683 ok(ret == sizeof(replacedData), 3684 "backup file has wrong size %d\n", ret); 3685 /* make sure that the "replaced" file has the size of the replacement file */ 3686 hReplacedFile = CreateFileA(replaced, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 3687 ok(hReplacedFile != INVALID_HANDLE_VALUE, 3688 "failed to open replaced file: %d\n", GetLastError()); 3689 if (hReplacedFile != INVALID_HANDLE_VALUE) 3690 { 3691 ret = GetFileSize(hReplacedFile, NULL); 3692 ok(ret == sizeof(replacementData), 3693 "replaced file has wrong size %d\n", ret); 3694 /* make sure that the replacement file no-longer exists */ 3695 hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 3696 ok(hReplacementFile == INVALID_HANDLE_VALUE, 3697 "unexpected error, replacement file should not exist %d\n", GetLastError()); 3698 /* make sure that the backup has the old "replaced" filetime */ 3699 ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup); 3700 ok( ret, "GetFileTime error (backup %d\n", GetLastError()); 3701 ok(check_file_time(&ftBackup, &ftReplaced, 20000000), "backup file has wrong filetime\n"); 3702 CloseHandle(hBackupFile); 3703 /* make sure that the "replaced" has the old replacement filetime */ 3704 ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced); 3705 ok( ret, "GetFileTime error (backup %d\n", GetLastError()); 3706 ok(check_file_time(&ftReplaced, &ftReplacement, 20000000), 3707 "replaced file has wrong filetime %x%08x / %x%08x\n", 3708 ftReplaced.dwHighDateTime, ftReplaced.dwLowDateTime, 3709 ftReplacement.dwHighDateTime, ftReplacement.dwLowDateTime ); 3710 CloseHandle(hReplacedFile); 3711 } 3712 else 3713 skip("couldn't open replacement file, skipping tests\n"); 3714 3715 /* re-create replacement file for pass w/o backup (blank) */ 3716 ret = GetTempFileNameA(temp_path, prefix, 0, replacement); 3717 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError()); 3718 /* perform replacement w/o backup 3719 * TODO: flags are not implemented 3720 */ 3721 SetLastError(0xdeadbeef); 3722 ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0); 3723 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3724 "ReplaceFileA: unexpected error %d\n", GetLastError()); 3725 3726 /* re-create replacement file for pass w/ backup (backup-file not existing) */ 3727 ret = GetTempFileNameA(temp_path, prefix, 0, replacement); 3728 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError()); 3729 ret = DeleteFileA(backup); 3730 ok(ret, "DeleteFileA: error (backup) %d\n", GetLastError()); 3731 /* perform replacement w/ backup (no pre-existing backup) 3732 * TODO: flags are not implemented 3733 */ 3734 SetLastError(0xdeadbeef); 3735 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0); 3736 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3737 "ReplaceFileA: unexpected error %d\n", GetLastError()); 3738 if (ret) 3739 removeBackup = TRUE; 3740 3741 /* re-create replacement file for pass w/ no permissions to "replaced" */ 3742 ret = GetTempFileNameA(temp_path, prefix, 0, replacement); 3743 ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError()); 3744 ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_READONLY); 3745 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3746 "SetFileAttributesA: error setting to read only %d\n", GetLastError()); 3747 /* perform replacement w/ backup (no permission to "replaced") 3748 * TODO: flags are not implemented 3749 */ 3750 SetLastError(0xdeadbeef); 3751 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0); 3752 ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED, "ReplaceFileA: unexpected error %d\n", GetLastError()); 3753 /* make sure that the replacement file still exists */ 3754 hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 3755 ok(hReplacementFile != INVALID_HANDLE_VALUE || 3756 broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* win2k */ 3757 "unexpected error, replacement file should still exist %d\n", GetLastError()); 3758 CloseHandle(hReplacementFile); 3759 ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_NORMAL); 3760 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3761 "SetFileAttributesA: error setting to normal %d\n", GetLastError()); 3762 3763 /* replacement file still exists, make pass w/o "replaced" */ 3764 ret = DeleteFileA(replaced); 3765 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3766 "DeleteFileA: error (replaced) %d\n", GetLastError()); 3767 /* perform replacement w/ backup (no pre-existing backup or "replaced") 3768 * TODO: flags are not implemented 3769 */ 3770 SetLastError(0xdeadbeef); 3771 ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0); 3772 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND || 3773 GetLastError() == ERROR_ACCESS_DENIED), 3774 "ReplaceFileA: unexpected error %d\n", GetLastError()); 3775 3776 /* perform replacement w/o existing "replacement" file 3777 * TODO: flags are not implemented 3778 */ 3779 SetLastError(0xdeadbeef); 3780 ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0); 3781 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND || 3782 GetLastError() == ERROR_ACCESS_DENIED), 3783 "ReplaceFileA: unexpected error %d\n", GetLastError()); 3784 DeleteFileA( replacement ); 3785 3786 /* 3787 * if the first round (w/ backup) worked then as long as there is no 3788 * failure then there is no need to check this round (w/ backup is the 3789 * more complete case) 3790 */ 3791 3792 /* delete temporary files, replacement and replaced are already deleted */ 3793 if (removeBackup) 3794 { 3795 ret = DeleteFileA(backup); 3796 ok(ret || 3797 broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */ 3798 "DeleteFileA: error (backup) %d\n", GetLastError()); 3799 } 3800 } 3801 3802 /* 3803 * ReplaceFileW is a simpler case of ReplaceFileA, there is no 3804 * need to be as thorough. 3805 */ 3806 static void test_ReplaceFileW(void) 3807 { 3808 WCHAR replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH]; 3809 static const WCHAR prefix[] = {'p','f','x',0}; 3810 WCHAR temp_path[MAX_PATH]; 3811 DWORD ret; 3812 BOOL removeBackup = FALSE; 3813 3814 if (!pReplaceFileW) 3815 { 3816 win_skip("ReplaceFileW() is missing\n"); 3817 return; 3818 } 3819 3820 ret = GetTempPathW(MAX_PATH, temp_path); 3821 if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 3822 { 3823 win_skip("GetTempPathW is not available\n"); 3824 return; 3825 } 3826 ok(ret != 0, "GetTempPathW error %d\n", GetLastError()); 3827 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 3828 3829 ret = GetTempFileNameW(temp_path, prefix, 0, replaced); 3830 ok(ret != 0, "GetTempFileNameW error (replaced) %d\n", GetLastError()); 3831 3832 ret = GetTempFileNameW(temp_path, prefix, 0, replacement); 3833 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError()); 3834 3835 ret = GetTempFileNameW(temp_path, prefix, 0, backup); 3836 ok(ret != 0, "GetTempFileNameW error (backup) %d\n", GetLastError()); 3837 3838 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0); 3839 ok(ret, "ReplaceFileW: error %d\n", GetLastError()); 3840 3841 ret = GetTempFileNameW(temp_path, prefix, 0, replacement); 3842 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError()); 3843 ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0); 3844 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3845 "ReplaceFileW: error %d\n", GetLastError()); 3846 3847 ret = GetTempFileNameW(temp_path, prefix, 0, replacement); 3848 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError()); 3849 ret = DeleteFileW(backup); 3850 ok(ret, "DeleteFileW: error (backup) %d\n", GetLastError()); 3851 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0); 3852 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3853 "ReplaceFileW: error %d\n", GetLastError()); 3854 3855 ret = GetTempFileNameW(temp_path, prefix, 0, replacement); 3856 ok(ret != 0, "GetTempFileNameW error (replacement) %d\n", GetLastError()); 3857 ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_READONLY); 3858 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3859 "SetFileAttributesW: error setting to read only %d\n", GetLastError()); 3860 3861 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0); 3862 ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED, 3863 "ReplaceFileW: unexpected error %d\n", GetLastError()); 3864 ret = SetFileAttributesW(replaced, FILE_ATTRIBUTE_NORMAL); 3865 ok(ret || GetLastError() == ERROR_ACCESS_DENIED, 3866 "SetFileAttributesW: error setting to normal %d\n", GetLastError()); 3867 if (ret) 3868 removeBackup = TRUE; 3869 3870 ret = DeleteFileW(replaced); 3871 ok(ret, "DeleteFileW: error (replaced) %d\n", GetLastError()); 3872 ret = pReplaceFileW(replaced, replacement, backup, 0, 0, 0); 3873 ok(!ret, "ReplaceFileW: error %d\n", GetLastError()); 3874 3875 ret = pReplaceFileW(replaced, replacement, NULL, 0, 0, 0); 3876 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND || 3877 GetLastError() == ERROR_ACCESS_DENIED), 3878 "ReplaceFileW: unexpected error %d\n", GetLastError()); 3879 DeleteFileW( replacement ); 3880 3881 if (removeBackup) 3882 { 3883 ret = DeleteFileW(backup); 3884 ok(ret || 3885 broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */ 3886 "DeleteFileW: error (backup) %d\n", GetLastError()); 3887 } 3888 } 3889 3890 static void test_CreateFile(void) 3891 { 3892 static const struct test_data 3893 { 3894 DWORD disposition, access, error, clean_up; 3895 } td[] = 3896 { 3897 /* 0 */ { 0, 0, ERROR_INVALID_PARAMETER, 0 }, 3898 /* 1 */ { 0, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 }, 3899 /* 2 */ { 0, GENERIC_READ|GENERIC_WRITE, ERROR_INVALID_PARAMETER, 0 }, 3900 /* 3 */ { CREATE_NEW, 0, ERROR_FILE_EXISTS, 1 }, 3901 /* 4 */ { CREATE_NEW, 0, 0, 1 }, 3902 /* 5 */ { CREATE_NEW, GENERIC_READ, 0, 1 }, 3903 /* 6 */ { CREATE_NEW, GENERIC_WRITE, 0, 1 }, 3904 /* 7 */ { CREATE_NEW, GENERIC_READ|GENERIC_WRITE, 0, 0 }, 3905 /* 8 */ { CREATE_ALWAYS, 0, 0, 0 }, 3906 /* 9 */ { CREATE_ALWAYS, GENERIC_READ, 0, 0 }, 3907 /* 10*/ { CREATE_ALWAYS, GENERIC_WRITE, 0, 0 }, 3908 /* 11*/ { CREATE_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 1 }, 3909 /* 12*/ { OPEN_EXISTING, 0, ERROR_FILE_NOT_FOUND, 0 }, 3910 /* 13*/ { CREATE_ALWAYS, 0, 0, 0 }, 3911 /* 14*/ { OPEN_EXISTING, 0, 0, 0 }, 3912 /* 15*/ { OPEN_EXISTING, GENERIC_READ, 0, 0 }, 3913 /* 16*/ { OPEN_EXISTING, GENERIC_WRITE, 0, 0 }, 3914 /* 17*/ { OPEN_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 1 }, 3915 /* 18*/ { OPEN_ALWAYS, 0, 0, 0 }, 3916 /* 19*/ { OPEN_ALWAYS, GENERIC_READ, 0, 0 }, 3917 /* 20*/ { OPEN_ALWAYS, GENERIC_WRITE, 0, 0 }, 3918 /* 21*/ { OPEN_ALWAYS, GENERIC_READ|GENERIC_WRITE, 0, 0 }, 3919 /* 22*/ { TRUNCATE_EXISTING, 0, ERROR_INVALID_PARAMETER, 0 }, 3920 /* 23*/ { TRUNCATE_EXISTING, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 }, 3921 /* 24*/ { TRUNCATE_EXISTING, GENERIC_WRITE, 0, 0 }, 3922 /* 25*/ { TRUNCATE_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 0 }, 3923 /* 26*/ { TRUNCATE_EXISTING, FILE_WRITE_DATA, ERROR_INVALID_PARAMETER, 0 } 3924 }; 3925 char temp_path[MAX_PATH]; 3926 char file_name[MAX_PATH]; 3927 DWORD i, ret, written; 3928 HANDLE hfile; 3929 3930 GetTempPathA(MAX_PATH, temp_path); 3931 GetTempFileNameA(temp_path, "tmp", 0, file_name); 3932 3933 i = strlen(temp_path); 3934 if (i && temp_path[i - 1] == '\\') temp_path[i - 1] = 0; 3935 3936 for (i = 0; i <= 5; i++) 3937 { 3938 SetLastError(0xdeadbeef); 3939 hfile = CreateFileA(temp_path, GENERIC_READ, 0, NULL, i, 0, 0); 3940 ok(hfile == INVALID_HANDLE_VALUE, "CreateFile should fail\n"); 3941 if (i == 0 || i == 5) 3942 { 3943 /* FIXME: remove once Wine is fixed */ 3944 todo_wine_if (i == 5) 3945 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError()); 3946 } 3947 else 3948 { 3949 /* FIXME: remove once Wine is fixed */ 3950 todo_wine_if (i == 1) 3951 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError()); 3952 } 3953 3954 SetLastError(0xdeadbeef); 3955 hfile = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, i, 0, 0); 3956 ok(hfile == INVALID_HANDLE_VALUE, "CreateFile should fail\n"); 3957 if (i == 0) 3958 ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError()); 3959 else 3960 { 3961 /* FIXME: remove once Wine is fixed */ 3962 todo_wine_if (i == 1) 3963 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError()); 3964 } 3965 } 3966 3967 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 3968 { 3969 SetLastError(0xdeadbeef); 3970 hfile = CreateFileA(file_name, td[i].access, 0, NULL, td[i].disposition, 0, 0); 3971 if (!td[i].error) 3972 { 3973 ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError()); 3974 written = 0xdeadbeef; 3975 SetLastError(0xdeadbeef); 3976 ret = WriteFile(hfile, &td[i].error, sizeof(td[i].error), &written, NULL); 3977 if (td[i].access & GENERIC_WRITE) 3978 ok(ret, "%d: WriteFile error %d\n", i, GetLastError()); 3979 else 3980 { 3981 ok(!ret, "%d: WriteFile should fail\n", i); 3982 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError()); 3983 } 3984 SetLastError(0xdeadbeef); 3985 ret = SetFileTime(hfile, NULL, NULL, NULL); 3986 if (td[i].access & GENERIC_WRITE) /* actually FILE_WRITE_ATTRIBUTES */ 3987 ok(ret, "%d: SetFileTime error %d\n", i, GetLastError()); 3988 else 3989 { 3990 todo_wine 3991 { 3992 ok(!ret, "%d: SetFileTime should fail\n", i); 3993 ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError()); 3994 } 3995 } 3996 CloseHandle(hfile); 3997 } 3998 else 3999 { 4000 /* FIXME: remove the condition below once Wine is fixed */ 4001 if (td[i].disposition == TRUNCATE_EXISTING && !(td[i].access & GENERIC_WRITE)) 4002 { 4003 todo_wine 4004 { 4005 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i); 4006 ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError()); 4007 } 4008 CloseHandle(hfile); 4009 } 4010 else 4011 { 4012 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i); 4013 ok(GetLastError() == td[i].error, "%d: expected %d, got %d\n", i, td[i].error, GetLastError()); 4014 } 4015 } 4016 4017 if (td[i].clean_up) DeleteFileA(file_name); 4018 } 4019 4020 DeleteFileA(file_name); 4021 } 4022 4023 static void test_GetFileInformationByHandleEx(void) 4024 { 4025 int i; 4026 char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024], *strPtr; 4027 BOOL ret; 4028 DWORD ret2, written; 4029 HANDLE directory, file; 4030 FILE_ID_BOTH_DIR_INFO *bothDirInfo; 4031 FILE_BASIC_INFO *basicInfo; 4032 FILE_STANDARD_INFO *standardInfo; 4033 FILE_NAME_INFO *nameInfo; 4034 LARGE_INTEGER prevWrite; 4035 FILE_IO_PRIORITY_HINT_INFO priohintinfo; 4036 FILE_ALLOCATION_INFO allocinfo; 4037 FILE_DISPOSITION_INFO dispinfo; 4038 FILE_END_OF_FILE_INFO eofinfo; 4039 FILE_RENAME_INFO renameinfo; 4040 4041 struct { 4042 FILE_INFO_BY_HANDLE_CLASS handleClass; 4043 void *ptr; 4044 DWORD size; 4045 DWORD errorCode; 4046 } checks[] = { 4047 {0xdeadbeef, NULL, 0, ERROR_INVALID_PARAMETER}, 4048 {FileIdBothDirectoryInfo, NULL, 0, ERROR_BAD_LENGTH}, 4049 {FileIdBothDirectoryInfo, NULL, sizeof(buffer), ERROR_NOACCESS}, 4050 {FileIdBothDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH}}; 4051 4052 if (!pGetFileInformationByHandleEx) 4053 { 4054 win_skip("GetFileInformationByHandleEx is missing.\n"); 4055 return; 4056 } 4057 4058 ret2 = GetTempPathA(sizeof(tempPath), tempPath); 4059 ok(ret2, "GetFileInformationByHandleEx: GetTempPathA failed, got error %u.\n", GetLastError()); 4060 4061 /* ensure the existence of a file in the temp folder */ 4062 ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName); 4063 ok(ret2, "GetFileInformationByHandleEx: GetTempFileNameA failed, got error %u.\n", GetLastError()); 4064 ret2 = GetFileAttributesA(tempFileName); 4065 ok(ret2 != INVALID_FILE_ATTRIBUTES, "GetFileInformationByHandleEx: " 4066 "GetFileAttributesA failed to find the temp file, got error %u.\n", GetLastError()); 4067 4068 directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 4069 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 4070 ok(directory != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp folder, " 4071 "got error %u.\n", GetLastError()); 4072 4073 for (i = 0; i < sizeof(checks) / sizeof(checks[0]); i += 1) 4074 { 4075 SetLastError(0xdeadbeef); 4076 ret = pGetFileInformationByHandleEx(directory, checks[i].handleClass, checks[i].ptr, checks[i].size); 4077 ok(!ret && GetLastError() == checks[i].errorCode, "GetFileInformationByHandleEx: expected error %u, " 4078 "got %u.\n", checks[i].errorCode, GetLastError()); 4079 } 4080 4081 while (TRUE) 4082 { 4083 memset(buffer, 0xff, sizeof(buffer)); 4084 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer)); 4085 if (!ret && GetLastError() == ERROR_NO_MORE_FILES) 4086 break; 4087 ok(ret, "GetFileInformationByHandleEx: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError()); 4088 if (!ret) 4089 break; 4090 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer; 4091 while (TRUE) 4092 { 4093 ok(bothDirInfo->FileAttributes != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file attributes.\n"); 4094 ok(bothDirInfo->FileId.u.LowPart != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file id.\n"); 4095 ok(bothDirInfo->FileNameLength != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file name length.\n"); 4096 if (!bothDirInfo->NextEntryOffset) 4097 break; 4098 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset); 4099 } 4100 } 4101 4102 CloseHandle(directory); 4103 4104 file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 4105 NULL, OPEN_EXISTING, 0, NULL); 4106 ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, " 4107 "got error %u.\n", GetLastError()); 4108 4109 /* Test FileBasicInfo; make sure the write time changes when a file is updated */ 4110 memset(buffer, 0xff, sizeof(buffer)); 4111 ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer)); 4112 ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError()); 4113 basicInfo = (FILE_BASIC_INFO *)buffer; 4114 prevWrite = basicInfo->LastWriteTime; 4115 CloseHandle(file); 4116 4117 Sleep(30); /* Make sure a new write time is different from the previous */ 4118 4119 /* Write something to the file, to make sure the write time has changed */ 4120 file = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 4121 NULL, OPEN_EXISTING, 0, NULL); 4122 ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, " 4123 "got error %u.\n", GetLastError()); 4124 ret = WriteFile(file, tempFileName, strlen(tempFileName), &written, NULL); 4125 ok(ret, "GetFileInformationByHandleEx: Write failed\n"); 4126 CloseHandle(file); 4127 4128 file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 4129 NULL, OPEN_EXISTING, 0, NULL); 4130 ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, " 4131 "got error %u.\n", GetLastError()); 4132 4133 memset(buffer, 0xff, sizeof(buffer)); 4134 ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer)); 4135 ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError()); 4136 basicInfo = (FILE_BASIC_INFO *)buffer; 4137 /* Could also check that the creation time didn't change - on windows 4138 * it doesn't, but on wine, it does change even if it shouldn't. */ 4139 ok(basicInfo->LastWriteTime.QuadPart != prevWrite.QuadPart, 4140 "GetFileInformationByHandleEx: last write time didn't change\n"); 4141 4142 /* Test FileStandardInfo, check some basic parameters */ 4143 memset(buffer, 0xff, sizeof(buffer)); 4144 ret = pGetFileInformationByHandleEx(file, FileStandardInfo, buffer, sizeof(buffer)); 4145 ok(ret, "GetFileInformationByHandleEx: failed to get FileStandardInfo, %u\n", GetLastError()); 4146 standardInfo = (FILE_STANDARD_INFO *)buffer; 4147 ok(standardInfo->NumberOfLinks == 1, "GetFileInformationByHandleEx: Unexpected number of links\n"); 4148 ok(standardInfo->DeletePending == FALSE, "GetFileInformationByHandleEx: Unexpected pending delete\n"); 4149 ok(standardInfo->Directory == FALSE, "GetFileInformationByHandleEx: Incorrect directory flag\n"); 4150 4151 /* Test FileNameInfo */ 4152 memset(buffer, 0xff, sizeof(buffer)); 4153 ret = pGetFileInformationByHandleEx(file, FileNameInfo, buffer, sizeof(buffer)); 4154 ok(ret, "GetFileInformationByHandleEx: failed to get FileNameInfo, %u\n", GetLastError()); 4155 nameInfo = (FILE_NAME_INFO *)buffer; 4156 strPtr = strchr(tempFileName, '\\'); 4157 ok(strPtr != NULL, "GetFileInformationByHandleEx: Temp filename didn't contain backslash\n"); 4158 ok(nameInfo->FileNameLength == strlen(strPtr) * 2, 4159 "GetFileInformationByHandleEx: Incorrect file name length\n"); 4160 for (i = 0; i < nameInfo->FileNameLength/2; i++) 4161 ok(strPtr[i] == nameInfo->FileName[i], "Incorrect filename char %d: %c vs %c\n", 4162 i, strPtr[i], nameInfo->FileName[i]); 4163 4164 /* invalid classes */ 4165 SetLastError(0xdeadbeef); 4166 ret = pGetFileInformationByHandleEx(file, FileEndOfFileInfo, &eofinfo, sizeof(eofinfo)); 4167 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4168 4169 SetLastError(0xdeadbeef); 4170 ret = pGetFileInformationByHandleEx(file, FileIoPriorityHintInfo, &priohintinfo, sizeof(priohintinfo)); 4171 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4172 4173 SetLastError(0xdeadbeef); 4174 ret = pGetFileInformationByHandleEx(file, FileAllocationInfo, &allocinfo, sizeof(allocinfo)); 4175 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4176 4177 SetLastError(0xdeadbeef); 4178 ret = pGetFileInformationByHandleEx(file, FileDispositionInfo, &dispinfo, sizeof(dispinfo)); 4179 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4180 4181 SetLastError(0xdeadbeef); 4182 ret = pGetFileInformationByHandleEx(file, FileRenameInfo, &renameinfo, sizeof(renameinfo)); 4183 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4184 4185 CloseHandle(file); 4186 DeleteFileA(tempFileName); 4187 } 4188 4189 static void test_OpenFileById(void) 4190 { 4191 char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[256], tickCount[256]; 4192 WCHAR tempFileNameW[MAX_PATH]; 4193 BOOL ret, found; 4194 DWORD ret2, count, tempFileNameLen; 4195 HANDLE directory, handle, tempFile; 4196 FILE_ID_BOTH_DIR_INFO *bothDirInfo; 4197 FILE_ID_DESCRIPTOR fileIdDescr; 4198 4199 if (!pGetFileInformationByHandleEx || !pOpenFileById) 4200 { 4201 win_skip("GetFileInformationByHandleEx or OpenFileById is missing.\n"); 4202 return; 4203 } 4204 4205 ret2 = GetTempPathA(sizeof(tempPath), tempPath); 4206 ok(ret2, "OpenFileById: GetTempPath failed, got error %u.\n", GetLastError()); 4207 4208 /* ensure the existence of a file in the temp folder */ 4209 ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName); 4210 ok(ret2, "OpenFileById: GetTempFileNameA failed, got error %u.\n", GetLastError()); 4211 ret2 = GetFileAttributesA(tempFileName); 4212 ok(ret2 != INVALID_FILE_ATTRIBUTES, 4213 "OpenFileById: GetFileAttributesA failed to find the temp file, got error %u\n", GetLastError()); 4214 4215 ret2 = MultiByteToWideChar(CP_ACP, 0, tempFileName + strlen(tempPath), -1, tempFileNameW, sizeof(tempFileNameW)/sizeof(tempFileNameW[0])); 4216 ok(ret2, "OpenFileById: MultiByteToWideChar failed to convert tempFileName, got error %u.\n", GetLastError()); 4217 tempFileNameLen = ret2 - 1; 4218 4219 tempFile = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 4220 ok(tempFile != INVALID_HANDLE_VALUE, "OpenFileById: failed to create a temp file, " 4221 "got error %u.\n", GetLastError()); 4222 ret2 = sprintf(tickCount, "%u", GetTickCount()); 4223 ret = WriteFile(tempFile, tickCount, ret2, &count, NULL); 4224 ok(ret, "OpenFileById: WriteFile failed, got error %u.\n", GetLastError()); 4225 CloseHandle(tempFile); 4226 4227 directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 4228 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 4229 ok(directory != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder, " 4230 "got error %u.\n", GetLastError()); 4231 4232 /* get info about the temp folder itself */ 4233 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer; 4234 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer)); 4235 ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError()); 4236 ok(bothDirInfo->FileNameLength == sizeof(WCHAR) && bothDirInfo->FileName[0] == '.', 4237 "OpenFileById: failed to return the temp folder at the first entry, got error %u.\n", GetLastError()); 4238 4239 /* open the temp folder itself */ 4240 fileIdDescr.dwSize = sizeof(fileIdDescr); 4241 fileIdDescr.Type = FileIdType; 4242 U(fileIdDescr).FileId = bothDirInfo->FileId; 4243 handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0); 4244 todo_wine 4245 ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder itself, got error %u.\n", GetLastError()); 4246 CloseHandle(handle); 4247 4248 /* find the temp file in the temp folder */ 4249 found = FALSE; 4250 while (!found) 4251 { 4252 ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer)); 4253 ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError()); 4254 if (!ret) 4255 break; 4256 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer; 4257 while (TRUE) 4258 { 4259 if (tempFileNameLen == bothDirInfo->FileNameLength / sizeof(WCHAR) && 4260 memcmp(tempFileNameW, bothDirInfo->FileName, bothDirInfo->FileNameLength) == 0) 4261 { 4262 found = TRUE; 4263 break; 4264 } 4265 if (!bothDirInfo->NextEntryOffset) 4266 break; 4267 bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset); 4268 } 4269 } 4270 ok(found, "OpenFileById: failed to find the temp file in the temp folder.\n"); 4271 4272 SetLastError(0xdeadbeef); 4273 handle = pOpenFileById(directory, NULL, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0); 4274 ok(handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER, 4275 "OpenFileById: expected ERROR_INVALID_PARAMETER, got error %u.\n", GetLastError()); 4276 4277 fileIdDescr.dwSize = sizeof(fileIdDescr); 4278 fileIdDescr.Type = FileIdType; 4279 U(fileIdDescr).FileId = bothDirInfo->FileId; 4280 handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0); 4281 ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the file, got error %u.\n", GetLastError()); 4282 4283 ret = ReadFile(handle, buffer, sizeof(buffer), &count, NULL); 4284 buffer[count] = 0; 4285 ok(ret, "OpenFileById: ReadFile failed, got error %u.\n", GetLastError()); 4286 ok(strcmp(tickCount, buffer) == 0, "OpenFileById: invalid contents of the temp file.\n"); 4287 4288 CloseHandle(handle); 4289 CloseHandle(directory); 4290 DeleteFileA(tempFileName); 4291 } 4292 4293 static void test_SetFileValidData(void) 4294 { 4295 BOOL ret; 4296 HANDLE handle; 4297 DWORD error, count; 4298 char path[MAX_PATH], filename[MAX_PATH]; 4299 TOKEN_PRIVILEGES privs; 4300 HANDLE token = NULL; 4301 4302 if (!pSetFileValidData) 4303 { 4304 win_skip("SetFileValidData is missing\n"); 4305 return; 4306 } 4307 GetTempPathA(sizeof(path), path); 4308 GetTempFileNameA(path, "tst", 0, filename); 4309 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 4310 WriteFile(handle, "test", sizeof("test") - 1, &count, NULL); 4311 CloseHandle(handle); 4312 4313 SetLastError(0xdeadbeef); 4314 ret = pSetFileValidData(INVALID_HANDLE_VALUE, 0); 4315 error = GetLastError(); 4316 ok(!ret, "SetFileValidData succeeded\n"); 4317 ok(error == ERROR_INVALID_HANDLE, "got %u\n", error); 4318 4319 SetLastError(0xdeadbeef); 4320 ret = pSetFileValidData(INVALID_HANDLE_VALUE, -1); 4321 error = GetLastError(); 4322 ok(!ret, "SetFileValidData succeeded\n"); 4323 ok(error == ERROR_INVALID_HANDLE, "got %u\n", error); 4324 4325 /* file opened for reading */ 4326 handle = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 4327 4328 SetLastError(0xdeadbeef); 4329 ret = pSetFileValidData(handle, 0); 4330 ok(!ret, "SetFileValidData succeeded\n"); 4331 error = GetLastError(); 4332 ok(error == ERROR_ACCESS_DENIED, "got %u\n", error); 4333 4334 SetLastError(0xdeadbeef); 4335 ret = pSetFileValidData(handle, -1); 4336 error = GetLastError(); 4337 ok(!ret, "SetFileValidData succeeded\n"); 4338 ok(error == ERROR_ACCESS_DENIED, "got %u\n", error); 4339 CloseHandle(handle); 4340 4341 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 4342 4343 SetLastError(0xdeadbeef); 4344 ret = pSetFileValidData(handle, 0); 4345 error = GetLastError(); 4346 ok(!ret, "SetFileValidData succeeded\n"); 4347 todo_wine ok(error == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", error); 4348 CloseHandle(handle); 4349 4350 privs.PrivilegeCount = 1; 4351 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 4352 4353 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token) || 4354 !LookupPrivilegeValueA(NULL, SE_MANAGE_VOLUME_NAME, &privs.Privileges[0].Luid) || 4355 !AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL) || 4356 GetLastError() == ERROR_NOT_ALL_ASSIGNED) 4357 { 4358 win_skip("cannot enable SE_MANAGE_VOLUME_NAME privilege\n"); 4359 CloseHandle(token); 4360 DeleteFileA(filename); 4361 return; 4362 } 4363 handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 4364 4365 SetLastError(0xdeadbeef); 4366 ret = pSetFileValidData(handle, 0); 4367 error = GetLastError(); 4368 ok(!ret, "SetFileValidData succeeded\n"); 4369 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error); 4370 4371 SetLastError(0xdeadbeef); 4372 ret = pSetFileValidData(handle, -1); 4373 error = GetLastError(); 4374 ok(!ret, "SetFileValidData succeeded\n"); 4375 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error); 4376 4377 SetLastError(0xdeadbeef); 4378 ret = pSetFileValidData(handle, 2); 4379 error = GetLastError(); 4380 todo_wine ok(!ret, "SetFileValidData succeeded\n"); 4381 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error); 4382 4383 ret = pSetFileValidData(handle, 4); 4384 ok(ret, "SetFileValidData failed %u\n", GetLastError()); 4385 4386 SetLastError(0xdeadbeef); 4387 ret = pSetFileValidData(handle, 8); 4388 error = GetLastError(); 4389 ok(!ret, "SetFileValidData succeeded\n"); 4390 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error); 4391 4392 count = SetFilePointer(handle, 1024, NULL, FILE_END); 4393 ok(count != INVALID_SET_FILE_POINTER, "SetFilePointer failed %u\n", GetLastError()); 4394 ret = SetEndOfFile(handle); 4395 ok(ret, "SetEndOfFile failed %u\n", GetLastError()); 4396 4397 SetLastError(0xdeadbeef); 4398 ret = pSetFileValidData(handle, 2); 4399 error = GetLastError(); 4400 todo_wine ok(!ret, "SetFileValidData succeeded\n"); 4401 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error); 4402 4403 ret = pSetFileValidData(handle, 4); 4404 ok(ret, "SetFileValidData failed %u\n", GetLastError()); 4405 4406 ret = pSetFileValidData(handle, 8); 4407 ok(ret, "SetFileValidData failed %u\n", GetLastError()); 4408 4409 ret = pSetFileValidData(handle, 4); 4410 error = GetLastError(); 4411 todo_wine ok(!ret, "SetFileValidData succeeded\n"); 4412 todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error); 4413 4414 ret = pSetFileValidData(handle, 1024); 4415 ok(ret, "SetFileValidData failed %u\n", GetLastError()); 4416 4417 ret = pSetFileValidData(handle, 2048); 4418 error = GetLastError(); 4419 ok(!ret, "SetFileValidData succeeded\n"); 4420 ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error); 4421 4422 privs.Privileges[0].Attributes = 0; 4423 AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL); 4424 4425 CloseHandle(token); 4426 CloseHandle(handle); 4427 DeleteFileA(filename); 4428 } 4429 4430 static void test_WriteFileGather(void) 4431 { 4432 char temp_path[MAX_PATH], filename[MAX_PATH]; 4433 HANDLE hfile, hiocp1, hiocp2; 4434 DWORD ret, size; 4435 ULONG_PTR key; 4436 FILE_SEGMENT_ELEMENT fse[2]; 4437 OVERLAPPED ovl, *povl = NULL; 4438 SYSTEM_INFO si; 4439 LPVOID buf = NULL; 4440 4441 ret = GetTempPathA( MAX_PATH, temp_path ); 4442 ok( ret != 0, "GetTempPathA error %d\n", GetLastError() ); 4443 ok( ret < MAX_PATH, "temp path should fit into MAX_PATH\n" ); 4444 ret = GetTempFileNameA( temp_path, "wfg", 0, filename ); 4445 ok( ret != 0, "GetTempFileNameA error %d\n", GetLastError() ); 4446 4447 hfile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 4448 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, 0 ); 4449 ok( hfile != INVALID_HANDLE_VALUE, "CreateFile failed err %u\n", GetLastError() ); 4450 if (hfile == INVALID_HANDLE_VALUE) return; 4451 4452 hiocp1 = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 999, 0 ); 4453 hiocp2 = CreateIoCompletionPort( hfile, hiocp1, 999, 0 ); 4454 ok( hiocp2 != 0, "CreateIoCompletionPort failed err %u\n", GetLastError() ); 4455 4456 GetSystemInfo( &si ); 4457 buf = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE ); 4458 ok( buf != NULL, "VirtualAlloc failed err %u\n", GetLastError() ); 4459 4460 memset( &ovl, 0, sizeof(ovl) ); 4461 memset( fse, 0, sizeof(fse) ); 4462 fse[0].Buffer = buf; 4463 if (!WriteFileGather( hfile, fse, si.dwPageSize, NULL, &ovl )) 4464 ok( GetLastError() == ERROR_IO_PENDING, "WriteFileGather failed err %u\n", GetLastError() ); 4465 4466 ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 ); 4467 ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError()); 4468 ok( povl == &ovl, "wrong ovl %p\n", povl ); 4469 4470 memset( &ovl, 0, sizeof(ovl) ); 4471 memset( fse, 0, sizeof(fse) ); 4472 fse[0].Buffer = buf; 4473 if (!ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl )) 4474 ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() ); 4475 4476 ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 ); 4477 ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError()); 4478 ok( povl == &ovl, "wrong ovl %p\n", povl ); 4479 4480 CloseHandle( hfile ); 4481 CloseHandle( hiocp1 ); 4482 CloseHandle( hiocp2 ); 4483 VirtualFree( buf, 0, MEM_RELEASE ); 4484 DeleteFileA( filename ); 4485 } 4486 4487 static unsigned file_map_access(unsigned access) 4488 { 4489 if (access & GENERIC_READ) access |= FILE_GENERIC_READ; 4490 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE; 4491 if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE; 4492 if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS; 4493 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); 4494 } 4495 4496 static BOOL is_access_compatible(unsigned obj_access, unsigned desired_access) 4497 { 4498 obj_access = file_map_access(obj_access); 4499 desired_access = file_map_access(desired_access); 4500 return (obj_access & desired_access) == desired_access; 4501 } 4502 4503 static void test_file_access(void) 4504 { 4505 static const struct 4506 { 4507 unsigned access, create_error, write_error, read_error; 4508 } td[] = 4509 { 4510 { GENERIC_READ | GENERIC_WRITE, 0, 0, 0 }, 4511 { GENERIC_WRITE, 0, 0, ERROR_ACCESS_DENIED }, 4512 { GENERIC_READ, 0, ERROR_ACCESS_DENIED, 0 }, 4513 { FILE_READ_DATA | FILE_WRITE_DATA, 0, 0, 0 }, 4514 { FILE_WRITE_DATA, 0, 0, ERROR_ACCESS_DENIED }, 4515 { FILE_READ_DATA, 0, ERROR_ACCESS_DENIED, 0 }, 4516 { FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED }, 4517 { FILE_READ_DATA | FILE_APPEND_DATA, 0, 0, 0 }, 4518 { FILE_WRITE_DATA | FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED }, 4519 { 0, 0, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED }, 4520 }; 4521 char path[MAX_PATH], fname[MAX_PATH]; 4522 unsigned char buf[16]; 4523 HANDLE hfile, hdup; 4524 DWORD i, j, ret, bytes; 4525 4526 GetTempPathA(MAX_PATH, path); 4527 GetTempFileNameA(path, "foo", 0, fname); 4528 4529 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 4530 { 4531 SetLastError(0xdeadbeef); 4532 hfile = CreateFileA(fname, td[i].access, 0, NULL, CREATE_ALWAYS, 4533 FILE_FLAG_DELETE_ON_CLOSE, 0); 4534 if (td[i].create_error) 4535 { 4536 ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i); 4537 ok(td[i].create_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].create_error, GetLastError()); 4538 continue; 4539 } 4540 else 4541 ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError()); 4542 4543 for (j = 0; j < sizeof(td)/sizeof(td[0]); j++) 4544 { 4545 SetLastError(0xdeadbeef); 4546 ret = DuplicateHandle(GetCurrentProcess(), hfile, GetCurrentProcess(), &hdup, 4547 td[j].access, 0, 0); 4548 if (is_access_compatible(td[i].access, td[j].access)) 4549 ok(ret, "DuplicateHandle(%#x => %#x) error %d\n", td[i].access, td[j].access, GetLastError()); 4550 else 4551 { 4552 /* FIXME: Remove once Wine is fixed */ 4553 todo_wine_if((td[j].access & (GENERIC_READ | GENERIC_WRITE) || 4554 (!(td[i].access & (GENERIC_WRITE | FILE_WRITE_DATA)) && (td[j].access & FILE_WRITE_DATA)) || 4555 (!(td[i].access & (GENERIC_READ | FILE_READ_DATA)) && (td[j].access & FILE_READ_DATA)) || 4556 (!(td[i].access & (GENERIC_WRITE)) && (td[j].access & FILE_APPEND_DATA)))) 4557 { 4558 ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access); 4559 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 4560 } 4561 } 4562 if (ret) CloseHandle(hdup); 4563 } 4564 4565 SetLastError(0xdeadbeef); 4566 bytes = 0xdeadbeef; 4567 ret = WriteFile(hfile, "\x5e\xa7", 2, &bytes, NULL); 4568 if (td[i].write_error) 4569 { 4570 ok(!ret, "%d: WriteFile should fail\n", i); 4571 ok(td[i].write_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].write_error, GetLastError()); 4572 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes); 4573 } 4574 else 4575 { 4576 ok(ret, "%d: WriteFile error %d\n", i, GetLastError()); 4577 ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes); 4578 } 4579 4580 SetLastError(0xdeadbeef); 4581 ret = SetFilePointer(hfile, 0, NULL, FILE_BEGIN); 4582 ok(ret != INVALID_SET_FILE_POINTER, "SetFilePointer error %d\n", GetLastError()); 4583 4584 SetLastError(0xdeadbeef); 4585 bytes = 0xdeadbeef; 4586 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL); 4587 if (td[i].read_error) 4588 { 4589 ok(!ret, "%d: ReadFile should fail\n", i); 4590 ok(td[i].read_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].read_error, GetLastError()); 4591 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes); 4592 } 4593 else 4594 { 4595 ok(ret, "%d: ReadFile error %d\n", i, GetLastError()); 4596 if (td[i].write_error) 4597 ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes); 4598 else 4599 { 4600 ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes); 4601 ok(buf[0] == 0x5e && buf[1] == 0xa7, "%d: expected 5ea7, got %02x%02x\n", i, buf[0], buf[1]); 4602 } 4603 } 4604 4605 CloseHandle(hfile); 4606 } 4607 } 4608 4609 static void test_GetFinalPathNameByHandleA(void) 4610 { 4611 static char prefix[] = "GetFinalPathNameByHandleA"; 4612 static char dos_prefix[] = "\\\\?\\"; 4613 char temp_path[MAX_PATH], test_path[MAX_PATH]; 4614 char long_path[MAX_PATH], result_path[MAX_PATH]; 4615 char dos_path[MAX_PATH + sizeof(dos_prefix)]; 4616 HANDLE file; 4617 DWORD count; 4618 UINT ret; 4619 4620 if (!pGetFinalPathNameByHandleA) 4621 { 4622 skip("GetFinalPathNameByHandleA is missing\n"); 4623 return; 4624 } 4625 4626 /* Test calling with INVALID_HANDLE_VALUE */ 4627 SetLastError(0xdeadbeaf); 4628 count = pGetFinalPathNameByHandleA(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4629 ok(count == 0, "Expected length 0, got %u\n", count); 4630 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 4631 4632 count = GetTempPathA(MAX_PATH, temp_path); 4633 ok(count, "Failed to get temp path, error %u\n", GetLastError()); 4634 ret = GetTempFileNameA(temp_path, prefix, 0, test_path); 4635 ok(ret != 0, "GetTempFileNameA error %u\n", GetLastError()); 4636 ret = GetLongPathNameA(test_path, long_path, MAX_PATH); 4637 ok(ret != 0, "GetLongPathNameA error %u\n", GetLastError()); 4638 strcpy(dos_path, dos_prefix); 4639 strcat(dos_path, long_path); 4640 4641 count = pGetFinalPathNameByHandleA(INVALID_HANDLE_VALUE, NULL, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4642 ok(count == 0, "Expected length 0, got %u\n", count); 4643 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 4644 4645 file = CreateFileA(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, 4646 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0); 4647 ok(file != INVALID_HANDLE_VALUE, "CreateFileA error %u\n", GetLastError()); 4648 4649 if (0) { 4650 /* Windows crashes on NULL path */ 4651 count = pGetFinalPathNameByHandleA(file, NULL, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4652 ok(count == 0, "Expected length 0, got %u\n", count); 4653 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 4654 } 4655 4656 /* Test 0-length path */ 4657 count = pGetFinalPathNameByHandleA(file, result_path, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4658 ok(count == strlen(dos_path), "Expected length %u, got %u\n", lstrlenA(dos_path), count); 4659 4660 /* Test 0 and NULL path */ 4661 count = pGetFinalPathNameByHandleA(file, NULL, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4662 ok(count == strlen(dos_path), "Expected length %u, got %u\n", lstrlenA(dos_path), count); 4663 4664 /* Test VOLUME_NAME_DOS with sufficient buffer size */ 4665 memset(result_path, 0x11, sizeof(result_path)); 4666 count = pGetFinalPathNameByHandleA(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4667 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count); 4668 ok(lstrcmpiA(dos_path, result_path) == 0, "Expected %s, got %s\n", dos_path, result_path); 4669 4670 /* Test VOLUME_NAME_DOS with insufficient buffer size */ 4671 memset(result_path, 0x11, sizeof(result_path)); 4672 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)-2, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4673 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count); 4674 ok(result_path[0] == 0x11, "Result path was modified\n"); 4675 4676 memset(result_path, 0x11, sizeof(result_path)); 4677 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4678 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count); 4679 ok(result_path[0] == 0x11, "Result path was modified\n"); 4680 4681 memset(result_path, 0x11, sizeof(result_path)); 4682 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4683 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count); 4684 ok(result_path[0] == 0x11, "Result path was modified\n"); 4685 4686 memset(result_path, 0x11, sizeof(result_path)); 4687 count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4688 ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count); 4689 ok(result_path[0] != 0x11, "Result path was not modified\n"); 4690 ok(!result_path[strlen(dos_path)], "Expected nullterminated string\n"); 4691 ok(result_path[strlen(dos_path)+1] == 0x11, "Buffer overflow\n"); 4692 4693 CloseHandle(file); 4694 } 4695 4696 static void test_GetFinalPathNameByHandleW(void) 4697 { 4698 static WCHAR prefix[] = {'G','e','t','F','i','n','a','l','P','a','t','h', 4699 'N','a','m','e','B','y','H','a','n','d','l','e','W','\0'}; 4700 static WCHAR dos_prefix[] = {'\\','\\','?','\\','\0'}; 4701 WCHAR temp_path[MAX_PATH], test_path[MAX_PATH]; 4702 WCHAR long_path[MAX_PATH], result_path[MAX_PATH]; 4703 WCHAR dos_path[MAX_PATH + sizeof(dos_prefix)]; 4704 WCHAR drive_part[MAX_PATH]; 4705 WCHAR *file_part; 4706 WCHAR volume_path[MAX_PATH + 50]; 4707 WCHAR nt_path[2 * MAX_PATH]; 4708 BOOL success; 4709 HANDLE file; 4710 DWORD count; 4711 UINT ret; 4712 4713 if (!pGetFinalPathNameByHandleW) 4714 { 4715 skip("GetFinalPathNameByHandleW is missing\n"); 4716 return; 4717 } 4718 4719 /* Test calling with INVALID_HANDLE_VALUE */ 4720 SetLastError(0xdeadbeaf); 4721 count = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4722 ok(count == 0, "Expected length 0, got %u\n", count); 4723 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 4724 4725 count = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, NULL, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4726 ok(count == 0, "Expected length 0, got %u\n", count); 4727 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 4728 4729 count = GetTempPathW(MAX_PATH, temp_path); 4730 ok(count, "Failed to get temp path, error %u\n", GetLastError()); 4731 ret = GetTempFileNameW(temp_path, prefix, 0, test_path); 4732 ok(ret != 0, "GetTempFileNameW error %u\n", GetLastError()); 4733 ret = GetLongPathNameW(test_path, long_path, MAX_PATH); 4734 ok(ret != 0, "GetLongPathNameW error %u\n", GetLastError()); 4735 lstrcpyW(dos_path, dos_prefix); 4736 lstrcatW(dos_path, long_path); 4737 4738 file = CreateFileW(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, 4739 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0); 4740 ok(file != INVALID_HANDLE_VALUE, "CreateFileW error %u\n", GetLastError()); 4741 4742 if (0) { 4743 /* Windows crashes on NULL path */ 4744 count = pGetFinalPathNameByHandleW(file, NULL, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4745 ok(count == 0, "Expected length 0, got %u\n", count); 4746 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 4747 } 4748 4749 /* Test 0-length path */ 4750 count = pGetFinalPathNameByHandleW(file, result_path, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4751 ok(count == lstrlenW(dos_path) + 1 || 4752 broken(count == lstrlenW(dos_path) + 2), "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count); 4753 4754 /* Test 0 and NULL path */ 4755 count = pGetFinalPathNameByHandleW(file, NULL, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4756 ok(count == lstrlenW(dos_path) + 1 || 4757 broken(count == lstrlenW(dos_path) + 2), "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count); 4758 4759 /* Test VOLUME_NAME_DOS with sufficient buffer size */ 4760 memset(result_path, 0x11, sizeof(result_path)); 4761 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4762 ok(count == lstrlenW(dos_path), "Expected length %u, got %u\n", lstrlenW(dos_path), count); 4763 ok(lstrcmpiW(dos_path, result_path) == 0, "Expected %s, got %s\n", wine_dbgstr_w(dos_path), wine_dbgstr_w(result_path)); 4764 4765 /* Test VOLUME_NAME_DOS with insufficient buffer size */ 4766 memset(result_path, 0x11, sizeof(result_path)); 4767 count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4768 ok(count == lstrlenW(dos_path) + 1, "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count); 4769 ok(result_path[0] == 0x1111, "Result path was modified\n"); 4770 4771 memset(result_path, 0x11, sizeof(result_path)); 4772 count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4773 ok(count == lstrlenW(dos_path) + 1, "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count); 4774 ok(result_path[0] == 0x1111, "Result path was modified\n"); 4775 4776 memset(result_path, 0x11, sizeof(result_path)); 4777 count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 4778 ok(count == lstrlenW(dos_path), "Expected length %u, got %u\n", lstrlenW(dos_path), count); 4779 ok(result_path[0] != 0x1111, "Result path was not modified\n"); 4780 ok(!result_path[lstrlenW(dos_path)], "Expected nullterminated string\n"); 4781 ok(result_path[lstrlenW(dos_path)+1] == 0x1111, "Buffer overflow\n"); 4782 4783 success = GetVolumePathNameW(long_path, drive_part, MAX_PATH); 4784 ok(success, "GetVolumePathNameW error %u\n", GetLastError()); 4785 success = GetVolumeNameForVolumeMountPointW(drive_part, volume_path, sizeof(volume_path) / sizeof(WCHAR)); 4786 ok(success, "GetVolumeNameForVolumeMountPointW error %u\n", GetLastError()); 4787 4788 /* Test for VOLUME_NAME_GUID */ 4789 lstrcatW(volume_path, long_path + lstrlenW(drive_part)); 4790 memset(result_path, 0x11, sizeof(result_path)); 4791 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_GUID); 4792 ok(count == lstrlenW(volume_path), "Expected length %u, got %u\n", lstrlenW(volume_path), count); 4793 ok(lstrcmpiW(volume_path, result_path) == 0, "Expected %s, got %s\n", 4794 wine_dbgstr_w(volume_path), wine_dbgstr_w(result_path)); 4795 4796 /* Test for VOLUME_NAME_NONE */ 4797 file_part = long_path + lstrlenW(drive_part) - 1; 4798 memset(result_path, 0x11, sizeof(result_path)); 4799 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE); 4800 ok(count == lstrlenW(file_part), "Expected length %u, got %u\n", lstrlenW(file_part), count); 4801 ok(lstrcmpiW(file_part, result_path) == 0, "Expected %s, got %s\n", 4802 wine_dbgstr_w(file_part), wine_dbgstr_w(result_path)); 4803 4804 drive_part[lstrlenW(drive_part)-1] = 0; 4805 success = QueryDosDeviceW(drive_part, nt_path, sizeof(nt_path) / sizeof(WCHAR)); 4806 ok(success, "QueryDosDeviceW error %u\n", GetLastError()); 4807 4808 /* Test for VOLUME_NAME_NT */ 4809 lstrcatW(nt_path, file_part); 4810 memset(result_path, 0x11, sizeof(result_path)); 4811 count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NT); 4812 ok(count == lstrlenW(nt_path), "Expected length %u, got %u\n", lstrlenW(nt_path), count); 4813 ok(lstrcmpiW(nt_path, result_path) == 0, "Expected %s, got %s\n", 4814 wine_dbgstr_w(nt_path), wine_dbgstr_w(result_path)); 4815 4816 CloseHandle(file); 4817 } 4818 4819 static void test_SetFileInformationByHandle(void) 4820 { 4821 FILE_ATTRIBUTE_TAG_INFO fileattrinfo = { 0 }; 4822 FILE_REMOTE_PROTOCOL_INFO protinfo = { 0 }; 4823 FILE_STANDARD_INFO stdinfo = { {{0}},{{0}},0,FALSE,FALSE }; 4824 FILE_COMPRESSION_INFO compressinfo; 4825 FILE_DISPOSITION_INFO dispinfo; 4826 char tempFileName[MAX_PATH]; 4827 char tempPath[MAX_PATH]; 4828 HANDLE file; 4829 BOOL ret; 4830 4831 if (!pSetFileInformationByHandle) 4832 { 4833 win_skip("SetFileInformationByHandle is not supported\n"); 4834 return; 4835 } 4836 4837 ret = GetTempPathA(sizeof(tempPath), tempPath); 4838 ok(ret, "GetTempPathA failed, got error %u.\n", GetLastError()); 4839 4840 /* ensure the existence of a file in the temp folder */ 4841 ret = GetTempFileNameA(tempPath, "abc", 0, tempFileName); 4842 ok(ret, "GetTempFileNameA failed, got error %u.\n", GetLastError()); 4843 4844 file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 4845 NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); 4846 ok(file != INVALID_HANDLE_VALUE, "failed to open the temp file, error %u.\n", GetLastError()); 4847 4848 /* invalid classes */ 4849 SetLastError(0xdeadbeef); 4850 ret = pSetFileInformationByHandle(file, FileStandardInfo, &stdinfo, sizeof(stdinfo)); 4851 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4852 4853 memset(&compressinfo, 0, sizeof(compressinfo)); 4854 SetLastError(0xdeadbeef); 4855 ret = pSetFileInformationByHandle(file, FileCompressionInfo, &compressinfo, sizeof(compressinfo)); 4856 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4857 4858 SetLastError(0xdeadbeef); 4859 ret = pSetFileInformationByHandle(file, FileAttributeTagInfo, &fileattrinfo, sizeof(fileattrinfo)); 4860 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4861 4862 memset(&protinfo, 0, sizeof(protinfo)); 4863 protinfo.StructureVersion = 1; 4864 protinfo.StructureSize = sizeof(protinfo); 4865 SetLastError(0xdeadbeef); 4866 ret = pSetFileInformationByHandle(file, FileRemoteProtocolInfo, &protinfo, sizeof(protinfo)); 4867 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError()); 4868 4869 /* test FileDispositionInfo, additional details already covered by ntdll tests */ 4870 SetLastError(0xdeadbeef); 4871 ret = pSetFileInformationByHandle(file, FileDispositionInfo, &dispinfo, 0); 4872 todo_wine 4873 ok(!ret && GetLastError() == ERROR_BAD_LENGTH, "got %d, error %d\n", ret, GetLastError()); 4874 4875 dispinfo.DeleteFile = TRUE; 4876 ret = pSetFileInformationByHandle(file, FileDispositionInfo, &dispinfo, sizeof(dispinfo)); 4877 ok(ret, "setting FileDispositionInfo failed, error %d\n", GetLastError()); 4878 4879 CloseHandle(file); 4880 } 4881 4882 static void test_GetFileAttributesExW(void) 4883 { 4884 static const WCHAR path1[] = {'\\','\\','?','\\',0}; 4885 static const WCHAR path2[] = {'\\','?','?','\\',0}; 4886 static const WCHAR path3[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0}; 4887 WIN32_FILE_ATTRIBUTE_DATA info; 4888 BOOL ret; 4889 4890 SetLastError(0xdeadbeef); 4891 ret = GetFileAttributesExW(path1, GetFileExInfoStandard, &info); 4892 ok(!ret, "GetFileAttributesExW succeeded\n"); 4893 ok(GetLastError() == ERROR_INVALID_NAME, "Expected error ERROR_INVALID_NAME, got %u\n", GetLastError()); 4894 4895 SetLastError(0xdeadbeef); 4896 ret = GetFileAttributesExW(path2, GetFileExInfoStandard, &info); 4897 ok(!ret, "GetFileAttributesExW succeeded\n"); 4898 ok(GetLastError() == ERROR_INVALID_NAME, "Expected error ERROR_INVALID_NAME, got %u\n", GetLastError()); 4899 4900 SetLastError(0xdeadbeef); 4901 ret = GetFileAttributesExW(path3, GetFileExInfoStandard, &info); 4902 ok(!ret, "GetFileAttributesExW succeeded\n"); 4903 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); 4904 } 4905 4906 START_TEST(file) 4907 { 4908 char temp_path[MAX_PATH]; 4909 DWORD ret; 4910 4911 InitFunctionPointers(); 4912 4913 ret = GetTempPathA(MAX_PATH, temp_path); 4914 ok(ret != 0, "GetTempPath error %u\n", GetLastError()); 4915 ret = GetTempFileNameA(temp_path, "tmp", 0, filename); 4916 ok(ret != 0, "GetTempFileName error %u\n", GetLastError()); 4917 ret = DeleteFileA(filename); 4918 ok(ret != 0, "DeleteFile error %u\n", GetLastError()); 4919 4920 test__hread( ); 4921 test__hwrite( ); 4922 test__lclose( ); 4923 test__lcreat( ); 4924 test__llseek( ); 4925 test__llopen( ); 4926 test__lread( ); 4927 test__lwrite( ); 4928 test_GetTempFileNameA(); 4929 test_CopyFileA(); 4930 test_CopyFileW(); 4931 test_CopyFile2(); 4932 test_CopyFileEx(); 4933 test_CreateFile(); 4934 test_CreateFileA(); 4935 test_CreateFileW(); 4936 test_CreateFile2(); 4937 test_DeleteFileA(); 4938 test_DeleteFileW(); 4939 test_MoveFileA(); 4940 test_MoveFileW(); 4941 test_FindFirstFileA(); 4942 test_FindNextFileA(); 4943 test_FindFirstFile_wildcards(); 4944 test_FindFirstFileExA(FindExInfoStandard, 0, 0); 4945 test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_CASE_SENSITIVE); 4946 test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_LARGE_FETCH); 4947 test_FindFirstFileExA(FindExInfoBasic, 0, 0); 4948 /* FindExLimitToDirectories is ignored if the file system doesn't support directory filtering */ 4949 test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, 0); 4950 test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, FIND_FIRST_EX_CASE_SENSITIVE); 4951 test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, FIND_FIRST_EX_LARGE_FETCH); 4952 test_FindFirstFileExA(FindExInfoBasic, FindExSearchLimitToDirectories, 0); 4953 test_LockFile(); 4954 test_file_sharing(); 4955 test_offset_in_overlapped_structure(); 4956 test_MapFile(); 4957 test_GetFileType(); 4958 test_async_file_errors(); 4959 test_read_write(); 4960 test_OpenFile(); 4961 test_overlapped(); 4962 test_RemoveDirectory(); 4963 test_ReplaceFileA(); 4964 test_ReplaceFileW(); 4965 test_GetFileInformationByHandleEx(); 4966 test_OpenFileById(); 4967 test_SetFileValidData(); 4968 test_WriteFileGather(); 4969 test_file_access(); 4970 test_GetFinalPathNameByHandleA(); 4971 test_GetFinalPathNameByHandleW(); 4972 test_SetFileInformationByHandle(); 4973 test_GetFileAttributesExW(); 4974 } 4975