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