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