ReactOS  0.4.11-dev-721-g95bc44e
file.c
Go to the documentation of this file.
1 /*
2  * Unit tests for file functions in Wine
3  *
4  * Copyright (c) 2002, 2004 Jakob Eriksson
5  * Copyright (c) 2008 Jeff Zaroyko
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  */
22 
23 #include "precomp.h"
24 
25 #include <time.h>
26 #include <fileapi.h>
27 
28 #undef DeleteFile /* needed for FILE_DISPOSITION_INFO */
29 
31 static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID);
32 static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID);
33 static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT);
34 static BOOL (WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
35 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
36 static BOOL (WINAPI *pGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD);
38 static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
39 static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*);
41 static DWORD (WINAPI *pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
42 static DWORD (WINAPI *pGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
45 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR*);
46 static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
47 static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD);
48 static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
49 static void (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
50 
51 static char filename[MAX_PATH];
52 static const char sillytext[] =
53 "en larvig liten text dx \033 gx hej 84 hej 4484 ! \001\033 bla bl\na.. bla bla."
54 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
55 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
56 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
57 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
58 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
59 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
60 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
61 "1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
62 "sdlkfjasdlkfj a dslkj adsklf \n \nasdklf askldfa sdlkf \nsadklf asdklf asdf ";
63 
64 struct test_list {
65  const char *file; /* file string to test */
66  const DWORD err; /* Win NT and further error code */
67  const LONG err2; /* Win 9x & ME error code or -1 */
68  const DWORD options; /* option flag to use for open */
69  const BOOL todo_flag; /* todo_wine indicator */
70 } ;
71 
72 static void InitFunctionPointers(void)
73 {
74  HMODULE hntdll = GetModuleHandleA("ntdll");
75  HMODULE hkernel32 = GetModuleHandleA("kernel32");
76 
77  pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
78  pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
79  pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
80  pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
81  pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
82 
83  pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA");
84  pReplaceFileA=(void*)GetProcAddress(hkernel32, "ReplaceFileA");
85  pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW");
86  pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA");
87  pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hkernel32, "GetVolumeNameForVolumeMountPointA");
88  pQueueUserAPC = (void *) GetProcAddress(hkernel32, "QueueUserAPC");
89  pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx");
90  pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById");
91  pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
92  pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2");
93  pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2");
94  pGetFinalPathNameByHandleA = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleA");
95  pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW");
96  pSetFileInformationByHandle = (void *) GetProcAddress(hkernel32, "SetFileInformationByHandle");
97 }
98 
99 static void test__hread( void )
100 {
101  HFILE filehandle;
102  char buffer[10000];
103  LONG bytes_read;
104  LONG bytes_wanted;
105  LONG i;
106  BOOL ret;
107 
108  SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL); /* be sure to remove stale files */
110  filehandle = _lcreat( filename, 0 );
111  if (filehandle == HFILE_ERROR)
112  {
113  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
114  return;
115  }
116 
117  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
118 
119  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
120 
121  filehandle = _lopen( filename, OF_READ );
122 
123  ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError( ) );
124 
125  bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
126 
127  ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
128 
129  for (bytes_wanted = 0; bytes_wanted < lstrlenA( sillytext ); bytes_wanted++)
130  {
131  ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
132  ok( _hread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
133  for (i = 0; i < bytes_wanted; i++)
134  {
135  ok( buffer[i] == sillytext[i], "that's not what's written\n" );
136  }
137  }
138 
139  ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
140 
141  ret = DeleteFileA( filename );
142  ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
143 }
144 
145 
146 static void test__hwrite( void )
147 {
148  HFILE filehandle;
149  char buffer[10000];
150  LONG bytes_read;
151  LONG bytes_written;
152  ULONG blocks;
153  LONG i;
154  char *contents;
155  HLOCAL memory_object;
156  char checksum[1];
157  BOOL ret;
158 
159  filehandle = _lcreat( filename, 0 );
160  if (filehandle == HFILE_ERROR)
161  {
162  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
163  return;
164  }
165 
166  ok( HFILE_ERROR != _hwrite( filehandle, "", 0 ), "_hwrite complains\n" );
167 
168  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
169 
170  filehandle = _lopen( filename, OF_READ );
171 
172  bytes_read = _hread( filehandle, buffer, 1);
173 
174  ok( 0 == bytes_read, "file read size error\n" );
175 
176  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
177 
178  filehandle = _lopen( filename, OF_READWRITE );
179 
180  bytes_written = 0;
181  checksum[0] = '\0';
182  srand( (unsigned)time( NULL ) );
183  for (blocks = 0; blocks < 100; blocks++)
184  {
185  for (i = 0; i < (LONG)sizeof( buffer ); i++)
186  {
187  buffer[i] = rand( );
188  checksum[0] = checksum[0] + buffer[i];
189  }
190  ok( HFILE_ERROR != _hwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
191  bytes_written = bytes_written + sizeof( buffer );
192  }
193 
194  ok( HFILE_ERROR != _hwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
195  bytes_written++;
196 
197  ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
198 
199  memory_object = LocalAlloc( LPTR, bytes_written );
200 
201  ok( 0 != memory_object, "LocalAlloc fails. (Could be out of memory.)\n" );
202 
203  contents = LocalLock( memory_object );
204  ok( NULL != contents, "LocalLock whines\n" );
205 
206  filehandle = _lopen( filename, OF_READ );
207 
208  contents = LocalLock( memory_object );
209  ok( NULL != contents, "LocalLock whines\n" );
210 
211  ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
212 
213  checksum[0] = '\0';
214  i = 0;
215  do
216  {
217  checksum[0] = checksum[0] + contents[i];
218  i++;
219  }
220  while (i < bytes_written - 1);
221 
222  ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
223 
224  ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
225 
226  ret = DeleteFileA( filename );
227  ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
228 
229  LocalFree( contents );
230 }
231 
232 
233 static void test__lclose( void )
234 {
235  HFILE filehandle;
236  BOOL ret;
237 
238  filehandle = _lcreat( filename, 0 );
239  if (filehandle == HFILE_ERROR)
240  {
241  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
242  return;
243  }
244 
245  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
246 
247  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
248 
249  ret = DeleteFileA( filename );
250  ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
251 }
252 
253 /* helper function for test__lcreat */
254 static void get_nt_pathW( const char *name, UNICODE_STRING *nameW )
255 {
259  BOOLEAN ret;
260 
261  pRtlInitAnsiString( &str, name );
262 
263  status = pRtlAnsiStringToUnicodeString( &strW, &str, TRUE );
264  ok( !status, "RtlAnsiStringToUnicodeString failed with %08x\n", status );
265 
266  ret = pRtlDosPathNameToNtPathName_U( strW.Buffer, nameW, NULL, NULL );
267  ok( ret, "RtlDosPathNameToNtPathName_U failed\n" );
268 
269  pRtlFreeUnicodeString( &strW );
270 }
271 
272 static void test__lcreat( void )
273 {
277  HFILE filehandle;
278  char buffer[10000];
279  WIN32_FIND_DATAA search_results;
280  char slashname[] = "testfi/";
281  int err;
282  HANDLE find, file;
284  BOOL ret;
285 
286  filehandle = _lcreat( filename, 0 );
287  if (filehandle == HFILE_ERROR)
288  {
289  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
290  return;
291  }
292 
293  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
294 
295  ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
296 
297  ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
298 
299  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
300 
301  find = FindFirstFileA( filename, &search_results );
302  ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
303  FindClose( find );
304 
305  ret = DeleteFileA(filename);
306  ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError());
307 
308  filehandle = _lcreat( filename, 1 ); /* readonly */
309  ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
310 
311  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write never the less\n" );
312 
313  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
314 
315  find = FindFirstFileA( filename, &search_results );
316  ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
317  FindClose( find );
318 
319  SetLastError( 0xdeadbeef );
320  ok( 0 == DeleteFileA( filename ), "shouldn't be able to delete a readonly file\n" );
321  ok( GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError() );
322 
323  ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
324 
325  ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file!\n" );
326 
327  filehandle = _lcreat( filename, 1 ); /* readonly */
328  ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError() );
329  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen(sillytext) ),
330  "_hwrite shouldn't be able to write never the less\n" );
331  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
332 
333  find = FindFirstFileA( filename, &search_results );
334  ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
335  FindClose( find );
336 
337  get_nt_pathW( filename, &filenameW );
338  attr.Length = sizeof(attr);
339  attr.RootDirectory = 0;
341  attr.ObjectName = &filenameW;
342  attr.SecurityDescriptor = NULL;
344 
345  status = pNtCreateFile( &file, GENERIC_READ | GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
348  ok( status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %08x\n", status );
349  ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
350 
351  status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
354  ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
355 
356  status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
359  ok( status == STATUS_NOT_A_DIRECTORY, "expected STATUS_NOT_A_DIRECTORY, got %08x\n", status );
360 
361  status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
364  todo_wine
365  ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
366  if (!status) CloseHandle( file );
367 
368  pRtlFreeUnicodeString( &filenameW );
369 
370  todo_wine
371  ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
372  todo_wine
373  ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
374  todo_wine
375  ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file\n" );
376 
377  filehandle = _lcreat( filename, 2 );
378  ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
379 
380  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
381 
382  ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
383 
384  ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
385 
386  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
387 
388  find = FindFirstFileA( filename, &search_results );
389  ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" );
390  FindClose( find );
391 
392  ret = DeleteFileA( filename );
393  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
394 
395  filehandle = _lcreat( filename, 4 ); /* SYSTEM file */
396  ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
397 
398  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
399 
400  ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
401 
402  ok( _hread( filehandle, buffer, strlen( sillytext ) ) == lstrlenA( sillytext ), "erratic _hread return value\n" );
403 
404  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
405 
406  find = FindFirstFileA( filename, &search_results );
407  ok( INVALID_HANDLE_VALUE != find, "should STILL be able to find file\n" );
408  FindClose( find );
409 
410  ret = DeleteFileA( filename );
411  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
412 
413  filehandle=_lcreat (slashname, 0); /* illegal name */
414  if (HFILE_ERROR==filehandle) {
415  err=GetLastError ();
417  "creating file \"%s\" failed with error %d\n", slashname, err);
418  } else { /* only NT succeeds */
419  _lclose(filehandle);
420  find=FindFirstFileA (slashname, &search_results);
421  if (INVALID_HANDLE_VALUE!=find)
422  {
423  ret = FindClose (find);
424  ok (0 != ret, "FindClose complains (%d)\n", GetLastError ());
425  slashname[strlen(slashname)-1]=0;
426  ok (!strcmp (slashname, search_results.cFileName),
427  "found unexpected name \"%s\"\n", search_results.cFileName);
428  ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
429  "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
430  search_results.dwFileAttributes);
431  }
432  ret = DeleteFileA( slashname );
433  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
434  }
435 
436  filehandle=_lcreat (filename, 8); /* illegal attribute */
437  if (HFILE_ERROR==filehandle)
438  ok (0, "couldn't create volume label \"%s\"\n", filename);
439  else {
440  _lclose(filehandle);
441  find=FindFirstFileA (filename, &search_results);
442  if (INVALID_HANDLE_VALUE==find)
443  ok (0, "file \"%s\" not found\n", filename);
444  else {
445  const char *name = strrchr(filename, '\\');
446 
447  if (name) name++;
448  else name = filename;
449 
450  ret = FindClose(find);
451  ok ( 0 != ret, "FindClose complains (%d)\n", GetLastError ());
452  ok (!strcmp (name, search_results.cFileName),
453  "expected \"%s\", got \"%s\"\n", name, search_results.cFileName);
454  search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
455  search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_COMPRESSED;
456  ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
457  "attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
458  search_results.dwFileAttributes);
459  }
460  ret = DeleteFileA( filename );
461  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
462  }
463 }
464 
465 
466 static void test__llseek( void )
467 {
468  INT i;
469  HFILE filehandle;
470  char buffer[1];
471  LONG bytes_read;
472  BOOL ret;
473 
474  filehandle = _lcreat( filename, 0 );
475  if (filehandle == HFILE_ERROR)
476  {
477  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
478  return;
479  }
480 
481  for (i = 0; i < 400; i++)
482  {
483  ok( _hwrite( filehandle, sillytext, strlen( sillytext ) ) != -1, "_hwrite complains\n" );
484  }
485  ok( _llseek( filehandle, 400 * strlen( sillytext ), FILE_CURRENT ) != -1, "should be able to seek\n" );
486  ok( _llseek( filehandle, 27 + 35 * strlen( sillytext ), FILE_BEGIN ) != -1, "should be able to seek\n" );
487 
488  bytes_read = _hread( filehandle, buffer, 1);
489  ok( 1 == bytes_read, "file read size error\n" );
490  ok( buffer[0] == sillytext[27], "_llseek error, it got lost seeking\n" );
491  ok( _llseek( filehandle, -400 * (LONG)strlen( sillytext ), FILE_END ) != -1, "should be able to seek\n" );
492 
493  bytes_read = _hread( filehandle, buffer, 1);
494  ok( 1 == bytes_read, "file read size error\n" );
495  ok( buffer[0] == sillytext[0], "_llseek error, it got lost seeking\n" );
496  ok( _llseek( filehandle, 1000000, FILE_END ) != -1, "should be able to seek past file; poor, poor Windows programmers\n" );
497  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
498 
499  ret = DeleteFileA( filename );
500  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
501 }
502 
503 
504 static void test__llopen( void )
505 {
506  HFILE filehandle;
507  UINT bytes_read;
508  char buffer[10000];
509  BOOL ret;
510 
511  filehandle = _lcreat( filename, 0 );
512  if (filehandle == HFILE_ERROR)
513  {
514  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
515  return;
516  }
517 
518  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
519  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
520 
521  filehandle = _lopen( filename, OF_READ );
522  ok( HFILE_ERROR == _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite shouldn't be able to write!\n" );
523  bytes_read = _hread( filehandle, buffer, strlen( sillytext ) );
524  ok( strlen( sillytext ) == bytes_read, "file read size error\n" );
525  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
526 
527  filehandle = _lopen( filename, OF_READWRITE );
528  bytes_read = _hread( filehandle, buffer, 2 * strlen( sillytext ) );
529  ok( strlen( sillytext ) == bytes_read, "file read size error\n" );
530  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
531  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
532 
533  filehandle = _lopen( filename, OF_WRITE );
534  ok( HFILE_ERROR == _hread( filehandle, buffer, 1 ), "you should only be able to write this file\n" );
535  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite should write just fine\n" );
536  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
537 
538  ret = DeleteFileA( filename );
539  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
540  /* TODO - add tests for the SHARE modes - use two processes to pull this one off */
541 }
542 
543 
544 static void test__lread( void )
545 {
546  HFILE filehandle;
547  char buffer[10000];
548  UINT bytes_read;
549  UINT bytes_wanted;
550  UINT i;
551  BOOL ret;
552 
553  filehandle = _lcreat( filename, 0 );
554  if (filehandle == HFILE_ERROR)
555  {
556  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
557  return;
558  }
559 
560  ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen( sillytext ) ), "_hwrite complains\n" );
561 
562  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
563 
564  filehandle = _lopen( filename, OF_READ );
565 
566  ok( HFILE_ERROR != filehandle, "couldn't open file \"%s\" again (err=%d)\n", filename, GetLastError());
567 
568  bytes_read = _lread( filehandle, buffer, 2 * strlen( sillytext ) );
569 
570  ok( lstrlenA( sillytext ) == bytes_read, "file read size error\n" );
571 
572  for (bytes_wanted = 0; bytes_wanted < strlen( sillytext ); bytes_wanted++)
573  {
574  ok( 0 == _llseek( filehandle, 0, FILE_BEGIN ), "_llseek complains\n" );
575  ok( _lread( filehandle, buffer, bytes_wanted ) == bytes_wanted, "erratic _hread return value\n" );
576  for (i = 0; i < bytes_wanted; i++)
577  {
578  ok( buffer[i] == sillytext[i], "that's not what's written\n" );
579  }
580  }
581 
582  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
583 
584  ret = DeleteFileA( filename );
585  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
586 }
587 
588 
589 static void test__lwrite( void )
590 {
591  HFILE filehandle;
592  char buffer[10000];
593  UINT bytes_read;
594  UINT bytes_written;
595  UINT blocks;
596  INT i;
597  char *contents;
598  HLOCAL memory_object;
599  char checksum[1];
600  BOOL ret;
601 
602  filehandle = _lcreat( filename, 0 );
603  if (filehandle == HFILE_ERROR)
604  {
605  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
606  return;
607  }
608 
609  ok( HFILE_ERROR != _lwrite( filehandle, "", 0 ), "_hwrite complains\n" );
610 
611  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
612 
613  filehandle = _lopen( filename, OF_READ );
614 
615  bytes_read = _hread( filehandle, buffer, 1);
616 
617  ok( 0 == bytes_read, "file read size error\n" );
618 
619  ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
620 
621  filehandle = _lopen( filename, OF_READWRITE );
622 
623  bytes_written = 0;
624  checksum[0] = '\0';
625  srand( (unsigned)time( NULL ) );
626  for (blocks = 0; blocks < 100; blocks++)
627  {
628  for (i = 0; i < (INT)sizeof( buffer ); i++)
629  {
630  buffer[i] = rand( );
631  checksum[0] = checksum[0] + buffer[i];
632  }
633  ok( HFILE_ERROR != _lwrite( filehandle, buffer, sizeof( buffer ) ), "_hwrite complains\n" );
634  bytes_written = bytes_written + sizeof( buffer );
635  }
636 
637  ok( HFILE_ERROR != _lwrite( filehandle, checksum, 1 ), "_hwrite complains\n" );
638  bytes_written++;
639 
640  ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
641 
642  memory_object = LocalAlloc( LPTR, bytes_written );
643 
644  ok( 0 != memory_object, "LocalAlloc fails, could be out of memory\n" );
645 
646  contents = LocalLock( memory_object );
647  ok( NULL != contents, "LocalLock whines\n" );
648 
649  filehandle = _lopen( filename, OF_READ );
650 
651  contents = LocalLock( memory_object );
652  ok( NULL != contents, "LocalLock whines\n" );
653 
654  ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
655 
656  checksum[0] = '\0';
657  i = 0;
658  do
659  {
660  checksum[0] += contents[i];
661  i++;
662  }
663  while (i < bytes_written - 1);
664 
665  ok( checksum[0] == contents[i], "stored checksum differ from computed checksum\n" );
666 
667  ok( HFILE_ERROR != _lclose( filehandle ), "_lclose complains\n" );
668 
669  ret = DeleteFileA( filename );
670  ok( ret, "DeleteFile failed (%d)\n", GetLastError( ) );
671 
672  LocalFree( contents );
673 }
674 
675 static void test_CopyFileA(void)
676 {
677  char temp_path[MAX_PATH];
678  char source[MAX_PATH], dest[MAX_PATH];
679  static const char prefix[] = "pfx";
680  HANDLE hfile;
681  HANDLE hmapfile;
682  FILETIME ft1, ft2;
683  char buf[10];
684  DWORD ret;
685  BOOL retok;
686 
687  ret = GetTempPathA(MAX_PATH, temp_path);
688  ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
689  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
690 
691  ret = GetTempFileNameA(temp_path, prefix, 0, source);
692  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
693 
694  /* copying a file to itself must fail */
695  retok = CopyFileA(source, source, FALSE);
696  ok( !retok && (GetLastError() == ERROR_SHARING_VIOLATION || broken(GetLastError() == ERROR_FILE_EXISTS) /* Win 9x */),
697  "copying a file to itself didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
698 
699  /* make the source have not zero size */
700  hfile = CreateFileA(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
701  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
702  retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL );
703  ok( retok && ret == sizeof(prefix),
704  "WriteFile error %d\n", GetLastError());
705  ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
706  /* get the file time and change it to prove the difference */
707  ret = GetFileTime(hfile, NULL, NULL, &ft1);
708  ok( ret, "GetFileTime error %d\n", GetLastError());
709  ft1.dwLowDateTime -= 600000000; /* 60 second */
710  ret = SetFileTime(hfile, NULL, NULL, &ft1);
711  ok( ret, "SetFileTime error %d\n", GetLastError());
712  GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */
713  CloseHandle(hfile);
714 
715  ret = GetTempFileNameA(temp_path, prefix, 0, dest);
716  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
717 
718  SetLastError(0xdeadbeef);
719  ret = CopyFileA(source, dest, TRUE);
720  ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
721  "CopyFileA: unexpected error %d\n", GetLastError());
722 
723  ret = CopyFileA(source, dest, FALSE);
724  ok(ret, "CopyFileA: error %d\n", GetLastError());
725 
726  /* copying from a read-locked source fails */
727  hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
728  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
729  retok = CopyFileA(source, dest, FALSE);
730  ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
731  "copying from a read-locked file succeeded when it shouldn't have\n");
732  /* in addition, the source is opened before the destination */
733  retok = CopyFileA("25f99d3b-4ba4-4f66-88f5-2906886993cc", dest, FALSE);
734  ok(!retok && GetLastError() == ERROR_FILE_NOT_FOUND,
735  "copying from a file that doesn't exist failed in an unexpected way (ret=%d, err=%d)\n", retok, GetLastError());
736  CloseHandle(hfile);
737 
738  /* copying from a r+w opened, r shared source succeeds */
740  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
741  retok = CopyFileA(source, dest, FALSE);
742  ok(retok,
743  "copying from an r+w opened and r shared file failed (ret=%d, err=%d)\n", retok, GetLastError());
744  CloseHandle(hfile);
745 
746  /* copying from a delete-locked source mostly succeeds */
747  hfile = CreateFileA(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
748  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
749  retok = CopyFileA(source, dest, FALSE);
750  ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* NT, 2000, XP */,
751  "copying from a delete-locked file failed (ret=%d, err=%d)\n", retok, GetLastError());
752  CloseHandle(hfile);
753 
754  /* copying to a write-locked destination fails */
756  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
757  retok = CopyFileA(source, dest, FALSE);
758  ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
759  "copying to a write-locked file didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
760  CloseHandle(hfile);
761 
762  /* copying to a r+w opened, w shared destination mostly succeeds */
764  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
765  retok = CopyFileA(source, dest, FALSE);
766  ok(retok || broken(!retok && GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */,
767  "copying to a r+w opened and w shared file failed (ret=%d, err=%d)\n", retok, GetLastError());
768  CloseHandle(hfile);
769 
770  /* copying to a delete-locked destination fails, even when the destination is delete-shared */
772  ok(hfile != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* Win 9x */,
773  "failed to open destination file, error %d\n", GetLastError());
774  if (hfile != INVALID_HANDLE_VALUE)
775  {
776  retok = CopyFileA(source, dest, FALSE);
777  ok(!retok && GetLastError() == ERROR_SHARING_VIOLATION,
778  "copying to a delete-locked shared file didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
779  CloseHandle(hfile);
780  }
781 
782  /* copy to a file that's opened the way Wine opens the source */
784  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
785  retok = CopyFileA(source, dest, FALSE);
786  ok(retok || broken(GetLastError() == ERROR_SHARING_VIOLATION) /* Win 9x */,
787  "copying to a file opened the way Wine opens the source failed (ret=%d, err=%d)\n", retok, GetLastError());
788  CloseHandle(hfile);
789 
790  /* make sure that destination has correct size */
792  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
793  ret = GetFileSize(hfile, NULL);
794  ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
795 
796  /* make sure that destination has the same filetime */
797  ret = GetFileTime(hfile, NULL, NULL, &ft2);
798  ok( ret, "GetFileTime error %d\n", GetLastError());
799  ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
800 
801  SetLastError(0xdeadbeef);
802  ret = CopyFileA(source, dest, FALSE);
804  "CopyFileA: ret = %d, unexpected error %d\n", ret, GetLastError());
805 
806  /* make sure that destination still has correct size */
807  ret = GetFileSize(hfile, NULL);
808  ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
809  retok = ReadFile(hfile, buf, sizeof(buf), &ret, NULL);
810  ok( retok && ret == sizeof(prefix),
811  "ReadFile: error %d\n", GetLastError());
812  ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
813 
814  /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
815  hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
816  ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
817 
818  ret = CopyFileA(source, dest, FALSE);
820  "CopyFileA with mapped dest file: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
821 
822  CloseHandle(hmapfile);
823  CloseHandle(hfile);
824 
826  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
827 
828  /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
829  hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
830  ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
831 
832  ret = CopyFileA(source, dest, FALSE);
833  ok(!ret, "CopyFileA: expected failure\n");
835  broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x */
836  "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
837 
838  CloseHandle(hmapfile);
839  CloseHandle(hfile);
840 
841  ret = DeleteFileA(source);
842  ok(ret, "DeleteFileA: error %d\n", GetLastError());
843  ret = DeleteFileA(dest);
844  ok(ret, "DeleteFileA: error %d\n", GetLastError());
845 }
846 
847 static void test_CopyFileW(void)
848 {
849  WCHAR temp_path[MAX_PATH];
851  static const WCHAR prefix[] = {'p','f','x',0};
852  DWORD ret;
853 
854  ret = GetTempPathW(MAX_PATH, temp_path);
855  if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
856  {
857  win_skip("GetTempPathW is not available\n");
858  return;
859  }
860  ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
861  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
862 
863  ret = GetTempFileNameW(temp_path, prefix, 0, source);
864  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
865 
866  ret = GetTempFileNameW(temp_path, prefix, 0, dest);
867  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
868 
869  ret = CopyFileW(source, dest, TRUE);
870  ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
871  "CopyFileW: unexpected error %d\n", GetLastError());
872 
873  ret = CopyFileW(source, dest, FALSE);
874  ok(ret, "CopyFileW: error %d\n", GetLastError());
875 
876  ret = DeleteFileW(source);
877  ok(ret, "DeleteFileW: error %d\n", GetLastError());
878  ret = DeleteFileW(dest);
879  ok(ret, "DeleteFileW: error %d\n", GetLastError());
880 }
881 
882 static void test_CopyFile2(void)
883 {
884  static const WCHAR doesntexistW[] = {'d','o','e','s','n','t','e','x','i','s','t',0};
885  static const WCHAR prefix[] = {'p','f','x',0};
886  WCHAR source[MAX_PATH], dest[MAX_PATH], temp_path[MAX_PATH];
887  COPYFILE2_EXTENDED_PARAMETERS params;
888  HANDLE hfile, hmapfile;
889  FILETIME ft1, ft2;
890  DWORD ret, len;
891  char buf[10];
892  HRESULT hr;
893 
894  if (!pCopyFile2)
895  {
896  skip("CopyFile2 is not available\n");
897  return;
898  }
899 
900  ret = GetTempPathW(MAX_PATH, temp_path);
901  ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
902  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
903 
904  ret = GetTempFileNameW(temp_path, prefix, 0, source);
905  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
906 
907  ret = GetTempFileNameW(temp_path, prefix, 0, dest);
908  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
909 
910  /* fail if exists */
911  memset(&params, 0, sizeof(params));
912  params.dwSize = sizeof(params);
913  params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
914 
915  SetLastError(0xdeadbeef);
916  hr = pCopyFile2(source, dest, &params);
917  ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
918  ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
919 
920  /* don't fail if exists */
921  params.dwSize = sizeof(params);
922  params.dwCopyFlags = 0;
923 
924  hr = pCopyFile2(source, dest, &params);
925  ok(hr == S_OK, "CopyFile2: error 0x%08x\n", hr);
926 
927  /* copying a file to itself must fail */
928  params.dwSize = sizeof(params);
929  params.dwCopyFlags = 0;
930 
931  SetLastError(0xdeadbeef);
932  hr = pCopyFile2(source, source, &params);
933  ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: copying a file to itself didn't fail, 0x%08x\n", hr);
934  ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
935 
936  /* make the source have not zero size */
937  hfile = CreateFileW(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
938  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
939  ret = WriteFile(hfile, prefix, sizeof(prefix), &len, NULL );
940  ok(ret && len == sizeof(prefix), "WriteFile error %d\n", GetLastError());
941  ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
942 
943  /* get the file time and change it to prove the difference */
944  ret = GetFileTime(hfile, NULL, NULL, &ft1);
945  ok(ret, "GetFileTime error %d\n", GetLastError());
946  ft1.dwLowDateTime -= 600000000; /* 60 second */
947  ret = SetFileTime(hfile, NULL, NULL, &ft1);
948  ok(ret, "SetFileTime error %d\n", GetLastError());
949  GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */
950  CloseHandle(hfile);
951 
952  ret = GetTempFileNameW(temp_path, prefix, 0, dest);
953  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
954 
955  params.dwSize = sizeof(params);
956  params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
957 
958  SetLastError(0xdeadbeef);
959  hr = pCopyFile2(source, dest, &params);
960  ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
961  ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
962 
963  params.dwSize = sizeof(params);
964  params.dwCopyFlags = 0;
965  hr = pCopyFile2(source, dest, &params);
966  ok(ret, "CopyFile2: error 0x%08x\n", hr);
967 
968  /* copying from a read-locked source fails */
969  hfile = CreateFileW(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
970  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
971 
972  params.dwSize = sizeof(params);
973  params.dwCopyFlags = 0;
974  SetLastError(0xdeadbeef);
975  hr = pCopyFile2(source, dest, &params);
976  ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
977  ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
978 
979  /* in addition, the source is opened before the destination */
980  params.dwSize = sizeof(params);
981  params.dwCopyFlags = 0;
982  SetLastError(0xdeadbeef);
983  hr = pCopyFile2(doesntexistW, dest, &params);
984  ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
985  ok(GetLastError() == ERROR_FILE_NOT_FOUND, "CopyFile2: last error %d\n", GetLastError());
986  CloseHandle(hfile);
987 
988  /* copying from a r+w opened, r shared source succeeds */
990  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
991 
992  params.dwSize = sizeof(params);
993  params.dwCopyFlags = 0;
994  hr = pCopyFile2(source, dest, &params);
995  ok(hr == S_OK, "failed 0x%08x\n", hr);
996  CloseHandle(hfile);
997 
998  /* copying from a delete-locked source mostly succeeds */
999  hfile = CreateFileW(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1000  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
1001 
1002  params.dwSize = sizeof(params);
1003  params.dwCopyFlags = 0;
1004  hr = pCopyFile2(source, dest, &params);
1005  ok(hr == S_OK, "failed 0x%08x\n", hr);
1006  CloseHandle(hfile);
1007 
1008  /* copying to a write-locked destination fails */
1010  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1011 
1012  params.dwSize = sizeof(params);
1013  params.dwCopyFlags = 0;
1014  SetLastError(0xdeadbeef);
1015  hr = pCopyFile2(source, dest, FALSE);
1016  ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1017  ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1018  CloseHandle(hfile);
1019 
1020  /* copying to a r+w opened, w shared destination mostly succeeds */
1022  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1023 
1024  params.dwSize = sizeof(params);
1025  params.dwCopyFlags = 0;
1026  hr = pCopyFile2(source, dest, FALSE);
1027  ok(hr == S_OK, "got 0x%08x\n", hr);
1028  CloseHandle(hfile);
1029 
1030  /* copying to a delete-locked destination fails, even when the destination is delete-shared */
1032  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1033 
1034  params.dwSize = sizeof(params);
1035  params.dwCopyFlags = 0;
1036  SetLastError(0xdeadbeef);
1037  hr = pCopyFile2(source, dest, &params);
1038  ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1039  ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1040  CloseHandle(hfile);
1041 
1042  /* copy to a file that's opened the way Wine opens the source */
1044  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1045 
1046  params.dwSize = sizeof(params);
1047  params.dwCopyFlags = 0;
1048  hr = pCopyFile2(source, dest, &params);
1049  ok(hr == S_OK, "got 0x%08x\n", hr);
1050  CloseHandle(hfile);
1051 
1052  /* make sure that destination has correct size */
1053  hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1054  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
1055  ret = GetFileSize(hfile, NULL);
1056  ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
1057 
1058  /* make sure that destination has the same filetime */
1059  ret = GetFileTime(hfile, NULL, NULL, &ft2);
1060  ok(ret, "GetFileTime error %d\n", GetLastError());
1061  ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
1062 
1063  params.dwSize = sizeof(params);
1064  params.dwCopyFlags = 0;
1065  SetLastError(0xdeadbeef);
1066  hr = pCopyFile2(source, dest, &params);
1067  ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1068  ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1069 
1070  /* make sure that destination still has correct size */
1071  ret = GetFileSize(hfile, NULL);
1072  ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
1073  ret = ReadFile(hfile, buf, sizeof(buf), &len, NULL);
1074  ok(ret && len == sizeof(prefix), "ReadFile: error %d\n", GetLastError());
1075  ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
1076 
1077  /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
1078  hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1079  ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1080 
1081  params.dwSize = sizeof(params);
1082  params.dwCopyFlags = 0;
1083  SetLastError(0xdeadbeef);
1084  hr = pCopyFile2(source, dest, &params);
1085  ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
1086  ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
1087 
1088  CloseHandle(hmapfile);
1089  CloseHandle(hfile);
1090 
1092  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
1093 
1094  /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
1095  hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1096  ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1097 
1098  params.dwSize = sizeof(params);
1099  params.dwCopyFlags = 0;
1100  hr = pCopyFile2(source, dest, &params);
1101  ok(hr == HRESULT_FROM_WIN32(ERROR_USER_MAPPED_FILE), "CopyFile2: unexpected error 0x%08x\n", hr);
1102  ok(GetLastError() == ERROR_USER_MAPPED_FILE, "CopyFile2: last error %d\n", GetLastError());
1103 
1104  CloseHandle(hmapfile);
1105  CloseHandle(hfile);
1106 
1107  DeleteFileW(source);
1108  DeleteFileW(dest);
1109 }
1110 
1111 static DWORD WINAPI copy_progress_cb(LARGE_INTEGER total_size, LARGE_INTEGER total_transferred,
1112  LARGE_INTEGER stream_size, LARGE_INTEGER stream_transferred,
1114 {
1115  ok(reason == CALLBACK_STREAM_SWITCH, "expected CALLBACK_STREAM_SWITCH, got %u\n", reason);
1116  CloseHandle(userdata);
1117  return PROGRESS_CANCEL;
1118 }
1119 
1120 static void test_CopyFileEx(void)
1121 {
1122  char temp_path[MAX_PATH];
1123  char source[MAX_PATH], dest[MAX_PATH];
1124  static const char prefix[] = "pfx";
1125  HANDLE hfile;
1126  DWORD ret;
1127  BOOL retok;
1128 
1129  ret = GetTempPathA(MAX_PATH, temp_path);
1130  ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1131  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1132 
1133  ret = GetTempFileNameA(temp_path, prefix, 0, source);
1134  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1135 
1136  ret = GetTempFileNameA(temp_path, prefix, 0, dest);
1137  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1138 
1140  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1141  SetLastError(0xdeadbeef);
1142  retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
1143  ok(!retok, "CopyFileExA unexpectedly succeeded\n");
1144  ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError());
1145  ok(GetFileAttributesA(dest) != INVALID_FILE_ATTRIBUTES, "file was deleted\n");
1146 
1148  NULL, OPEN_EXISTING, 0, 0);
1149  ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
1150  SetLastError(0xdeadbeef);
1151  retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
1152  ok(!retok, "CopyFileExA unexpectedly succeeded\n");
1153  ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError());
1154  ok(GetFileAttributesA(dest) == INVALID_FILE_ATTRIBUTES, "file was not deleted\n");
1155 
1156  ret = DeleteFileA(source);
1157  ok(ret, "DeleteFileA failed with error %d\n", GetLastError());
1158  ret = DeleteFileA(dest);
1159  ok(!ret, "DeleteFileA unexpectedly succeeded\n");
1160 }
1161 
1162 /*
1163  * Debugging routine to dump a buffer in a hexdump-like fashion.
1164  */
1165 static void dumpmem(unsigned char *mem, int len)
1166 {
1167  int x = 0;
1168  char hex[49], *p;
1169  char txt[17], *c;
1170 
1171  while (x < len)
1172  {
1173  p = hex;
1174  c = txt;
1175  do {
1176  p += sprintf(p, "%02x ", mem[x]);
1177  *c++ = (mem[x] >= 32 && mem[x] <= 127) ? mem[x] : '.';
1178  } while (++x % 16 && x < len);
1179  *c = '\0';
1180  trace("%04x: %-48s- %s\n", x, hex, txt);
1181  }
1182 }
1183 
1184 static void test_CreateFileA(void)
1185 {
1186  HANDLE hFile;
1187  char temp_path[MAX_PATH], dirname[MAX_PATH];
1188  char filename[MAX_PATH];
1189  static const char prefix[] = "pfx";
1190  char windowsdir[MAX_PATH];
1191  char Volume_1[MAX_PATH];
1192  unsigned char buffer[512];
1193  char directory[] = "removeme";
1194  static const char nt_drive[] = "\\\\?\\A:";
1195  DWORD i, ret, len;
1196  static const struct test_list p[] =
1197  {
1198  {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dir as file w \ */
1199  {"", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* dir as dir w \ */
1200  {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */
1201  {"a\\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */
1202  {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */
1203  {"removeme\\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exst dir w \ */
1204  {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */
1205  {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */
1206  {"c:\\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */
1207  {"c:\\", ERROR_SUCCESS, ERROR_ACCESS_DENIED, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* root dir w \ as dir */
1208  {"c:c:\\windows", ERROR_INVALID_NAME, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* invalid path */
1209  {"\\\\?\\c:", ERROR_SUCCESS, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL,FALSE }, /* dev namespace drive */
1210  {"\\\\?\\c:\\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dev namespace drive w \ */
1211  {NULL, 0, -1, 0, FALSE}
1212  };
1214  WCHAR curdir[MAX_PATH];
1215 
1216  ret = GetTempPathA(MAX_PATH, temp_path);
1217  ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1218  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1219 
1220  ret = GetTempFileNameA(temp_path, prefix, 0, filename);
1221  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1222 
1223  SetLastError(0xdeadbeef);
1224  hFile = CreateFileA(filename, GENERIC_READ, 0, NULL,
1227  "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1228 
1229  SetLastError(0xdeadbeef);
1230  hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1233  "hFile %p, last error %u\n", hFile, GetLastError());
1234 
1235  CloseHandle(hFile);
1236 
1237  SetLastError(0xdeadbeef);
1238  hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1241  "hFile %p, last error %u\n", hFile, GetLastError());
1242 
1243  CloseHandle(hFile);
1244 
1245  ret = DeleteFileA(filename);
1246  ok(ret, "DeleteFileA: error %d\n", GetLastError());
1247 
1248  SetLastError(0xdeadbeef);
1249  hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1251  ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1252  "hFile %p, last error %u\n", hFile, GetLastError());
1253 
1254  CloseHandle(hFile);
1255 
1256  ret = DeleteFileA(filename);
1257  ok(ret, "DeleteFileA: error %d\n", GetLastError());
1258 
1259  SetLastError(0xdeadbeef);
1261  ok(hFile == INVALID_HANDLE_VALUE, "hFile should have been INVALID_HANDLE_VALUE\n");
1263  broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */
1264  "LastError should have been ERROR_INVALID_NAME or ERROR_FILE_NOT_FOUND but got %u\n", GetLastError());
1265 
1266  /* get windows drive letter */
1267  ret = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
1268  ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
1269  ok(ret != 0, "GetWindowsDirectory: error %d\n", GetLastError());
1270 
1271  /* test error return codes from CreateFile for some cases */
1272  ret = GetTempPathA(MAX_PATH, temp_path);
1273  ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1274  strcpy(dirname, temp_path);
1275  strcat(dirname, directory);
1276  ret = CreateDirectoryA(dirname, NULL);
1277  ok( ret, "Createdirectory failed, gle=%d\n", GetLastError() );
1278  /* set current drive & directory to known location */
1279  GetCurrentDirectoryW( MAX_PATH, curdir);
1280  SetCurrentDirectoryA( temp_path );
1281  i = 0;
1282  while (p[i].file)
1283  {
1284  filename[0] = 0;
1285  /* update the drive id in the table entry with the current one */
1286  if (p[i].file[1] == ':')
1287  {
1288  strcpy(filename, p[i].file);
1289  filename[0] = windowsdir[0];
1290  }
1291  else if (p[i].file[0] == '\\' && p[i].file[5] == ':')
1292  {
1293  strcpy(filename, p[i].file);
1294  filename[4] = windowsdir[0];
1295  }
1296  else
1297  {
1298  /* prefix the table entry with the current temp directory */
1299  strcpy(filename, temp_path);
1300  strcat(filename, p[i].file);
1301  }
1302  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1305  p[i].options, NULL );
1306  /* if we get ACCESS_DENIED when we do not expect it, assume
1307  * no access to the volume
1308  */
1309  if (hFile == INVALID_HANDLE_VALUE &&
1311  p[i].err != ERROR_ACCESS_DENIED)
1312  {
1313  if (p[i].todo_flag)
1314  skip("Either no authority to volume, or is todo_wine for %s err=%d should be %d\n", filename, GetLastError(), p[i].err);
1315  else
1316  skip("Do not have authority to access volumes. Test for %s skipped\n", filename);
1317  }
1318  /* otherwise validate results with expectations */
1319  else
1320  {
1321  todo_wine_if (p[i].todo_flag)
1322  ok((hFile == INVALID_HANDLE_VALUE &&
1323  (p[i].err == GetLastError() || p[i].err2 == GetLastError())) ||
1324  (hFile != INVALID_HANDLE_VALUE && p[i].err == ERROR_SUCCESS),
1325  "CreateFileA failed on %s, hFile %p, err=%u, should be %u\n",
1326  filename, hFile, GetLastError(), p[i].err);
1327  }
1328  if (hFile != INVALID_HANDLE_VALUE)
1329  CloseHandle( hFile );
1330  i++;
1331  }
1332  ret = RemoveDirectoryA(dirname);
1333  ok(ret, "RemoveDirectoryA: error %d\n", GetLastError());
1334  SetCurrentDirectoryW(curdir);
1335 
1336  /* test opening directory as a directory */
1337  hFile = CreateFileA( temp_path, GENERIC_READ,
1339  NULL,
1340  OPEN_EXISTING,
1343  {
1345  "CreateFileA did not work, last error %u on volume <%s>\n",
1346  GetLastError(), temp_path );
1347 
1348  if (hFile != INVALID_HANDLE_VALUE)
1349  {
1350  ret = GetFileInformationByHandle( hFile, &Finfo );
1351  if (ret)
1352  {
1354  "CreateFileA probably did not open temp directory %s correctly\n file information does not include FILE_ATTRIBUTE_DIRECTORY, actual=0x%08x\n",
1355  temp_path, Finfo.dwFileAttributes);
1356  }
1357  CloseHandle( hFile );
1358  }
1359  }
1360  else
1361  skip("Probable Win9x, got ERROR_PATH_NOT_FOUND w/ FILE_FLAG_BACKUP_SEMANTICS or %s\n", temp_path);
1362 
1363 
1364  /* *** Test opening volumes/devices using drive letter *** */
1365 
1366  /* test using drive letter in non-rewrite format without trailing \ */
1367  /* this should work */
1368  strcpy(filename, nt_drive);
1369  filename[4] = windowsdir[0];
1370  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1374  if (hFile != INVALID_HANDLE_VALUE ||
1376  {
1377  /* if we have adm rights to volume, then try rest of tests */
1378  ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1379  filename, GetLastError());
1380  if (hFile != INVALID_HANDLE_VALUE)
1381  {
1382  /* if we opened the volume/device, try to read it. Since it */
1383  /* opened, we should be able to read it. We don't care about*/
1384  /* what the data is at this time. */
1385  len = 512;
1386  ret = ReadFile( hFile, buffer, len, &len, NULL );
1387  todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n",
1388  GetLastError(), ret, filename);
1389  if (ret)
1390  {
1391  trace("buffer is\n");
1392  dumpmem(buffer, 64);
1393  }
1394  CloseHandle( hFile );
1395  }
1396 
1397  /* test using drive letter with trailing \ and in non-rewrite */
1398  /* this should not work */
1399  strcpy(filename, nt_drive);
1400  filename[4] = windowsdir[0];
1401  strcat( filename, "\\" );
1402  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1406  todo_wine
1408  "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n",
1409  filename, GetLastError());
1410  if (hFile != INVALID_HANDLE_VALUE)
1411  CloseHandle( hFile );
1412 
1413  /* test using temp path with trailing \ and in non-rewrite as dir */
1414  /* this should work */
1415  strcpy(filename, nt_drive);
1416  filename[4] = 0;
1417  strcat( filename, temp_path );
1418  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1422  ok(hFile != INVALID_HANDLE_VALUE,
1423  "CreateFileA should have worked on %s, but got %u\n",
1424  filename, GetLastError());
1425  if (hFile != INVALID_HANDLE_VALUE)
1426  CloseHandle( hFile );
1427 
1428  /* test using drive letter without trailing \ and in device ns */
1429  /* this should work */
1430  strcpy(filename, nt_drive);
1431  filename[4] = windowsdir[0];
1432  filename[2] = '.';
1433  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1437  ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1438  filename, GetLastError());
1439  if (hFile != INVALID_HANDLE_VALUE)
1440  CloseHandle( hFile );
1441  }
1442  /* If we see ERROR_BAD_NETPATH then on Win9x or WinME, so skip */
1443  else if (GetLastError() == ERROR_BAD_NETPATH)
1444  skip("Probable Win9x, got ERROR_BAD_NETPATH (53)\n");
1445  else
1446  skip("Do not have authority to access volumes. Tests skipped\n");
1447 
1448 
1449  /* *** Test opening volumes/devices using GUID *** */
1450 
1451  if (pGetVolumeNameForVolumeMountPointA)
1452  {
1453  strcpy(filename, "c:\\");
1454  filename[0] = windowsdir[0];
1455  ret = pGetVolumeNameForVolumeMountPointA( filename, Volume_1, MAX_PATH );
1456  ok(ret, "GetVolumeNameForVolumeMountPointA failed, for %s, last error=%d\n", filename, GetLastError());
1457  if (ret)
1458  {
1459  ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name <%s>\n", Volume_1);
1460 
1461  /* test the result of opening a unique volume name (GUID)
1462  * with the trailing \
1463  * this should error out
1464  */
1465  strcpy(filename, Volume_1);
1466  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1470  todo_wine
1471  ok(hFile == INVALID_HANDLE_VALUE,
1472  "CreateFileA should not have opened %s, hFile %p\n",
1473  filename, hFile);
1474  todo_wine
1476  "CreateFileA should have returned ERROR_PATH_NOT_FOUND on %s, but got %u\n",
1477  filename, GetLastError());
1478  if (hFile != INVALID_HANDLE_VALUE)
1479  CloseHandle( hFile );
1480 
1481  /* test the result of opening a unique volume name (GUID)
1482  * with the temp path string as dir
1483  * this should work
1484  */
1485  strcpy(filename, Volume_1);
1486  strcat(filename, temp_path+3);
1487  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1491  todo_wine
1492  ok(hFile != INVALID_HANDLE_VALUE,
1493  "CreateFileA should have opened %s, but got %u\n",
1494  filename, GetLastError());
1495  if (hFile != INVALID_HANDLE_VALUE)
1496  CloseHandle( hFile );
1497 
1498  /* test the result of opening a unique volume name (GUID)
1499  * without the trailing \ and in device namespace
1500  * this should work
1501  */
1502  strcpy(filename, Volume_1);
1503  filename[2] = '.';
1504  filename[48] = 0;
1505  hFile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
1510  {
1511  /* if we have adm rights to volume, then try rest of tests */
1512  ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA did not open %s, last error=%u\n",
1513  filename, GetLastError());
1514  if (hFile != INVALID_HANDLE_VALUE)
1515  {
1516  /* if we opened the volume/device, try to read it. Since it */
1517  /* opened, we should be able to read it. We don't care about*/
1518  /* what the data is at this time. */
1519  len = 512;
1520  ret = ReadFile( hFile, buffer, len, &len, NULL );
1521  todo_wine ok(ret, "Failed to read volume, last error %u, %u, for %s\n",
1522  GetLastError(), ret, filename);
1523  if (ret)
1524  {
1525  trace("buffer is\n");
1526  dumpmem(buffer, 64);
1527  }
1528  CloseHandle( hFile );
1529  }
1530  }
1531  else
1532  skip("Do not have authority to access volumes. Tests skipped\n");
1533  }
1534  else
1535  win_skip("GetVolumeNameForVolumeMountPointA not functioning\n");
1536  }
1537  else
1538  win_skip("GetVolumeNameForVolumeMountPointA not found\n");
1539 }
1540 
1541 static void test_CreateFileW(void)
1542 {
1543  HANDLE hFile;
1544  WCHAR temp_path[MAX_PATH];
1546  static const WCHAR emptyW[]={'\0'};
1547  static const WCHAR prefix[] = {'p','f','x',0};
1548  static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
1549  DWORD ret;
1550 
1551  ret = GetTempPathW(MAX_PATH, temp_path);
1552  if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1553  {
1554  win_skip("GetTempPathW is not available\n");
1555  return;
1556  }
1557  ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1558  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1559 
1560  ret = GetTempFileNameW(temp_path, prefix, 0, filename);
1561  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1562 
1563  SetLastError(0xdeadbeef);
1564  hFile = CreateFileW(filename, GENERIC_READ, 0, NULL,
1567  "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1568 
1569  SetLastError(0xdeadbeef);
1570  hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1573  "hFile %p, last error %u\n", hFile, GetLastError());
1574 
1575  CloseHandle(hFile);
1576 
1577  SetLastError(0xdeadbeef);
1578  hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1581  "hFile %p, last error %u\n", hFile, GetLastError());
1582 
1583  CloseHandle(hFile);
1584 
1585  ret = DeleteFileW(filename);
1586  ok(ret, "DeleteFileW: error %d\n", GetLastError());
1587 
1588  SetLastError(0xdeadbeef);
1589  hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
1591  ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1592  "hFile %p, last error %u\n", hFile, GetLastError());
1593 
1594  CloseHandle(hFile);
1595 
1596  ret = DeleteFileW(filename);
1597  ok(ret, "DeleteFileW: error %d\n", GetLastError());
1598 
1599  if (0)
1600  {
1601  /* this crashes on NT4.0 */
1602  hFile = CreateFileW(NULL, GENERIC_READ, 0, NULL,
1605  "CreateFileW(NULL) returned ret=%p error=%u\n",hFile,GetLastError());
1606  }
1607 
1608  hFile = CreateFileW(emptyW, GENERIC_READ, 0, NULL,
1611  "CreateFileW(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
1612 
1613  /* test the result of opening a nonexistent driver name */
1614  hFile = CreateFileW(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1617  "CreateFileW on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
1618 
1619  ret = CreateDirectoryW(filename, NULL);
1620  ok(ret == TRUE, "couldn't create temporary directory\n");
1621  hFile = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1623  ok(hFile != INVALID_HANDLE_VALUE,
1624  "expected CreateFile to succeed on existing directory, error: %d\n", GetLastError());
1625  CloseHandle(hFile);
1626  ret = RemoveDirectoryW(filename);
1627  ok(ret, "DeleteFileW: error %d\n", GetLastError());
1628 }
1629 
1630 static void test_CreateFile2(void)
1631 {
1632  HANDLE hFile;
1633  WCHAR temp_path[MAX_PATH];
1636  static const WCHAR emptyW[]={'\0'};
1637  static const WCHAR prefix[] = {'p','f','x',0};
1638  static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
1639  DWORD ret;
1640 
1641  if (!pCreateFile2)
1642  {
1643  win_skip("CreateFile2 is missing\n");
1644  return;
1645  }
1646 
1647  ret = GetTempPathW(MAX_PATH, temp_path);
1648  ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1649  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1650 
1651  ret = GetTempFileNameW(temp_path, prefix, 0, filename);
1652  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1653 
1654  SetLastError(0xdeadbeef);
1655  exparams.dwSize = sizeof(exparams);
1657  exparams.dwFileFlags = 0;
1658  exparams.dwSecurityQosFlags = 0;
1659  exparams.lpSecurityAttributes = NULL;
1660  exparams.hTemplateFile = 0;
1661  hFile = pCreateFile2(filename, GENERIC_READ, 0, CREATE_NEW, &exparams);
1663  "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
1664 
1665  SetLastError(0xdeadbeef);
1666  hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, CREATE_ALWAYS, &exparams);
1668  "hFile %p, last error %u\n", hFile, GetLastError());
1669  CloseHandle(hFile);
1670 
1671  SetLastError(0xdeadbeef);
1672  hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
1674  "hFile %p, last error %u\n", hFile, GetLastError());
1675  CloseHandle(hFile);
1676 
1677  ret = DeleteFileW(filename);
1678  ok(ret, "DeleteFileW: error %d\n", GetLastError());
1679 
1680  SetLastError(0xdeadbeef);
1681  hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
1682  ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
1683  "hFile %p, last error %u\n", hFile, GetLastError());
1684  CloseHandle(hFile);
1685 
1686  ret = DeleteFileW(filename);
1687  ok(ret, "DeleteFileW: error %d\n", GetLastError());
1688 
1689  hFile = pCreateFile2(emptyW, GENERIC_READ, 0, CREATE_NEW, &exparams);
1691  "CreateFile2(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
1692 
1693  /* test the result of opening a nonexistent driver name */
1695  hFile = pCreateFile2(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &exparams);
1697  "CreateFile2 on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
1698 
1699  ret = CreateDirectoryW(filename, NULL);
1700  ok(ret == TRUE, "couldn't create temporary directory\n");
1702  hFile = pCreateFile2(filename, GENERIC_READ | GENERIC_WRITE, 0, OPEN_ALWAYS, &exparams);
1703  todo_wine
1704  ok(hFile == INVALID_HANDLE_VALUE,
1705  "expected CreateFile2 to fail on existing directory, error: %d\n", GetLastError());
1706  CloseHandle(hFile);
1707  ret = RemoveDirectoryW(filename);
1708  ok(ret, "DeleteFileW: error %d\n", GetLastError());
1709 }
1710 
1711 static void test_GetTempFileNameA(void)
1712 {
1713  UINT result;
1714  char out[MAX_PATH];
1715  char expected[MAX_PATH + 10];
1716  char windowsdir[MAX_PATH + 10];
1717  char windowsdrive[3];
1718 
1719  result = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
1720  ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
1721  ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
1722 
1723  /* If the Windows directory is the root directory, it ends in backslash, not else. */
1724  if (strlen(windowsdir) != 3) /* As in "C:\" or "F:\" */
1725  {
1726  strcat(windowsdir, "\\");
1727  }
1728 
1729  windowsdrive[0] = windowsdir[0];
1730  windowsdrive[1] = windowsdir[1];
1731  windowsdrive[2] = '\0';
1732 
1733  result = GetTempFileNameA(windowsdrive, "abc", 1, out);
1734  ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
1735  ok(((out[0] == windowsdrive[0]) && (out[1] == ':')) && (out[2] == '\\'),
1736  "GetTempFileNameA: first three characters should be %c:\\, string was actually %s\n",
1737  windowsdrive[0], out);
1738 
1739  result = GetTempFileNameA(windowsdir, "abc", 2, out);
1740  ok(result != 0, "GetTempFileNameA: error %d\n", GetLastError());
1741  expected[0] = '\0';
1742  strcat(expected, windowsdir);
1743  strcat(expected, "abc2.tmp");
1744  ok(lstrcmpiA(out, expected) == 0, "GetTempFileNameA: Unexpected output \"%s\" vs \"%s\"\n",
1745  out, expected);
1746 }
1747 
1748 static void test_DeleteFileA( void )
1749 {
1750  BOOL ret;
1751  char temp_path[MAX_PATH], temp_file[MAX_PATH];
1752  HANDLE hfile;
1753 
1754  ret = DeleteFileA(NULL);
1755  ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER ||
1757  "DeleteFileA(NULL) returned ret=%d error=%d\n",ret,GetLastError());
1758 
1759  ret = DeleteFileA("");
1760  ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND ||
1762  "DeleteFileA(\"\") returned ret=%d error=%d\n",ret,GetLastError());
1763 
1764  ret = DeleteFileA("nul");
1765  ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
1769  "DeleteFileA(\"nul\") returned ret=%d error=%d\n",ret,GetLastError());
1770 
1771  ret = DeleteFileA("nonexist.txt");
1772  ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "DeleteFileA(\"nonexist.txt\") returned ret=%d error=%d\n",ret,GetLastError());
1773 
1774  GetTempPathA(MAX_PATH, temp_path);
1775  GetTempFileNameA(temp_path, "tst", 0, temp_file);
1776 
1777  SetLastError(0xdeadbeef);
1779  ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1780 
1781  SetLastError(0xdeadbeef);
1782  ret = DeleteFileA(temp_file);
1783  ok(ret, "DeleteFile error %d\n", GetLastError());
1784 
1785  SetLastError(0xdeadbeef);
1786  ret = CloseHandle(hfile);
1787  ok(ret, "CloseHandle error %d\n", GetLastError());
1788  ret = DeleteFileA(temp_file);
1789  ok(!ret, "DeleteFile should fail\n");
1790 
1791  SetLastError(0xdeadbeef);
1792  ret = CreateDirectoryA("testdir", NULL);
1793  ok(ret, "CreateDirectory failed, got err %d\n", GetLastError());
1794  ret = DeleteFileA("testdir");
1795  ok(!ret && GetLastError() == ERROR_ACCESS_DENIED,
1796  "Expected ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
1797  ret = RemoveDirectoryA("testdir");
1798  ok(ret, "Remove a directory failed, got error %d\n", GetLastError());
1799 }
1800 
1801 static void test_DeleteFileW( void )
1802 {
1803  BOOL ret;
1804  WCHAR pathW[MAX_PATH];
1805  WCHAR pathsubW[MAX_PATH];
1806  static const WCHAR dirW[] = {'d','e','l','e','t','e','f','i','l','e',0};
1807  static const WCHAR subdirW[] = {'\\','s','u','b',0};
1808  static const WCHAR emptyW[]={'\0'};
1809 
1810  ret = DeleteFileW(NULL);
1811  if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1812  {
1813  win_skip("DeleteFileW is not available\n");
1814  return;
1815  }
1816  ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
1817  "DeleteFileW(NULL) returned ret=%d error=%d\n",ret,GetLastError());
1818 
1819  ret = DeleteFileW(emptyW);
1820  ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
1821  "DeleteFileW(\"\") returned ret=%d error=%d\n",ret,GetLastError());
1822 
1823  /* test DeleteFile on empty directory */
1824  ret = GetTempPathW(MAX_PATH, pathW);
1825  if (ret + sizeof(dirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
1826  {
1827  ok(0, "MAX_PATH exceeded in constructing paths\n");
1828  return;
1829  }
1830  lstrcatW(pathW, dirW);
1831  lstrcpyW(pathsubW, pathW);
1832  lstrcatW(pathsubW, subdirW);
1833  ret = CreateDirectoryW(pathW, NULL);
1834  ok(ret == TRUE, "couldn't create directory deletefile\n");
1835  ret = DeleteFileW(pathW);
1836  ok(ret == FALSE, "DeleteFile should fail for empty directories\n");
1837  ret = RemoveDirectoryW(pathW);
1838  ok(ret == TRUE, "expected to remove directory deletefile\n");
1839 
1840  /* test DeleteFile on non-empty directory */
1841  ret = CreateDirectoryW(pathW, NULL);
1842  ok(ret == TRUE, "couldn't create directory deletefile\n");
1843  ret = CreateDirectoryW(pathsubW, NULL);
1844  ok(ret == TRUE, "couldn't create directory deletefile\\sub\n");
1845  ret = DeleteFileW(pathW);
1846  ok(ret == FALSE, "DeleteFile should fail for non-empty directories\n");
1847  ret = RemoveDirectoryW(pathsubW);
1848  ok(ret == TRUE, "expected to remove directory deletefile\\sub\n");
1849  ret = RemoveDirectoryW(pathW);
1850  ok(ret == TRUE, "expected to remove directory deletefile\n");
1851 }
1852 
1853 #define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
1854 
1855 static void test_MoveFileA(void)
1856 {
1857  char tempdir[MAX_PATH];
1858  char source[MAX_PATH], dest[MAX_PATH];
1859  static const char prefix[] = "pfx";
1860  HANDLE hfile;
1861  HANDLE hmapfile;
1862  DWORD ret;
1863  BOOL retok;
1864 
1865  ret = GetTempPathA(MAX_PATH, tempdir);
1866  ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
1867  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1868 
1869  ret = GetTempFileNameA(tempdir, prefix, 0, source);
1870  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1871 
1872  ret = GetTempFileNameA(tempdir, prefix, 0, dest);
1873  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
1874 
1875  ret = MoveFileA(source, source);
1876  ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
1877 
1878  ret = MoveFileA(source, dest);
1879  ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
1880  "MoveFileA: unexpected error %d\n", GetLastError());
1881 
1882  ret = DeleteFileA(dest);
1883  ok(ret, "DeleteFileA: error %d\n", GetLastError());
1884 
1886  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
1887 
1888  retok = WriteFile(hfile, prefix, sizeof(prefix), &ret, NULL );
1889  ok( retok && ret == sizeof(prefix),
1890  "WriteFile error %d\n", GetLastError());
1891 
1892  hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1893  ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1894 
1895  ret = MoveFileA(source, dest);
1896  ok(!ret, "MoveFileA: expected failure\n");
1898  broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
1899  "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
1900 
1901  CloseHandle(hmapfile);
1902  CloseHandle(hfile);
1903 
1904  /* if MoveFile succeeded, move back to dest */
1905  if (ret) MoveFileA(dest, source);
1906 
1907  hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1908  ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
1909 
1910  hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
1911  ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
1912 
1913  ret = MoveFileA(source, dest);
1914  ok(!ret, "MoveFileA: expected failure\n");
1916  broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
1917  "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
1918 
1919  CloseHandle(hmapfile);
1920  CloseHandle(hfile);
1921 
1922  /* if MoveFile succeeded, move back to dest */
1923  if (ret) MoveFileA(dest, source);
1924 
1925  ret = MoveFileA(source, dest);
1926  ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
1927 
1928  lstrcatA(tempdir, "Remove Me");
1929  ret = CreateDirectoryA(tempdir, NULL);
1930  ok(ret == TRUE, "CreateDirectoryA failed\n");
1931 
1932  lstrcpyA(source, dest);
1933  lstrcpyA(dest, tempdir);
1934  lstrcatA(dest, "\\wild?.*");
1935  /* FIXME: if we create a file with wildcards we can't delete it now that DeleteFile works correctly */
1936  ret = MoveFileA(source, dest);
1937  ok(!ret, "MoveFileA: shouldn't move to wildcard file\n");
1938  ok(GetLastError() == ERROR_INVALID_NAME || /* NT */
1939  GetLastError() == ERROR_FILE_NOT_FOUND, /* Win9x */
1940  "MoveFileA: with wildcards, unexpected error %d\n", GetLastError());
1941  if (ret || (GetLastError() != ERROR_INVALID_NAME))
1942  {
1944  char temppath[MAX_PATH];
1945  HANDLE hFind;
1946 
1947  lstrcpyA(temppath, tempdir);
1948  lstrcatA(temppath, "\\*.*");
1949  hFind = FindFirstFileA(temppath, &fd);
1950  if (INVALID_HANDLE_VALUE != hFind)
1951  {
1952  LPSTR lpName;
1953  do
1954  {
1955  lpName = fd.cAlternateFileName;
1956  if (!lpName[0])
1957  lpName = fd.cFileName;
1958  ok(IsDotDir(lpName), "MoveFileA: wildcards file created!\n");
1959  }
1960  while (FindNextFileA(hFind, &fd));
1961  FindClose(hFind);
1962  }
1963  }
1964  ret = DeleteFileA(source);
1965  ok(ret, "DeleteFileA: error %d\n", GetLastError());
1966  ret = DeleteFileA(dest);
1967  ok(!ret, "DeleteFileA: error %d\n", GetLastError());
1968  ret = RemoveDirectoryA(tempdir);
1969  ok(ret, "DeleteDirectoryA: error %d\n", GetLastError());
1970 }
1971 
1972 static void test_MoveFileW(void)
1973 {
1974  WCHAR temp_path[MAX_PATH];
1976  static const WCHAR prefix[] = {'p','f','x',0};
1977  DWORD ret;
1978 
1979  ret = GetTempPathW(MAX_PATH, temp_path);
1980  if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1981  {
1982  win_skip("GetTempPathW is not available\n");
1983  return;
1984  }
1985  ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
1986  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
1987 
1988  ret = GetTempFileNameW(temp_path, prefix, 0, source);
1989  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1990 
1991  ret = GetTempFileNameW(temp_path, prefix, 0, dest);
1992  ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
1993 
1994  ret = MoveFileW(source, dest);
1995  ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
1996  "CopyFileW: unexpected error %d\n", GetLastError());
1997 
1998  ret = DeleteFileW(source);
1999  ok(ret, "DeleteFileW: error %d\n", GetLastError());
2000  ret = DeleteFileW(dest);
2001  ok(ret, "DeleteFileW: error %d\n", GetLastError());
2002 }
2003 
2004 #define PATTERN_OFFSET 0x10
2005 
2007 {
2008  HANDLE hFile;
2009  OVERLAPPED ov;
2010  DWORD done, offset;
2011  BOOL rc;
2012  BYTE buf[256], pattern[] = "TeSt";
2013  UINT i;
2014  char temp_path[MAX_PATH], temp_fname[MAX_PATH];
2015  BOOL ret;
2016 
2017  ret =GetTempPathA(MAX_PATH, temp_path);
2018  ok( ret, "GetTempPathA error %d\n", GetLastError());
2019  ret =GetTempFileNameA(temp_path, "pfx", 0, temp_fname);
2020  ok( ret, "GetTempFileNameA error %d\n", GetLastError());
2021 
2022  /*** Write File *****************************************************/
2023 
2024  hFile = CreateFileA(temp_fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
2025  ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
2026 
2027  for(i = 0; i < sizeof(buf); i++) buf[i] = i;
2028  ret = WriteFile(hFile, buf, sizeof(buf), &done, NULL);
2029  ok( ret, "WriteFile error %d\n", GetLastError());
2030  ok(done == sizeof(buf), "expected number of bytes written %u\n", done);
2031 
2032  memset(&ov, 0, sizeof(ov));
2033  S(U(ov)).Offset = PATTERN_OFFSET;
2034  S(U(ov)).OffsetHigh = 0;
2035  rc=WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
2036  /* Win 9x does not support the overlapped I/O on files */
2037  if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
2038  ok(rc, "WriteFile error %d\n", GetLastError());
2039  ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
2040  offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
2041  ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
2042 
2043  S(U(ov)).Offset = sizeof(buf) * 2;
2044  S(U(ov)).OffsetHigh = 0;
2045  ret = WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
2046  ok( ret, "WriteFile error %d\n", GetLastError());
2047  ok(done == sizeof(pattern), "expected number of bytes written %u\n", done);
2048  offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
2049  ok(offset == sizeof(buf) * 2 + sizeof(pattern), "wrong file offset %d\n", offset);
2050  }
2051 
2052  CloseHandle(hFile);
2053 
2054  /*** Read File *****************************************************/
2055 
2056  hFile = CreateFileA(temp_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
2057  ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError());
2058 
2059  memset(buf, 0, sizeof(buf));
2060  memset(&ov, 0, sizeof(ov));
2061  S(U(ov)).Offset = PATTERN_OFFSET;
2062  S(U(ov)).OffsetHigh = 0;
2063  rc=ReadFile(hFile, buf, sizeof(pattern), &done, &ov);
2064  /* Win 9x does not support the overlapped I/O on files */
2065  if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
2066  ok(rc, "ReadFile error %d\n", GetLastError());
2067  ok(done == sizeof(pattern), "expected number of bytes read %u\n", done);
2068  offset = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
2069  ok(offset == PATTERN_OFFSET + sizeof(pattern), "wrong file offset %d\n", offset);
2070  ok(!memcmp(buf, pattern, sizeof(pattern)), "pattern match failed\n");
2071  }
2072 
2073  CloseHandle(hFile);
2074 
2075  ret = DeleteFileA(temp_fname);
2076  ok( ret, "DeleteFileA error %d\n", GetLastError());
2077 }
2078 
2079 static void test_LockFile(void)
2080 {
2081  HANDLE handle, handle2;
2082  DWORD written;
2084  int limited_LockFile;
2085  int limited_UnLockFile;
2086  BOOL ret;
2087 
2090  CREATE_ALWAYS, 0, 0 );
2091  if (handle == INVALID_HANDLE_VALUE)
2092  {
2093  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2094  return;
2095  }
2098  OPEN_EXISTING, 0, 0 );
2099  if (handle2 == INVALID_HANDLE_VALUE)
2100  {
2101  ok( 0, "couldn't open file \"%s\" (err=%d)\n", filename, GetLastError() );
2102  goto cleanup;
2103  }
2104  ok( WriteFile( handle, sillytext, strlen(sillytext), &written, NULL ), "write failed\n" );
2105 
2106  ok( LockFile( handle, 0, 0, 0, 0 ), "LockFile failed\n" );
2107  ok( UnlockFile( handle, 0, 0, 0, 0 ), "UnlockFile failed\n" );
2108 
2109  limited_UnLockFile = 0;
2110  if (UnlockFile( handle, 0, 0, 0, 0 ))
2111  {
2112  limited_UnLockFile = 1;
2113  }
2114 
2115  ok( LockFile( handle, 10, 0, 20, 0 ), "LockFile 10,20 failed\n" );
2116  /* overlapping locks must fail */
2117  ok( !LockFile( handle, 12, 0, 10, 0 ), "LockFile 12,10 succeeded\n" );
2118  ok( !LockFile( handle, 5, 0, 6, 0 ), "LockFile 5,6 succeeded\n" );
2119  /* non-overlapping locks must succeed */
2120  ok( LockFile( handle, 5, 0, 5, 0 ), "LockFile 5,5 failed\n" );
2121 
2122  ok( !UnlockFile( handle, 10, 0, 10, 0 ), "UnlockFile 10,10 succeeded\n" );
2123  ok( UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 failed\n" );
2124  ok( !UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 again succeeded\n" );
2125  ok( UnlockFile( handle, 5, 0, 5, 0 ), "UnlockFile 5,5 failed\n" );
2126 
2127  S(U(overlapped)).Offset = 100;
2128  S(U(overlapped)).OffsetHigh = 0;
2129  overlapped.hEvent = 0;
2130 
2131  /* Test for broken LockFileEx a la Windows 95 OSR2. */
2132  if (LockFileEx( handle, 0, 0, 100, 0, &overlapped ))
2133  {
2134  /* LockFileEx is probably OK, test it more. */
2135  ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ),
2136  "LockFileEx 100,100 failed\n" );
2137  }
2138 
2139  /* overlapping shared locks are OK */
2140  S(U(overlapped)).Offset = 150;
2141  limited_UnLockFile || ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 150,100 failed\n" );
2142 
2143  /* but exclusive is not */
2145  0, 50, 0, &overlapped ),
2146  "LockFileEx exclusive 150,50 succeeded\n" );
2147  if (!UnlockFileEx( handle, 0, 100, 0, &overlapped ))
2148  { /* UnLockFile is capable. */
2149  S(U(overlapped)).Offset = 100;
2150  ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ),
2151  "UnlockFileEx 150,100 again succeeded\n" );
2152  }
2153 
2154  /* shared lock can overlap exclusive if handles are equal */
2155  S(U(overlapped)).Offset = 300;
2156  ok( LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, &overlapped ),
2157  "LockFileEx exclusive 300,100 failed\n" );
2158  ok( !LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
2159  "LockFileEx handle2 300,100 succeeded\n" );
2160  ret = LockFileEx( handle, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped );
2161  ok( ret, "LockFileEx 300,100 failed\n" );
2162  ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2163  /* exclusive lock is removed first */
2164  ok( LockFileEx( handle2, LOCKFILE_FAIL_IMMEDIATELY, 0, 100, 0, &overlapped ),
2165  "LockFileEx handle2 300,100 failed\n" );
2166  ok( UnlockFileEx( handle2, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2167  if (ret)
2168  ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 300,100 failed\n" );
2169 
2170  ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 );
2171  if (ret)
2172  {
2173  ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
2174  ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
2175  ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
2176  }
2177  else /* win9x */
2178  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong LockFile error %u\n", GetLastError() );
2179 
2180  /* wrap-around lock should not do anything */
2181  /* (but still succeeds on NT4 so we don't check result) */
2182  LockFile( handle, 0, 0x10000000, 0, 0xf0000001 );
2183 
2184  limited_LockFile = 0;
2185  if (!LockFile( handle, ~0, ~0, 1, 0 ))
2186  {
2187  limited_LockFile = 1;
2188  }
2189 
2190  limited_UnLockFile || ok( UnlockFile( handle, ~0, ~0, 1, 0 ), "Unlockfile ~0,1 failed\n" );
2191 
2192  /* zero-byte lock */
2193  ok( LockFile( handle, 100, 0, 0, 0 ), "LockFile 100,0 failed\n" );
2194  if (!limited_LockFile) ok( !LockFile( handle, 98, 0, 4, 0 ), "LockFile 98,4 succeeded\n" );
2195  ok( LockFile( handle, 90, 0, 10, 0 ), "LockFile 90,10 failed\n" );
2196  if (!limited_LockFile) ok( !LockFile( handle, 100, 0, 10, 0 ), "LockFile 100,10 failed\n" );
2197 
2198  ok( UnlockFile( handle, 90, 0, 10, 0 ), "UnlockFile 90,10 failed\n" );
2199  ok( !UnlockFile( handle, 100, 0, 10, 0 ), "UnlockFile 100,10 succeeded\n" );
2200 
2201  ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed\n" );
2202 
2203  CloseHandle( handle2 );
2204 cleanup:
2205  CloseHandle( handle );
2206  DeleteFileA( filename );
2207 }
2208 
2210 {
2213  IMAGE_SECTION_HEADER *sec;
2214  BYTE *buffer;
2215  DWORD lfanew = sizeof(*dos);
2216  DWORD size = lfanew + sizeof(*nt) + sizeof(*sec);
2217  DWORD written;
2218  BOOL ret;
2219 
2221  if (file == INVALID_HANDLE_VALUE) return FALSE;
2222 
2223  buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
2224 
2225  dos = (IMAGE_DOS_HEADER *)buffer;
2227  dos->e_cblp = sizeof(*dos);
2228  dos->e_cp = 1;
2229  dos->e_cparhdr = lfanew / 16;
2230  dos->e_minalloc = 0;
2231  dos->e_maxalloc = 0xffff;
2232  dos->e_ss = 0x0000;
2233  dos->e_sp = 0x00b8;
2234  dos->e_lfarlc = lfanew;
2235  dos->e_lfanew = lfanew;
2236 
2237  nt = (IMAGE_NT_HEADERS *)(buffer + lfanew);
2239 #if defined __i386__
2241 #elif defined __x86_64__
2243 #elif defined __powerpc__
2245 #elif defined __arm__
2247 #elif defined __aarch64__
2249 #else
2250 # error You must specify the machine type
2251 #endif
2252  nt->FileHeader.NumberOfSections = 1;
2258  nt->OptionalHeader.ImageBase = 0x10000000;
2259  nt->OptionalHeader.SectionAlignment = 0x1000;
2260  nt->OptionalHeader.FileAlignment = 0x1000;
2267  nt->OptionalHeader.SizeOfImage = 0x2000;
2271 
2272  sec = (IMAGE_SECTION_HEADER *)(nt + 1);
2273  memcpy( sec->Name, ".rodata", sizeof(".rodata") );
2274  sec->Misc.VirtualSize = 0x1000;
2275  sec->VirtualAddress = 0x1000;
2276  sec->SizeOfRawData = 0;
2277  sec->PointerToRawData = 0;
2278  sec->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
2279 
2280  ret = WriteFile( file, buffer, size, &written, NULL ) && written == size;
2281  HeapFree( GetProcessHeap(), 0, buffer );
2282  CloseHandle( file );
2283  return ret;
2284 }
2285 
2286 static unsigned int map_file_access( unsigned int access )
2287 {
2288  if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
2289  if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
2290  if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
2291  if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS;
2292  return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
2293 }
2294 
2295 static BOOL is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 )
2296 {
2297  access1 = map_file_access( access1 );
2298  access2 = map_file_access( access2 );
2301 
2302  if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
2303  if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
2304 
2305  if ((access1 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing2 & FILE_SHARE_READ)) return FALSE;
2306  if ((access1 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing2 & FILE_SHARE_WRITE)) return FALSE;
2307  if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return FALSE;
2308  if ((access2 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing1 & FILE_SHARE_READ)) return FALSE;
2309  if ((access2 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing1 & FILE_SHARE_WRITE)) return FALSE;
2310  if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return FALSE;
2311  return TRUE;
2312 }
2313 
2314 static BOOL is_sharing_map_compatible( DWORD map_access, DWORD access2, DWORD sharing2 )
2315 {
2316  if ((map_access == PAGE_READWRITE || map_access == PAGE_EXECUTE_READWRITE) &&
2317  !(sharing2 & FILE_SHARE_WRITE)) return FALSE;
2318  access2 = map_file_access( access2 );
2319  if ((map_access & SEC_IMAGE) && (access2 & FILE_WRITE_DATA)) return FALSE;
2320  return TRUE;
2321 }
2322 
2323 static void test_file_sharing(void)
2324 {
2325  struct mode { DWORD dw; const char* str; };
2326 #define M(x) {x, # x}
2327  static const struct mode access_modes[] =
2335  static const struct mode sharing_modes[] =
2336  { M(0), M(FILE_SHARE_READ),
2340  static const struct mode mapping_modes[] =
2342 #undef M
2343  int a1, s1, a2, s2;
2344  int ret;
2345  HANDLE h, h2;
2346 
2347  /* make sure the file exists */
2348  if (!create_fake_dll( filename ))
2349  {
2350  ok(0, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError());
2351  return;
2352  }
2353 
2354  for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++)
2355  {
2356  for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++)
2357  {
2358  SetLastError(0xdeadbeef);
2359  h = CreateFileA( filename, access_modes[a1].dw, sharing_modes[s1].dw,
2360  NULL, OPEN_EXISTING, 0, 0 );
2361  if (h == INVALID_HANDLE_VALUE)
2362  {
2363  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2364  return;
2365  }
2366  for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
2367  {
2368  for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
2369  {
2370  SetLastError(0xdeadbeef);
2371  h2 = CreateFileA( filename, access_modes[a2].dw, sharing_modes[s2].dw,
2372  NULL, OPEN_EXISTING, 0, 0 );
2373  ret = GetLastError();
2374  if (is_sharing_compatible( access_modes[a1].dw, sharing_modes[s1].dw,
2375  access_modes[a2].dw, sharing_modes[s2].dw ))
2376  {
2377  ok( h2 != INVALID_HANDLE_VALUE,
2378  "open failed for modes %s / %s / %s / %s\n",
2379  access_modes[a1].str, sharing_modes[s1].str,
2380  access_modes[a2].str, sharing_modes[s2].str );
2381  ok( ret == 0, "wrong error code %d\n", ret );
2382  }
2383  else
2384  {
2385  ok( h2 == INVALID_HANDLE_VALUE,
2386  "open succeeded for modes %s / %s / %s / %s\n",
2387  access_modes[a1].str, sharing_modes[s1].str,
2388  access_modes[a2].str, sharing_modes[s2].str );
2389  ok( ret == ERROR_SHARING_VIOLATION,
2390  "wrong error code %d\n", ret );
2391  }
2392  if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2393  }
2394  }
2395  CloseHandle( h );
2396  }
2397  }
2398 
2399  for (a1 = 0; a1 < sizeof(mapping_modes)/sizeof(mapping_modes[0]); a1++)
2400  {
2401  HANDLE m;
2402 
2404  SetLastError(0xdeadbeef);
2406  if (h == INVALID_HANDLE_VALUE)
2407  {
2408  ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
2409  return;
2410  }
2411  m = CreateFileMappingA( h, NULL, mapping_modes[a1].dw, 0, 0, NULL );
2412  ok( m != 0, "failed to create mapping %s err %u\n", mapping_modes[a1].str, GetLastError() );
2413  CloseHandle( h );
2414  if (!m) continue;
2415 
2416  for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
2417  {
2418  for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
2419  {
2420  SetLastError(0xdeadbeef);
2421  h2 = CreateFileA( filename, access_modes[a2].dw, sharing_modes[s2].dw,
2422  NULL, OPEN_EXISTING, 0, 0 );
2423 
2424  ret = GetLastError();
2425  if (h2 == INVALID_HANDLE_VALUE)
2426  {
2427  ok( !is_sharing_map_compatible(mapping_modes[a1].dw, access_modes[a2].dw, sharing_modes[s2].dw),
2428  "open failed for modes map %s / %s / %s\n",
2429  mapping_modes[a1].str, access_modes[a2].str, sharing_modes[s2].str );
2430  ok( ret == ERROR_SHARING_VIOLATION,
2431  "wrong error code %d\n", ret );
2432  }
2433  else
2434  {
2435  if (!is_sharing_map_compatible(mapping_modes[a1].dw, access_modes[a2].dw, sharing_modes[s2].dw))
2436  ok( broken(1), /* no checking on nt4 */
2437  "open succeeded for modes map %s / %s / %s\n",
2438  mapping_modes[a1].str, access_modes[a2].str, sharing_modes[s2].str );
2439  ok( ret == 0xdeadbeef /* Win9x */ ||
2440  ret == 0, /* XP */
2441  "wrong error code %d\n", ret );
2442  CloseHandle( h2 );
2443  }
2444  }
2445  }
2446 
2447  /* try CREATE_ALWAYS over an existing mapping */
2448  SetLastError(0xdeadbeef);
2450  NULL, CREATE_ALWAYS, 0, 0 );
2451  ret = GetLastError();
2452  if (mapping_modes[a1].dw & SEC_IMAGE)
2453  {
2454  ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str );
2455  ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %s\n", ret, mapping_modes[a1].str );
2456  }
2457  else
2458  {
2459  ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str );
2460  ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %s\n", ret, mapping_modes[a1].str );
2461  }
2462  if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2463 
2464  /* try DELETE_ON_CLOSE over an existing mapping */
2465  SetLastError(0xdeadbeef);
2468  ret = GetLastError();
2469  if (mapping_modes[a1].dw & SEC_IMAGE)
2470  {
2471  ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str );
2472  ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %s\n", ret, mapping_modes[a1].str );
2473  }
2474  else
2475  {
2476  ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %s err %u\n", mapping_modes[a1].str, ret );
2477  }
2478  if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
2479 
2480  CloseHandle( m );
2481  }
2482 
2483  SetLastError(0xdeadbeef);
2485  ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
2486 
2487  SetLastError(0xdeadbeef);
2489  ok( h2 == INVALID_HANDLE_VALUE, "CreateFileA should fail\n");
2490  ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error code %d\n", GetLastError() );
2491 
2493  ok( h2 != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
2494 
2495  CloseHandle(h);
2496  CloseHandle(h2);
2497 
2498  DeleteFileA( filename );
2499 }
2500 
2501 static char get_windows_drive(void)
2502 {
2503  char windowsdir[MAX_PATH];
2504  GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
2505  return windowsdir[0];
2506 }
2507 
2508 static const struct
2509 {
2510  const char *path;
2512 }
2514 {
2515  { "./test-dir", TRUE },
2516  { "./test-dir/", FALSE },
2517  { ".\\test-dir", TRUE },
2518  { ".\\test-dir\\", FALSE },
2519  { "/>test-dir", FALSE },
2520  { "<\"test->dir", FALSE },
2521  { "<test->dir", FALSE },
2522  { "><test->dir", FALSE },
2523  { ">>test-dir", FALSE },
2524  { ">test->dir", FALSE },
2525  { ">test-dir", FALSE },
2526  { "\"test-dir\"", FALSE },
2527  { "\"test-file\"", FALSE },
2528  { "test-/>dir", FALSE },
2529  { "test-dir/", FALSE },
2530  { "test-dir//", FALSE },
2531  { "test-dir/:", FALSE },
2532  { "test-dir/<", TRUE },
2533  { "test-dir/>", TRUE },
2534  { "test-dir/\"", TRUE },
2535  { "test-dir/\\", FALSE },
2536  { "test-dir/|", FALSE },
2537  { "test-dir<", TRUE },
2538  { "test-dir</", FALSE },
2539  { "test-dir<<", TRUE },
2540  { "test-dir<<<><><>\"\"\"\"<<<>", TRUE },
2541  { "test-dir<>", TRUE },
2542  { "test-dir<\"", TRUE },
2543  { "test-dir>", TRUE },
2544  { "test-dir>/", FALSE },
2545  { "test-dir><", TRUE },
2546  { "test-dir>>", TRUE },
2547  { "test-dir>\"", TRUE },
2548  { "test-dir\"", TRUE },
2549  { "test-dir\"/", FALSE },
2550  { "test-dir\"<", TRUE },
2551  { "test-dir\">", TRUE },
2552  { "test-dir\"\"", TRUE },
2553  { "test-dir\"\"\"\"\"", TRUE },
2554  { "test-dir\\", FALSE },
2555  { "test-dir\\/", FALSE },
2556  { "test-dir\\<", TRUE },
2557  { "test-dir\\>", TRUE },
2558  { "test-dir\\\"", TRUE },
2559  { "test-dir\\\\", FALSE },
2560  { "test-file/", FALSE },
2561  { "test-file/<", FALSE },
2562  { "test-file/>", FALSE },
2563  { "test-file/\"", FALSE },
2564  { "test-file<", TRUE },
2565  { "test-file<<", TRUE },
2566  { "test-file<>", TRUE },
2567  { "test-file<\"", TRUE },
2568  { "test-file>", TRUE },
2569  { "test-file><", TRUE },
2570  { "test-file>>", TRUE },
2571  { "test-file>\"", TRUE },
2572  { "test-file\"", TRUE },
2573  { "test-file\"<", TRUE },
2574  { "test-file\">", TRUE },
2575  { "test-file\"\"", TRUE },
2576  { "test-file\\", FALSE },
2577  { "test-file\\<", FALSE },
2578  { "test-file\\>", FALSE },
2579  { "test-file\\\"", FALSE },
2580 };
2581 
2582 static void test_FindFirstFileA(void)
2583 {
2584  HANDLE handle;
2586  int err, i;
2587  char buffer[5] = "C:\\";
2588  char buffer2[100];
2589  char nonexistent[MAX_PATH];
2590 
2591  /* try FindFirstFileA on "C:\" */
2592  buffer[0] = get_windows_drive();
2593 
2594  SetLastError( 0xdeadbeaf );
2595  handle = FindFirstFileA(buffer, &data);
2596  err = GetLastError();
2597  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on root directory should fail\n" );
2598  ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2599 
2600  /* try FindFirstFileA on "C:\*" */
2601  strcpy(buffer2, buffer);
2602  strcat(buffer2, "*");
2603  handle = FindFirstFileA(buffer2, &data);
2604  ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
2605  ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2606  "FindFirstFile shouldn't return '%s' in drive root\n", data.cFileName );
2607  if (FindNextFileA( handle, &data ))
2608  ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2609  "FindNextFile shouldn't return '%s' in drive root\n", data.cFileName );
2610  ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
2611 
2612  /* try FindFirstFileA on windows dir */
2613  GetWindowsDirectoryA( buffer2, sizeof(buffer2) );
2614  strcat(buffer2, "\\*");
2615  handle = FindFirstFileA(buffer2, &data);
2616  ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
2617  ok( !strcmp( data.cFileName, "." ), "FindFirstFile should return '.' first\n" );
2618  ok( FindNextFileA( handle, &data ), "FindNextFile failed\n" );
2619  ok( !strcmp( data.cFileName, ".." ), "FindNextFile should return '..' as second entry\n" );
2620  while (FindNextFileA( handle, &data ))
2621  ok ( strcmp( data.cFileName, "." ) && strcmp( data.cFileName, ".." ),
2622  "FindNextFile shouldn't return '%s'\n", data.cFileName );
2623  ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
2624 
2625  /* try FindFirstFileA on "C:\foo\" */
2626  SetLastError( 0xdeadbeaf );
2627  if (!GetTempFileNameA( buffer, "foo", 0, nonexistent ) && GetLastError() == ERROR_ACCESS_DENIED)
2628  {
2629  char tmp[MAX_PATH];
2630  GetTempPathA( sizeof(tmp), tmp );
2631  GetTempFileNameA( tmp, "foo", 0, nonexistent );
2632  }
2633  DeleteFileA( nonexistent );
2634  strcpy(buffer2, nonexistent);
2635  strcat(buffer2, "\\");
2636  handle = FindFirstFileA(buffer2, &data);
2637  err = GetLastError();
2638  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2639  todo_wine {
2640  ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2641  }
2642 
2643  /* try FindFirstFileA without trailing backslash */
2644  SetLastError( 0xdeadbeaf );
2645  strcpy(buffer2, nonexistent);
2646  handle = FindFirstFileA(buffer2, &data);
2647  err = GetLastError();
2648  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2649  ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2650 
2651  /* try FindFirstFileA on "C:\foo\bar.txt" */
2652  SetLastError( 0xdeadbeaf );
2653  strcpy(buffer2, nonexistent);
2654  strcat(buffer2, "\\bar.txt");
2655  handle = FindFirstFileA(buffer2, &data);
2656  err = GetLastError();
2657  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2658  ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2659 
2660  /* try FindFirstFileA on "C:\foo\*.*" */
2661  SetLastError( 0xdeadbeaf );
2662  strcpy(buffer2, nonexistent);
2663  strcat(buffer2, "\\*.*");
2664  handle = FindFirstFileA(buffer2, &data);
2665  err = GetLastError();
2666  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2667  ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2668 
2669  /* try FindFirstFileA on "foo\bar.txt" */
2670  SetLastError( 0xdeadbeaf );
2671  strcpy(buffer2, nonexistent + 3);
2672  strcat(buffer2, "\\bar.txt");
2673  handle = FindFirstFileA(buffer2, &data);
2674  err = GetLastError();
2675  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2676  ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2677 
2678  /* try FindFirstFileA on "c:\nul" */
2679  SetLastError( 0xdeadbeaf );
2680  strcpy(buffer2, buffer);
2681  strcat(buffer2, "nul");
2682  handle = FindFirstFileA(buffer2, &data);
2683  err = GetLastError();
2684  ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
2685  ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
2686  ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
2687  FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
2688  "wrong attributes %x\n", data.dwFileAttributes );
2689  if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
2690  {
2691  ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
2692  ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
2693  }
2694  SetLastError( 0xdeadbeaf );
2695  ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
2696  ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
2697  ok( FindClose( handle ), "failed to close handle\n" );
2698 
2699  /* try FindFirstFileA on "lpt1" */
2700  SetLastError( 0xdeadbeaf );
2701  strcpy(buffer2, "lpt1");
2702  handle = FindFirstFileA(buffer2, &data);
2703  err = GetLastError();
2704  ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
2705  ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
2706  ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
2707  FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
2708  "wrong attributes %x\n", data.dwFileAttributes );
2709  if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
2710  {
2711  ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
2712  ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
2713  }
2714  SetLastError( 0xdeadbeaf );
2715  ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
2716  ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
2717  ok( FindClose( handle ), "failed to close handle\n" );
2718 
2719  /* try FindFirstFileA on "c:\nul\*" */
2720  SetLastError( 0xdeadbeaf );
2721  strcpy(buffer2, buffer);
2722  strcat(buffer2, "nul\\*");
2723  handle = FindFirstFileA(buffer2, &data);
2724  err = GetLastError();
2725  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2726  ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2727 
2728  /* try FindFirstFileA on "c:\nul*" */
2729  SetLastError( 0xdeadbeaf );
2730  strcpy(buffer2, buffer);
2731  strcat(buffer2, "nul*");
2732  handle = FindFirstFileA(buffer2, &data);
2733  err = GetLastError();
2734  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2735  ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
2736 
2737  /* try FindFirstFileA on "c:\foo\bar\nul" */
2738  SetLastError( 0xdeadbeaf );
2739  strcpy(buffer2, buffer);
2740  strcat(buffer2, "foo\\bar\\nul");
2741  handle = FindFirstFileA(buffer2, &data);
2742  err = GetLastError();
2743  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2744  ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2745 
2746  /* try FindFirstFileA on "c:\foo\nul\bar" */
2747  SetLastError( 0xdeadbeaf );
2748  strcpy(buffer2, buffer);
2749  strcat(buffer2, "foo\\nul\\bar");
2750  handle = FindFirstFileA(buffer2, &data);
2751  err = GetLastError();
2752  ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
2753  ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
2754 
2755  /* try FindFirstFileA with invalid characters */
2756  CreateDirectoryA("test-dir", NULL);
2757  _lclose(_lcreat("test-file", 0));
2758 
2759  for (i = 0; i < sizeof(invalid_char_tests) / sizeof(invalid_char_tests[0]); i++)
2760  {
2761  handle = FindFirstFileA(invalid_char_tests[i].path, &data);
2763  {
2764  ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileA on %s should succeed\n",
2765  invalid_char_tests[i].path);
2766  }
2767  else
2768  {
2769  ok(handle == INVALID_HANDLE_VALUE, "FindFirstFileA on %s should fail\n",
2770  invalid_char_tests[i].path);
2771  }
2772  if (handle != INVALID_HANDLE_VALUE)
2773  FindClose(handle);
2774  }
2775 
2776  DeleteFileA("test-file");
2777  RemoveDirectoryA("test-dir");
2778 }
2779 
2780 static void test_FindNextFileA(void)
2781 {
2782  HANDLE handle;
2783  WIN32_FIND_DATAA search_results;
2784  int err;
2785  char buffer[5] = "C:\\*";
2786 
2787  buffer[0] = get_windows_drive();
2788  handle = FindFirstFileA(buffer,&search_results);
2789  ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed\n" );
2790  while (FindNextFileA(handle, &search_results))
2791  {
2792  /* get to the end of the files */
2793  }
2794  ok ( FindClose(handle) == TRUE, "Failed to close handle\n");
2795  err = GetLastError();
2796  ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES\n");
2797 }
2798 
2800 {
2801  WIN32_FIND_DATAA search_results;
2802  HANDLE handle;
2803  BOOL ret;
2804 
2805  if (!pFindFirstFileExA)
2806  {
2807  win_skip("FindFirstFileExA() is missing\n");
2808  return;
2809  }
2810 
2811  trace("Running FindFirstFileExA tests with level=%d, search_ops=%d, flags=%u\n",
2812  level, search_ops, flags);
2813 
2814  CreateDirectoryA("test-dir", NULL);
2815  _lclose(_lcreat("test-dir\\file1", 0));
2816  _lclose(_lcreat("test-dir\\file2", 0));
2817  CreateDirectoryA("test-dir\\dir1", NULL);
2818  SetLastError(0xdeadbeef);
2819  handle = pFindFirstFileExA("test-dir\\*", level, &search_results, search_ops, NULL, flags);
2821  {
2822  win_skip("FindFirstFileExA is not implemented\n");
2823  goto cleanup;
2824  }
2826  {
2827  win_skip("FindFirstFileExA flag FIND_FIRST_EX_LARGE_FETCH not supported, skipping test\n");
2828  goto cleanup;
2829  }
2830  if ((level == FindExInfoBasic) && handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
2831  {
2832  win_skip("FindFirstFileExA level FindExInfoBasic not supported, skipping test\n");
2833  goto cleanup;
2834  }
2835 
2836 #define CHECK_NAME(fn) (strcmp((fn), "file1") == 0 || strcmp((fn), "file2") == 0 || strcmp((fn), "dir1") == 0)
2837 #define CHECK_LEVEL(fn) (level != FindExInfoBasic || !(fn)[0])
2838 
2839  ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
2840  ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
2841  ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2842 
2843  ok(FindNextFileA(handle, &search_results), "Fetching second file failed\n");
2844  ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
2845  ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2846 
2847  ok(FindNextFileA(handle, &search_results), "Fetching third file failed\n");
2848  ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
2849  ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2850 
2851  SetLastError(0xdeadbeef);
2852  ret = FindNextFileA(handle, &search_results);
2853  if (!ret && (GetLastError() == ERROR_NO_MORE_FILES) && (search_ops == FindExSearchLimitToDirectories))
2854  {
2855  skip("File system supports directory filtering\n");
2856  /* Results from the previous call are not cleared */
2857  ok(strcmp(search_results.cFileName, "dir1") == 0, "Third entry should be 'dir1' is %s\n", search_results.cFileName);
2858  ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2859 
2860  }
2861  else
2862  {
2863  ok(ret, "Fetching fourth file failed\n");
2864  ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
2865  ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2866 
2867  ok(FindNextFileA(handle, &search_results), "Fetching fifth file failed\n");
2868  ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName);
2869  ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
2870 
2871  ok(FindNextFileA(handle, &search_results) == FALSE, "Fetching sixth file should fail\n");
2872  }
2873 
2874 #undef CHECK_NAME
2875 #undef CHECK_LEVEL
2876 
2877  FindClose( handle );
2878 
2879  /* Most Windows systems seem to ignore the FIND_FIRST_EX_CASE_SENSITIVE flag. Unofficial documentation
2880  * suggests that there are registry keys and that it might depend on the used filesystem. */
2881  SetLastError(0xdeadbeef);
2882  handle = pFindFirstFileExA("TEST-DIR\\*", level, &search_results, search_ops, NULL, flags);
2883  if (flags & FIND_FIRST_EX_CASE_SENSITIVE)
2884  {
2886  "Unexpected error %x, expected valid handle or ERROR_PATH_NOT_FOUND\n", GetLastError());
2887  trace("FindFirstFileExA flag FIND_FIRST_EX_CASE_SENSITIVE is %signored\n",
2888  (handle == INVALID_HANDLE_VALUE) ? "not " : "");
2889  }
2890  else
2891  ok(handle != INVALID_HANDLE_VALUE, "Unexpected error %x, expected valid handle\n", GetLastError());
2892  if (handle != INVALID_HANDLE_VALUE)
2893  FindClose( handle );
2894 
2895 cleanup:
2896  DeleteFileA("test-dir\\file1");
2897  DeleteFileA("test-dir\\file2");
2898  RemoveDirectoryA("test-dir\\dir1");
2899  RemoveDirectoryA("test-dir");
2900 }
2901 
2903 {
2905  HANDLE handle;
2906  int i;
2907  static const char* files[] = {
2908  "..a", "..a.a", ".a", ".a..a", ".a.a", ".aaa",
2909  "a", "a..a", "a.a", "a.a.a", "aa", "aaa", "aaaa"
2910  };
2911  static const struct {
2912  int todo;
2913  const char *pattern, *result;
2914  } tests[] = {
2915  {0, "*.*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2916  {0, "*.*.", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2917  {0, ".*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa'"},
2918  {0, "*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2919  {0, ".*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa'"},
2920  {1, "*.", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
2921  {0, "*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2922  {1, "*..*", ", '.', '..', '..a', '..a.a', '.a..a', 'a..a'"},
2923  {1, "*..", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
2924  {1, ".*.", ", '.', '..', '.a', '.aaa'"},
2925  {0, "..*", ", '.', '..', '..a', '..a.a'"},
2926  {0, "**", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2927  {0, "**.", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2928  {0, "*. ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2929  {1, "* .", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
2930  {0, "* . ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2931  {0, "*.. ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
2932  {1, "*. .", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
2933  {1, "* ..", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
2934  {1, " *..", ", '.aaa'"},
2935  {0, "..* ", ", '.', '..', '..a', '..a.a'"},
2936  {1, "?", ", '.', '..', 'a'"},
2937  {1, "?.", ", '.', '..', 'a'"},
2938  {1, "?. ", ", '.', '..', 'a'"},
2939  {1, "??.", ", '.', '..', 'a', 'aa'"},
2940  {1, "??. ", ", '.', '..', 'a', 'aa'"},
2941  {1, "???.", ", '.', '..', 'a', 'aa', 'aaa'"},
2942  {1, "?.??.", ", '.', '..', '.a', 'a', 'a.a'"}
2943  };
2944 
2945  CreateDirectoryA("test-dir", NULL);
2946  SetCurrentDirectoryA("test-dir");
2947  for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
2948  _lclose(_lcreat(files[i], 0));
2949 
2950  for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
2951  {
2952  char correct[512];
2953  char incorrect[512];
2954  char missing[512];
2955 
2956  strcpy(missing, tests[i].result);
2957  correct[0] = incorrect[0] = 0;
2958 
2959  handle = FindFirstFileA(tests[i].pattern, &find_data);
2960  if (handle) do {
2961  char* ptr;
2962  char quoted[16];
2963 
2964  sprintf( quoted, ", '%.10s'", find_data.cFileName );
2965 
2966  if ((ptr = strstr(missing, quoted)))
2967  {
2968  int len = strlen(quoted);
2969  while ((ptr[0] = ptr[len]) != 0)
2970  ++ptr;
2971  strcat(correct, quoted);
2972  }
2973  else
2974  strcat(incorrect, quoted);
2975  } while (FindNextFileA(handle, &find_data));
2976  FindClose(handle);
2977 
2978  todo_wine_if (tests[i].todo)
2979  ok(missing[0] == 0 && incorrect[0] == 0,
2980  "FindFirstFile with '%s' found correctly %s, found incorrectly %s, and missed %s\n",
2981  tests[i].pattern,
2982  correct[0] ? correct+2 : "none",
2983  incorrect[0] ? incorrect+2 : "none",
2984  missing[0] ? missing+2 : "none");
2985  }
2986 
2987  for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
2988  DeleteFileA(files[i]);
2989  SetCurrentDirectoryA("..");
2990  RemoveDirectoryA("test-dir");
2991 }
2992 
2994 {
2999  if (*handle != INVALID_HANDLE_VALUE) {
3000 
3001  return 1;
3002  }
3003 
3004  return 0;
3005 }
3006 
3007 static void test_MapFile(void)
3008 {
3009  HANDLE handle;
3010  HANDLE hmap;
3011 
3012  ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
3013 
3014  hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" );
3015  ok( hmap != NULL, "mapping should work, I named it!\n" );
3016 
3017  ok( CloseHandle( hmap ), "can't close mapping handle\n");
3018 
3019  /* We have to close file before we try new stuff with mapping again.
3020  Else we would always succeed on XP or block descriptors on 95. */
3021  hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
3022  ok( hmap != NULL, "We should still be able to map!\n" );
3023  ok( CloseHandle( hmap ), "can't close mapping handle\n");
3024  ok( CloseHandle( handle ), "can't close file handle\n");
3025  handle = NULL;
3026 
3027  ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
3028 
3029  hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
3030  ok( hmap == NULL, "mapped zero size file\n");
3031  ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
3032 
3033  hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
3034  ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
3035  /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
3036  if ( hmap )
3037  CloseHandle( hmap );
3038 
3039  hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
3040  ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
3041  /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
3042  if ( hmap )
3043  CloseHandle( hmap );
3044 
3045  /* On XP you can now map again, on Win 95 you cannot. */
3046 
3047  ok( CloseHandle( handle ), "can't close file handle\n");
3048  ok( DeleteFileA( filename ), "DeleteFile failed after map\n" );
3049 }
3050 
3051 static void test_GetFileType(void)
3052 {
3053  DWORD type, type2;
3055  ok( h != INVALID_HANDLE_VALUE, "open %s failed\n", filename );
3056  type = GetFileType(h);
3057  ok( type == FILE_TYPE_DISK, "expected type disk got %d\n", type );
3058  CloseHandle( h );
3059  h = CreateFileA( "nul", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3060  ok( h != INVALID_HANDLE_VALUE, "open nul failed\n" );
3061  type = GetFileType(h);
3062  ok( type == FILE_TYPE_CHAR, "expected type char for nul got %d\n", type );
3063  CloseHandle( h );
3064  DeleteFileA( filename );
3066  ok( h != INVALID_HANDLE_VALUE, "GetStdHandle failed\n" );
3068  type2 = GetFileType( h );
3069  ok(type == type2, "expected type %d for STD_OUTPUT_HANDLE got %d\n", type2, type);
3070 }
3071 
3072 static int completion_count;
3073 
3074 static void CALLBACK FileIOComplete(DWORD dwError, DWORD dwBytes, LPOVERLAPPED ovl)
3075 {
3076 /* printf("(%ld, %ld, %p { %ld, %ld, %ld, %ld, %p })\n", dwError, dwBytes, ovl, ovl->Internal, ovl->InternalHigh, ovl->Offset, ovl->OffsetHigh, ovl->hEvent);*/
3077  ReleaseSemaphore(ovl->hEvent, 1, NULL);
3078  completion_count++;
3079 }
3080 
3081 static void test_async_file_errors(void)
3082 {
3083  char szFile[MAX_PATH];
3084  HANDLE hSem = CreateSemaphoreW(NULL, 1, 1, NULL);
3085  HANDLE hFile;
3086  LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096);
3087  OVERLAPPED ovl;
3088  S(U(ovl)).Offset = 0;
3089  S(U(ovl)).OffsetHigh = 0;
3090  ovl.hEvent = hSem;
3091  completion_count = 0;
3092  szFile[0] = '\0';
3093  GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini"));
3094  strcat(szFile, "\\win.ini");
3097  if (hFile == INVALID_HANDLE_VALUE) /* win9x doesn't like FILE_SHARE_DELETE */
3100  ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA(%s ...) failed\n", szFile);
3101  while (TRUE)
3102  {
3103  BOOL res;
3104  DWORD count;
3106  ;
3107  res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete);
3108  /*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
3109  if (!res)
3110  break;
3111  if (!GetOverlappedResult(hFile, &ovl, &count, FALSE))
3112  break;
3113  S(U(ovl)).Offset += count;
3114  /* i/o completion routine only called if ReadFileEx returned success.
3115  * we only care about violations of this rule so undo what should have
3116  * been done */
3117  completion_count--;
3118  }
3119  ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count);
3120  /*printf("Error = %ld\n", GetLastError());*/
3121  HeapFree(GetProcessHeap(), 0, lpBuffer);
3122 }
3123 
3126 {
3127  user_apc_ran = TRUE;
3128 }
3129 
3130 static void test_read_write(void)
3131 {
3132  DWORD bytes, ret, old_prot;
3133  HANDLE hFile;
3134  char temp_path[MAX_PATH];
3135  char filename[MAX_PATH];
3136  char *mem;
3137  static const char prefix[] = "pfx";
3138 
3139  ret = GetTempPathA(MAX_PATH, temp_path);
3140  ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
3141  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
3142 
3143  ret = GetTempFileNameA(temp_path, prefix, 0, filename);
3144  ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
3145 
3146  hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
3148  ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
3149 
3150  user_apc_ran = FALSE;
3151  if (pQueueUserAPC) {
3152  trace("Queueing an user APC\n"); /* verify the file is non alerable */
3153  ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
3154  ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
3155  }
3156 
3157  SetLastError(12345678);
3158  bytes = 12345678;
3159  ret = WriteFile(hFile, NULL, 0, &bytes, NULL);
3160  ok(ret && GetLastError() == 12345678,
3161  "ret = %d, error %d\n", ret, GetLastError());
3162  ok(!bytes, "bytes = %d\n", bytes);
3163 
3164  SetLastError(12345678);
3165  bytes = 12345678;
3166  ret = WriteFile(hFile, NULL, 10, &bytes, NULL);
3167  ok((!ret && GetLastError() == ERROR_INVALID_USER_BUFFER) || /* Win2k */
3168  (ret && GetLastError() == 12345678), /* Win9x */
3169  "ret = %d, error %d\n", ret, GetLastError());
3170  ok(!bytes || /* Win2k */
3171  bytes == 10, /* Win9x */
3172  "bytes = %d\n", bytes);
3173 
3174  /* make sure the file contains data */
3175  WriteFile(hFile, "this is the test data", 21, &bytes, NULL);
3176  SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
3177 
3178  SetLastError(12345678);
3179  bytes = 12345678;
3180  ret = ReadFile(hFile, NULL, 0, &bytes, NULL);
3181  ok(ret && GetLastError() == 12345678,
3182  "ret = %d, error %d\n", ret, GetLastError());
3183  ok(!bytes, "bytes = %d\n", bytes);
3184 
3185  SetLastError(12345678);
3186  bytes = 12345678;
3187  ret = ReadFile(hFile, NULL, 10, &bytes, NULL);
3188  ok(!ret && (GetLastError() == ERROR_NOACCESS || /* Win2k */
3189  GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
3190  "ret = %d, error %d\n", ret, GetLastError());
3191  ok(!bytes, "bytes = %d\n", bytes);
3192 
3193  ok(user_apc_ran == FALSE, "UserAPC ran, file using alertable io mode\n");
3194  if (pQueueUserAPC)
3195  SleepEx(0, TRUE); /* get rid of apc */
3196 
3197  /* test passing protected memory as buffer */
3198 
3199  mem = VirtualAlloc( NULL, 0x4000, MEM_COMMIT, PAGE_READWRITE );
3200  ok( mem != NULL, "failed to allocate virtual mem error %u\n", GetLastError() );
3201 
3202  ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
3203  ok( ret, "WriteFile failed error %u\n", GetLastError() );
3204  ok( bytes == 0x4000, "only wrote %x bytes\n", bytes );
3205 
3206  ret = VirtualProtect( mem + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
3207  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3208 
3209  ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
3210  ok( !ret, "WriteFile succeeded\n" );
3212  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3213  "wrong error %u\n", GetLastError() );
3214  ok( bytes == 0, "wrote %x bytes\n", bytes );
3215 
3216  ret = WriteFile( (HANDLE)0xdead, mem, 0x4000, &bytes, NULL );
3217  ok( !ret, "WriteFile succeeded\n" );
3218  ok( GetLastError() == ERROR_INVALID_HANDLE || /* handle is checked before buffer on NT */
3219  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3220  "wrong error %u\n", GetLastError() );
3221  ok( bytes == 0, "wrote %x bytes\n", bytes );
3222 
3223  ret = VirtualProtect( mem, 0x2000, PAGE_NOACCESS, &old_prot );
3224  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3225 
3226  ret = WriteFile( hFile, mem, 0x4000, &bytes, NULL );
3227  ok( !ret, "WriteFile succeeded\n" );
3229  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3230  "wrong error %u\n", GetLastError() );
3231  ok( bytes == 0, "wrote %x bytes\n", bytes );
3232 
3233  SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
3234 
3235  ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3236  ok( !ret, "ReadFile succeeded\n" );
3237  ok( GetLastError() == ERROR_NOACCESS ||
3238  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3239  "wrong error %u\n", GetLastError() );
3240  ok( bytes == 0, "read %x bytes\n", bytes );
3241 
3242  ret = VirtualProtect( mem, 0x2000, PAGE_READONLY, &old_prot );
3243  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3244 
3245  ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3246  ok( !ret, "ReadFile succeeded\n" );
3247  ok( GetLastError() == ERROR_NOACCESS ||
3248  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3249  "wrong error %u\n", GetLastError() );
3250  ok( bytes == 0, "read %x bytes\n", bytes );
3251 
3252  ret = VirtualProtect( mem, 0x2000, PAGE_READWRITE, &old_prot );
3253  ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
3254 
3255  ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3256  ok( !ret, "ReadFile succeeded\n" );
3257  ok( GetLastError() == ERROR_NOACCESS ||
3258  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3259  "wrong error %u\n", GetLastError() );
3260  ok( bytes == 0, "read %x bytes\n", bytes );
3261 
3262  SetFilePointer( hFile, 0x1234, NULL, FILE_BEGIN );
3263  SetEndOfFile( hFile );
3264  SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
3265 
3266  ret = ReadFile( hFile, mem, 0x4000, &bytes, NULL );
3267  ok( !ret, "ReadFile succeeded\n" );
3268  ok( GetLastError() == ERROR_NOACCESS ||
3269  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3270  "wrong error %u\n", GetLastError() );
3271  ok( bytes == 0, "read %x bytes\n", bytes );
3272 
3273  ret = ReadFile( hFile, mem, 0x2000, &bytes, NULL );
3274  ok( ret, "ReadFile failed error %u\n", GetLastError() );
3275  ok( bytes == 0x1234, "read %x bytes\n", bytes );
3276 
3277  ret = ReadFile( hFile, NULL, 1, &bytes, NULL );
3278  ok( !ret, "ReadFile succeeded\n" );
3279  ok( GetLastError() == ERROR_NOACCESS ||
3280  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
3281  "wrong error %u\n", GetLastError() );
3282  ok( bytes == 0, "read %x bytes\n", bytes );
3283 
3284  VirtualFree( mem, 0, MEM_RELEASE );
3285 
3286  ret = CloseHandle(hFile);
3287  ok( ret, "CloseHandle: error %d\n", GetLastError());
3288  ret = DeleteFileA(filename);
3289  ok( ret, "DeleteFileA: error %d\n", GetLastError());
3290 }
3291 
3292 static void test_OpenFile(void)
3293 {
3294  HFILE hFile;
3295  OFSTRUCT ofs;
3296  BOOL ret;
3297  DWORD retval;
3298 
3299  static const char file[] = "regedit.exe";
3300  static const char foo[] = ".\\foo-bar-foo.baz";
3301  static const char *foo_too_long = ".\\foo-bar-foo.baz+++++++++++++++"
3302  "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3303  "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3304  "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3305  "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
3306  "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
3307  char buff[MAX_PATH];
3308  char buff_long[4*MAX_PATH];
3309  char filled_0xA5[OFS_MAXPATHNAME];
3310  char *p;
3311  UINT length;
3312 
3313  /* Check for existing file */
3314  if (!pGetSystemWindowsDirectoryA)
3315  length = GetWindowsDirectoryA(buff, MAX_PATH);
3316  else
3317  length = pGetSystemWindowsDirectoryA(buff, MAX_PATH);
3318 
3319  if (length + sizeof(file) < MAX_PATH)
3320  {
3321  p = buff + strlen(buff);
3322  if (p > buff && p[-1] != '\\') *p++ = '\\';
3323  strcpy( p, file );
3324  memset(&ofs, 0xA5, sizeof(ofs));
3325  SetLastError(0xfaceabee);
3326 
3327  hFile = OpenFile(buff, &ofs, OF_EXIST);
3328  ok( hFile == TRUE, "%s not found : %d\n", buff, GetLastError() );
3329  ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3330  "GetLastError() returns %d\n", GetLastError() );
3331  ok( ofs.cBytes == sizeof(ofs), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3332  ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3333  ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3334  "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n",
3335  ofs.szPathName, buff );
3336  }
3337 
3338  memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
3339  length = GetCurrentDirectoryA(MAX_PATH, buff);
3340 
3341  /* Check for nonexistent file */
3342  if (length + sizeof(foo) < MAX_PATH)
3343  {
3344  p = buff + strlen(buff);
3345  if (p > buff && p[-1] != '\\') *p++ = '\\';
3346  strcpy( p, foo + 2 );
3347  memset(&ofs, 0xA5, sizeof(ofs));
3348  SetLastError(0xfaceabee);
3349 
3350  hFile = OpenFile(foo, &ofs, OF_EXIST);
3351  ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
3352  ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError() returns %d\n", GetLastError() );
3353  todo_wine
3354  ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3355  ok( ofs.nErrCode == ERROR_FILE_NOT_FOUND, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3356  ok( lstrcmpiA(ofs.szPathName, buff) == 0 || strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
3357  "OpenFile returned '%s', but was expected to return '%s' or string filled with 0xA5\n",
3358  ofs.szPathName, buff );
3359  }
3360 
3361  length = GetCurrentDirectoryA(MAX_PATH, buff_long);
3362  length += lstrlenA(foo_too_long + 1);
3363 
3364  /* Check for nonexistent file with too long filename */
3365  if (length >= OFS_MAXPATHNAME && length < sizeof(buff_long))
3366  {
3367  lstrcatA(buff_long, foo_too_long + 1); /* Avoid '.' during concatenation */
3368  memset(&ofs, 0xA5, sizeof(ofs));
3369  SetLastError(0xfaceabee);
3370 
3371  hFile = OpenFile(foo_too_long, &ofs, OF_EXIST);
3372  ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %d\n", GetLastError());
3374  "GetLastError() returns %d\n", GetLastError() );
3375  todo_wine
3376  ok( ofs.cBytes == 0xA5, "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3378  "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3379  ok( strncmp(ofs.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
3380  "OpenFile returned '%s', but was expected to return string filled with 0xA5\n",
3381  ofs.szPathName );
3382  }
3383 
3384  length = GetCurrentDirectoryA(MAX_PATH, buff) + sizeof(filename);
3385 
3386  if (length >= MAX_PATH)
3387  {
3388  trace("Buffer too small, requested length = %d, but MAX_PATH = %d. Skipping test.\n", length, MAX_PATH);
3389  return;
3390  }
3391  p = buff + strlen(buff);
3392  if (p > buff && p[-1] != '\\') *p++ = '\\';
3393  strcpy( p, filename );
3394 
3395  memset(&ofs, 0xA5, sizeof(ofs));
3396  SetLastError(0xfaceabee);
3397  /* Create an empty file */
3398  hFile = OpenFile(filename, &ofs, OF_CREATE);
3399  ok( hFile != HFILE_ERROR, "OpenFile failed to create nonexistent file\n" );
3400  ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3401  "GetLastError() returns %d\n", GetLastError() );
3402  ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3403  ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3404  "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3405  ret = _lclose(hFile);
3406  ok( !ret, "_lclose() returns %d\n", ret );
3407  retval = GetFileAttributesA(filename);
3408  ok( retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %d\n", GetLastError() );
3409 
3410  memset(&ofs, 0xA5, sizeof(ofs));
3411  SetLastError(0xfaceabee);
3412  /* Check various opening options: */
3413  /* for reading only, */
3414  hFile = OpenFile(filename, &ofs, OF_READ);
3415  ok( hFile != HFILE_ERROR, "OpenFile failed on read\n" );
3416  ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3417  "GetLastError() returns %d\n", GetLastError() );
3418  ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3419  ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3420  "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3421  ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3422  "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3423  ret = _lclose(hFile);
3424  ok( !ret, "_lclose() returns %d\n", ret );
3425 
3426  memset(&ofs, 0xA5, sizeof(ofs));
3427  SetLastError(0xfaceabee);
3428  /* for writing only, */
3429  hFile = OpenFile(filename, &ofs, OF_WRITE);
3430  ok( hFile != HFILE_ERROR, "OpenFile failed on write\n" );
3431  ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3432  "GetLastError() returns %d\n", GetLastError() );
3433  ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3434  ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3435  "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3436  ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3437  "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3438  ret = _lclose(hFile);
3439  ok( !ret, "_lclose() returns %d\n", ret );
3440 
3441  memset(&ofs, 0xA5, sizeof(ofs));
3442  SetLastError(0xfaceabee);
3443  /* for reading and writing, */
3444  hFile = OpenFile(filename, &ofs, OF_READWRITE);
3445  ok( hFile != HFILE_ERROR, "OpenFile failed on read/write\n" );
3446  ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3447  "GetLastError() returns %d\n", GetLastError() );
3448  ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3449  ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3450  "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3451  ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3452  "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3453  ret = _lclose(hFile);
3454  ok( !ret, "_lclose() returns %d\n", ret );
3455 
3456  memset(&ofs, 0xA5, sizeof(ofs));
3457  SetLastError(0xfaceabee);
3458  /* for checking file presence. */
3459  hFile = OpenFile(filename, &ofs, OF_EXIST);
3460  ok( hFile == 1, "OpenFile failed on finding our created file\n" );
3461  ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3462  "GetLastError() returns %d\n", GetLastError() );
3463  ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3464  ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3465  "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3466  ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3467  "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3468 
3469  memset(&ofs, 0xA5, sizeof(ofs));
3470  SetLastError(0xfaceabee);
3471  /* Delete the file and make sure it doesn't exist anymore */
3472  hFile = OpenFile(filename, &ofs, OF_DELETE);
3473  ok( hFile == 1, "OpenFile failed on delete (%d)\n", hFile );
3474  ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
3475  "GetLastError() returns %d\n", GetLastError() );
3476  ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
3477  ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
3478  "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
3479  ok( lstrcmpiA(ofs.szPathName, buff) == 0,
3480  "OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
3481 
3482  retval = GetFileAttributesA(filename);
3483  ok( retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file\n" );
3484 }
3485 
3486 static void test_overlapped(void)
3487 {
3488  OVERLAPPED ov;
3489  DWORD r, result;
3490 
3491  /* GetOverlappedResult crashes if the 2nd or 3rd param are NULL */
3492  if (0) /* tested: WinXP */
3493  {
3494  GetOverlappedResult(0, NULL, &result, FALSE);
3495  GetOverlappedResult(0, &ov, NULL, FALSE);
3497  }
3498 
3499  memset( &ov, 0, sizeof ov );
3500  result = 1;
3501  r = GetOverlappedResult(0, &ov, &result, 0);
3502  if (r)
3503  ok( result == 0, "wrong result %u\n", result );
3504  else /* win9x */
3505  ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3506 
3507  result = 0;
3508  ov.Internal = 0;
3509  ov.InternalHigh = 0xabcd;
3510  r = GetOverlappedResult(0, &ov, &result, 0);
3511  if (r)
3512  ok( result == 0xabcd, "wrong result %u\n", result );
3513  else /* win9x */
3514  ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3515 
3516  SetLastError( 0xb00 );
3517  result = 0;
3519  ov.InternalHigh = 0xabcd;
3520  r = GetOverlappedResult(0, &ov, &result, 0);
3521  ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
3522  ok( r == FALSE, "should return false\n");
3523  ok( result == 0xabcd || result == 0 /* win9x */, "wrong result %u\n", result );
3524 
3525  SetLastError( 0xb00 );
3526  result = 0;
3527  ov.Internal = STATUS_PENDING;
3528  ov.InternalHigh = 0xabcd;
3529  r = GetOverlappedResult(0, &ov, &result, 0);
3531  "wrong error %u\n", GetLastError() );
3532  ok( r == FALSE, "should return false\n");
3533  ok( result == 0, "wrong result %u\n", result );
3534 
3535  SetLastError( 0xb00 );
3536  ov.hEvent = CreateEventW( NULL, 1, 1, NULL );
3537  ov.Internal = STATUS_PENDING;
3538  ov.InternalHigh = 0xabcd;
3539  r = GetOverlappedResult(0, &ov, &result, 0);
3541  "wrong error %u\n", GetLastError() );
3542  ok( r == FALSE, "should return false\n");
3543 
3544  r = GetOverlappedResult( 0, &ov, &result, TRUE );
3545  ok( r == TRUE, "should return TRUE\n" );
3546  ok( result == 0xabcd, "wrong result %u\n", result );
3547  ok( ov.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", ov.Internal );
3548 
3549  ResetEvent( ov.hEvent );
3550 
3551  SetLastError( 0xb00 );
3552  ov.Internal = STATUS_PENDING;
3553  ov.InternalHigh = 0;
3554  r = GetOverlappedResult(0, &ov, &result, 0);
3556  "wrong error %u\n", GetLastError() );
3557  ok( r == FALSE, "should return false\n");
3558 
3559  r = CloseHandle( ov.hEvent );
3560  ok( r == TRUE, "close handle failed\n");
3561 }
3562 
3563 static void test_RemoveDirectory(void)
3564 {
3565  int rc;
3566  char directory[] = "removeme";
3567 
3568  rc = CreateDirectoryA(directory, NULL);
3569  ok( rc, "Createdirectory failed, gle=%d\n", GetLastError() );
3570 
3571  rc = SetCurrentDirectoryA(directory);
3572  ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
3573 
3574  rc = RemoveDirectoryA(".");
3575  if (!rc)
3576  {
3577  rc = SetCurrentDirectoryA("..");
3578  ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
3579 
3580  rc = RemoveDirectoryA(directory);
3581  ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
3582  }
3583 }
3584 
3585 static BOOL check_file_time( const FILETIME *ft1, const FILETIME *ft2, UINT tolerance )
3586 {
3587  ULONGLONG t1 = ((ULONGLONG)ft1->dwHighDateTime << 32) | ft1->dwLowDateTime;
3588  ULONGLONG t2 = ((ULONGLONG)ft2->dwHighDateTime << 32) | ft2->dwLowDateTime;
3589  return abs(t1 - t2) <= tolerance;
3590 }
3591 
3592 static void test_ReplaceFileA(void)
3593 {
3594  char replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
3595  HANDLE hReplacedFile, hReplacementFile, hBackupFile;
3596  static const char replacedData[] = "file-to-replace";
3597  static const char replacementData[] = "new-file";
3598  static const char backupData[] = "backup-file";
3599  FILETIME ftReplaced, ftReplacement, ftBackup;
3600  static const char prefix[] = "pfx";
3601  char temp_path[MAX_PATH];
3602  DWORD ret;
3603  BOOL retok, removeBackup = FALSE;
3604 
3605  if (!pReplaceFileA)
3606  {
3607  win_skip("ReplaceFileA() is missing\n");
3608  return;
3609  }
3610 
3611  ret = GetTempPathA(MAX_PATH, temp_path);
3612  ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
3613  ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
3614 
3615  ret = GetTempFileNameA(temp_path, prefix, 0, replaced);
3616  ok(ret != 0, "GetTempFileNameA error (replaced) %d\n", GetLastError());
3617 
3618  ret = GetTempFileNameA(temp_path, prefix, 0, replacement);
3619  ok(ret != 0, "GetTempFileNameA error (replacement) %d\n", GetLastError());
3620 
3621  ret = GetTempFileNameA(temp_path, prefix, 0, backup);
3622  ok(ret != 0, "GetTempFileNameA error (backup) %d\n", GetLastError());
3623 
3624  /* place predictable data in the file to be replaced */
3625  hReplacedFile = CreateFileA(replaced, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3626  ok(hReplacedFile != INVALID_HANDLE_VALUE,
3627  "failed to open replaced file\n");
3628  retok = WriteFile(hReplacedFile, replacedData, sizeof(replacedData), &ret, NULL );
3629  ok( retok && ret == sizeof(replacedData),
3630  "WriteFile error (replaced) %d\n", GetLastError());
3631  ok(GetFileSize(hReplacedFile, NULL) == sizeof(replacedData),
3632  "replaced file has wrong size\n");
3633  /* place predictable data in the file to be the replacement */
3634  hReplacementFile = CreateFileA(replacement, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3635  ok(hReplacementFile != INVALID_HANDLE_VALUE,
3636  "failed to open replacement file\n");
3637  retok = WriteFile(hReplacementFile, replacementData, sizeof(replacementData), &ret, NULL );
3638  ok( retok && ret == sizeof(replacementData),
3639  "WriteFile error (replacement) %d\n", GetLastError());
3640  ok(GetFileSize(hReplacementFile, NULL) == sizeof(replacementData),
3641  "replacement file has wrong size\n");
3642  /* place predictable data in the backup file (to be over-written) */
3643  hBackupFile = CreateFileA(backup, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
3644  ok(hBackupFile != INVALID_HANDLE_VALUE,
3645  "failed to open backup file\n");
3646  retok = WriteFile(hBackupFile, backupData, sizeof(backupData), &ret, NULL );
3647  ok( retok && ret == sizeof(backupData),
3648  "WriteFile error (replacement) %d\n", GetLastError());
3649  ok(GetFileSize(hBackupFile, NULL) == sizeof(backupData),
3650  "backup file has wrong size\n");
3651  /* change the filetime on the "replaced" file to ensure that it changes */
3652  ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3653  ok( ret, "GetFileTime error (replaced) %d\n", GetLastError());
3654  ftReplaced.dwLowDateTime -= 600000000; /* 60 second */
3655  ret = SetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
3656  ok( ret, "SetFileTime error (replaced) %d\n", GetLastError());
3657  GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced); /* get the actual time back */
3658  CloseHandle(hReplacedFile);
3659  /* change the filetime on the backup to ensure that it changes */
3660  ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3661  ok( ret, "GetFileTime error (backup) %d\n", GetLastError());
3662  ftBackup.dwLowDateTime -= 1200000000; /* 120 second */
3663  ret = SetFileTime(hBackupFile, NULL, NULL, &ftBackup);
3664  ok( ret, "SetFileTime error (backup) %d\n", GetLastError());
3665  GetFileTime(hBackupFile, NULL, NULL, &ftBackup); /* get the actual time back */
3666  CloseHandle(hBackupFile);
3667  /* get the filetime on the replacement file to perform checks */
3668  ret = GetFileTime(hReplacementFile, NULL, NULL, &ftReplacement);
3669  ok( ret, "GetFileTime error (replacement) %d\n", GetLastError());