[NTDLL_WINETEST] Sync with Wine Staging 2.16. CORE-13762
[reactos.git] / modules / rostests / winetests / ntdll / file.c
1 /* Unit test suite for Ntdll file functions
2 *
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2011 Dmitry Timoshkov
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 *
22 * NOTES
23 * We use function pointers here as there is no import library for NTDLL on
24 * windows.
25 */
26
27 #include <stdio.h>
28 #include <stdarg.h>
29
30 #include "ntstatus.h"
31 /* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
32 * definition errors when we get to winnt.h
33 */
34 #define WIN32_NO_STATUS
35
36 #include "wine/test.h"
37 #include "wine/winternl.h"
38 #include "winuser.h"
39 #include "wine/winioctl.h"
40
41 /* FIXME */
42 typedef struct _REPARSE_DATA_BUFFER {
43 ULONG ReparseTag;
44 USHORT ReparseDataLength;
45 USHORT Reserved;
46 _ANONYMOUS_UNION union {
47 struct {
48 USHORT SubstituteNameOffset;
49 USHORT SubstituteNameLength;
50 USHORT PrintNameOffset;
51 USHORT PrintNameLength;
52 ULONG Flags;
53 WCHAR PathBuffer[1];
54 } SymbolicLinkReparseBuffer;
55 struct {
56 USHORT SubstituteNameOffset;
57 USHORT SubstituteNameLength;
58 USHORT PrintNameOffset;
59 USHORT PrintNameLength;
60 WCHAR PathBuffer[1];
61 } MountPointReparseBuffer;
62 struct {
63 UCHAR DataBuffer[1];
64 } GenericReparseBuffer;
65 } DUMMYUNIONNAME;
66 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
67
68 #ifndef IO_COMPLETION_ALL_ACCESS
69 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
70 #endif
71
72 static BOOL (WINAPI * pGetVolumePathNameW)(LPCWSTR, LPWSTR, DWORD);
73 static UINT (WINAPI *pGetSystemWow64DirectoryW)( LPWSTR, UINT );
74
75 static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
76 static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
77 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
78 static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
79
80 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
81 ULONG, ULONG, ULONG, PLARGE_INTEGER );
82 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
83 static NTSTATUS (WINAPI *pNtOpenFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
84 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
85 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
86 PIO_APC_ROUTINE apc, void* apc_user,
87 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
88 PLARGE_INTEGER offset, PULONG key);
89 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
90 PIO_APC_ROUTINE apc, void* apc_user,
91 PIO_STATUS_BLOCK io_status,
92 const void* buffer, ULONG length,
93 PLARGE_INTEGER offset, PULONG key);
94 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
95 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
96 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
97 static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size);
98
99 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
100 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
101 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
102 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
103 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
104 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
105 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
106 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
107 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
108 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
109 static NTSTATUS (WINAPI *pNtQueryFullAttributesFile)(const OBJECT_ATTRIBUTES*, FILE_NETWORK_OPEN_INFORMATION*);
110 static NTSTATUS (WINAPI *pNtFlushBuffersFile)(HANDLE, IO_STATUS_BLOCK*);
111 static NTSTATUS (WINAPI *pNtQueryEaFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,BOOLEAN,PVOID,ULONG,PULONG,BOOLEAN);
112
113 static inline BOOL is_signaled( HANDLE obj )
114 {
115 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
116 }
117
118 #define TEST_BUF_LEN 3
119
120 static HANDLE create_temp_file( ULONG flags )
121 {
122 char path[MAX_PATH], buffer[MAX_PATH];
123 HANDLE handle;
124
125 GetTempPathA( MAX_PATH, path );
126 GetTempFileNameA( path, "foo", 0, buffer );
127 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
128 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
129 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
130 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
131 }
132
133 #define CVALUE_FIRST 0xfffabbcc
134 #define CKEY_FIRST 0x1030341
135 #define CKEY_SECOND 0x132E46
136
137 static ULONG_PTR completionKey;
138 static IO_STATUS_BLOCK ioSb;
139 static ULONG_PTR completionValue;
140
141 static ULONG get_pending_msgs(HANDLE h)
142 {
143 NTSTATUS res;
144 ULONG a, req;
145
146 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
147 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
148 if (res != STATUS_SUCCESS) return -1;
149 ok( req == sizeof(a), "Unexpected response size: %x\n", req );
150 return a;
151 }
152
153 static BOOL get_msg(HANDLE h)
154 {
155 LARGE_INTEGER timeout = {{-10000000*3}};
156 DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
157 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
158 if (res != STATUS_SUCCESS)
159 {
160 completionKey = completionValue = 0;
161 memset(&ioSb, 0, sizeof(ioSb));
162 return FALSE;
163 }
164 return TRUE;
165 }
166
167
168 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
169 {
170 int *count = arg;
171
172 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
173 iosb, U(*iosb).Status, iosb->Information );
174 (*count)++;
175 ok( !reserved, "reserved is not 0: %x\n", reserved );
176 }
177
178 static void create_file_test(void)
179 {
180 static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0};
181 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
182 '\\','f','a','i','l','i','n','g',0};
183 static const WCHAR systemrootExplorerW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
184 '\\','e','x','p','l','o','r','e','r','.','e','x','e',0};
185 static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
186 static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
187 static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
188 static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
189 static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
190 static const char testdata[] = "Hello World";
191 static const WCHAR sepW[] = {'\\',0};
192 FILE_NETWORK_OPEN_INFORMATION info;
193 NTSTATUS status;
194 HANDLE dir, file;
195 WCHAR path[MAX_PATH], temp[MAX_PATH];
196 OBJECT_ATTRIBUTES attr;
197 IO_STATUS_BLOCK io;
198 UNICODE_STRING nameW;
199 LARGE_INTEGER offset;
200 char buf[32];
201 DWORD ret;
202
203 GetCurrentDirectoryW( MAX_PATH, path );
204 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
205 attr.Length = sizeof(attr);
206 attr.RootDirectory = 0;
207 attr.ObjectName = &nameW;
208 attr.Attributes = OBJ_CASE_INSENSITIVE;
209 attr.SecurityDescriptor = NULL;
210 attr.SecurityQualityOfService = NULL;
211
212 /* try various open modes and options on directories */
213 status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0,
214 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
215 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
216
217 U(io).Status = 0xdeadbeef;
218 offset.QuadPart = 0;
219 status = pNtReadFile( dir, NULL, NULL, NULL, &io, buf, sizeof(buf), &offset, NULL );
220 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtReadFile error %08x\n", status );
221 if (status == STATUS_PENDING)
222 {
223 ret = WaitForSingleObject( dir, 1000 );
224 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
225 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
226 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
227 }
228
229 U(io).Status = 0xdeadbeef;
230 offset.QuadPart = 0;
231 status = pNtWriteFile( dir, NULL, NULL, NULL, &io, testdata, sizeof(testdata), &offset, NULL);
232 todo_wine
233 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtWriteFile error %08x\n", status );
234 if (status == STATUS_PENDING)
235 {
236 ret = WaitForSingleObject( dir, 1000 );
237 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
238 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
239 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
240 }
241
242 CloseHandle( dir );
243
244 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
245 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
246 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
247 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
248
249 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
250 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
251 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
252 CloseHandle( dir );
253
254 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
255 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
256 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
257
258 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
259 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
260 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
261
262 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
263 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
264 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
265
266 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
267 FILE_OPEN, 0, NULL, 0 );
268 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
269 CloseHandle( dir );
270
271 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
272 FILE_CREATE, 0, NULL, 0 );
273 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
274 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
275
276 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
277 FILE_OPEN_IF, 0, NULL, 0 );
278 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
279 CloseHandle( dir );
280
281 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
282 FILE_SUPERSEDE, 0, NULL, 0 );
283 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
284 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
285
286 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
287 FILE_OVERWRITE, 0, NULL, 0 );
288 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
289 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
290
291 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
292 FILE_OVERWRITE_IF, 0, NULL, 0 );
293 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
294 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
295
296 pRtlFreeUnicodeString( &nameW );
297
298 pRtlInitUnicodeString( &nameW, systemrootW );
299 attr.Length = sizeof(attr);
300 attr.RootDirectory = NULL;
301 attr.ObjectName = &nameW;
302 attr.Attributes = OBJ_CASE_INSENSITIVE;
303 attr.SecurityDescriptor = NULL;
304 attr.SecurityQualityOfService = NULL;
305 dir = NULL;
306 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
307 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
308 todo_wine
309 ok( status == STATUS_INVALID_PARAMETER,
310 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
311
312 /* Invalid chars in file/dirnames */
313 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
314 attr.ObjectName = &nameW;
315 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
316 FILE_SHARE_READ, FILE_CREATE,
317 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
318 ok(status == STATUS_OBJECT_NAME_INVALID,
319 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
320
321 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
322 0, FILE_CREATE,
323 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
324 ok(status == STATUS_OBJECT_NAME_INVALID,
325 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
326 pRtlFreeUnicodeString(&nameW);
327
328 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
329 attr.ObjectName = &nameW;
330 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
331 FILE_SHARE_READ, FILE_CREATE,
332 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
333 ok(status == STATUS_OBJECT_NAME_INVALID,
334 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
335
336 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
337 0, FILE_CREATE,
338 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
339 ok(status == STATUS_OBJECT_NAME_INVALID,
340 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
341 pRtlFreeUnicodeString(&nameW);
342
343 pRtlInitUnicodeString( &nameW, pathInvalidNtW );
344 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
345 FILE_SHARE_READ, FILE_CREATE,
346 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
347 ok( status == STATUS_OBJECT_NAME_INVALID,
348 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
349
350 status = pNtQueryFullAttributesFile( &attr, &info );
351 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
352 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
353
354 pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
355 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
356 FILE_SHARE_READ, FILE_CREATE,
357 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
358 ok( status == STATUS_OBJECT_NAME_INVALID,
359 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
360
361 status = pNtQueryFullAttributesFile( &attr, &info );
362 ok( status == STATUS_OBJECT_NAME_INVALID,
363 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
364
365 pRtlInitUnicodeString( &nameW, pathInvalidDosW );
366 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
367 FILE_SHARE_READ, FILE_CREATE,
368 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
369 ok( status == STATUS_OBJECT_NAME_INVALID,
370 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
371
372 status = pNtQueryFullAttributesFile( &attr, &info );
373 ok( status == STATUS_OBJECT_NAME_INVALID,
374 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
375
376 GetWindowsDirectoryW( path, MAX_PATH );
377 path[2] = 0;
378 ok( QueryDosDeviceW( path, temp, MAX_PATH ),
379 "QueryDosDeviceW failed with error %u\n", GetLastError() );
380 lstrcatW( temp, sepW );
381 lstrcatW( temp, path+3 );
382 lstrcatW( temp, sepW );
383 lstrcatW( temp, notepadW );
384
385 pRtlInitUnicodeString( &nameW, temp );
386 status = pNtQueryFullAttributesFile( &attr, &info );
387 ok( status == STATUS_SUCCESS,
388 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
389
390 pRtlInitUnicodeString( &nameW, systemrootExplorerW );
391 status = pNtQueryFullAttributesFile( &attr, &info );
392 ok( status == STATUS_SUCCESS,
393 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
394 }
395
396 static void open_file_test(void)
397 {
398 static const char testdata[] = "Hello World";
399 static WCHAR fooW[] = {'f','o','o',0};
400 NTSTATUS status;
401 HANDLE dir, root, handle, file;
402 WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
403 BYTE data[1024];
404 OBJECT_ATTRIBUTES attr;
405 IO_STATUS_BLOCK io;
406 UNICODE_STRING nameW;
407 UINT i, len;
408 BOOL ret, restart = TRUE;
409 DWORD numbytes;
410
411 len = GetWindowsDirectoryW( path, MAX_PATH );
412 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
413 attr.Length = sizeof(attr);
414 attr.RootDirectory = 0;
415 attr.ObjectName = &nameW;
416 attr.Attributes = OBJ_CASE_INSENSITIVE;
417 attr.SecurityDescriptor = NULL;
418 attr.SecurityQualityOfService = NULL;
419 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
420 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
421 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
422 pRtlFreeUnicodeString( &nameW );
423
424 path[3] = 0; /* root of the drive */
425 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
426 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
427 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
428 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
429 pRtlFreeUnicodeString( &nameW );
430
431 /* test opening system dir with RootDirectory set to windows dir */
432 GetSystemDirectoryW( path, MAX_PATH );
433 while (path[len] == '\\') len++;
434 nameW.Buffer = path + len;
435 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
436 attr.RootDirectory = dir;
437 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
438 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
439 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
440 CloseHandle( handle );
441
442 /* try uppercase name */
443 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
444 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
445 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
446 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
447 CloseHandle( handle );
448
449 /* try with leading backslash */
450 nameW.Buffer--;
451 nameW.Length += sizeof(WCHAR);
452 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
453 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
454 ok( status == STATUS_INVALID_PARAMETER ||
455 status == STATUS_OBJECT_NAME_INVALID ||
456 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
457 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
458 if (!status) CloseHandle( handle );
459
460 /* try with empty name */
461 nameW.Length = 0;
462 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
463 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
464 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
465 CloseHandle( handle );
466
467 /* try open by file id */
468
469 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
470 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
471 {
472 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
473
474 restart = FALSE;
475
476 if (!info->FileId.QuadPart) continue;
477
478 nameW.Buffer = (WCHAR *)&info->FileId;
479 nameW.Length = sizeof(info->FileId);
480 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
481 attr.RootDirectory = dir;
482 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
483 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
484 FILE_SHARE_READ,
485 FILE_OPEN_BY_FILE_ID |
486 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
487 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
488 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
489 if (status == STATUS_NOT_IMPLEMENTED)
490 {
491 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
492 break;
493 }
494 if (status == STATUS_SHARING_VIOLATION)
495 trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
496 if (!status)
497 {
498 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
499
500 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
501 {
502 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
503
504 /* check that it's the same file/directory */
505
506 /* don't check the size for directories */
507 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
508 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
509 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
510
511 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
512 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
513 }
514 CloseHandle( handle );
515
516 /* try same thing from drive root */
517 attr.RootDirectory = root;
518 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
519 FILE_SHARE_READ|FILE_SHARE_WRITE,
520 FILE_OPEN_BY_FILE_ID |
521 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
522 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
523 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
524 if (!status) CloseHandle( handle );
525 }
526 }
527
528 CloseHandle( dir );
529 CloseHandle( root );
530
531 GetTempPathW( MAX_PATH, path );
532 GetTempFileNameW( path, fooW, 0, tmpfile );
533 pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
534
535 file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
536 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
537 numbytes = 0xdeadbeef;
538 ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
539 ok( ret, "WriteFile failed with error %u\n", GetLastError() );
540 ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
541 CloseHandle( file );
542
543 attr.Length = sizeof(attr);
544 attr.RootDirectory = 0;
545 attr.ObjectName = &nameW;
546 attr.Attributes = OBJ_CASE_INSENSITIVE;
547 attr.SecurityDescriptor = NULL;
548 attr.SecurityQualityOfService = NULL;
549 status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
550 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
551 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
552 pRtlFreeUnicodeString( &nameW );
553
554 numbytes = 0xdeadbeef;
555 memset( data, 0, sizeof(data) );
556 ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
557 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
558 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
559 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
560
561 nameW.Length = sizeof(fooW) - sizeof(WCHAR);
562 nameW.Buffer = fooW;
563 attr.RootDirectory = file;
564 attr.ObjectName = &nameW;
565 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
566 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
567 ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
568 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
569
570 nameW.Length = 0;
571 nameW.Buffer = NULL;
572 attr.RootDirectory = file;
573 attr.ObjectName = &nameW;
574 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
575 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
576 ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
577
578 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
579 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
580 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
581 ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
582
583 numbytes = 0xdeadbeef;
584 memset( data, 0, sizeof(data) );
585 ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
586 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
587 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
588 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
589
590 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
591 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
592 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
593 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
594
595 CloseHandle( file );
596 CloseHandle( root );
597 DeleteFileW( tmpfile );
598 }
599
600 static void delete_file_test(void)
601 {
602 NTSTATUS ret;
603 OBJECT_ATTRIBUTES attr;
604 UNICODE_STRING nameW;
605 WCHAR pathW[MAX_PATH];
606 WCHAR pathsubW[MAX_PATH];
607 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
608 static const WCHAR subdirW[] = {'\\','s','u','b',0};
609
610 ret = GetTempPathW(MAX_PATH, pathW);
611 if (!ret)
612 {
613 ok(0, "couldn't get temp dir\n");
614 return;
615 }
616 if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
617 {
618 ok(0, "MAX_PATH exceeded in constructing paths\n");
619 return;
620 }
621
622 lstrcatW(pathW, testdirW);
623 lstrcpyW(pathsubW, pathW);
624 lstrcatW(pathsubW, subdirW);
625
626 ret = CreateDirectoryW(pathW, NULL);
627 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
628 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
629 {
630 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
631 return;
632 }
633
634 attr.Length = sizeof(attr);
635 attr.RootDirectory = 0;
636 attr.Attributes = OBJ_CASE_INSENSITIVE;
637 attr.ObjectName = &nameW;
638 attr.SecurityDescriptor = NULL;
639 attr.SecurityQualityOfService = NULL;
640
641 /* test NtDeleteFile on an empty directory */
642 ret = pNtDeleteFile(&attr);
643 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
644 ret = RemoveDirectoryW(pathW);
645 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
646
647 /* test NtDeleteFile on a non-empty directory */
648 ret = CreateDirectoryW(pathW, NULL);
649 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
650 ret = CreateDirectoryW(pathsubW, NULL);
651 ok(ret == TRUE, "couldn't create directory subdir\n");
652 ret = pNtDeleteFile(&attr);
653 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
654 ret = RemoveDirectoryW(pathsubW);
655 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
656 ret = RemoveDirectoryW(pathW);
657 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
658
659 pRtlFreeUnicodeString( &nameW );
660 }
661
662 static void read_file_test(void)
663 {
664 const char text[] = "foobar";
665 HANDLE handle;
666 IO_STATUS_BLOCK iosb;
667 NTSTATUS status;
668 int apc_count = 0;
669 char buffer[128];
670 LARGE_INTEGER offset;
671 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
672
673 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
674 apc_count = 0;
675 U(iosb).Status = 0xdeadbabe;
676 iosb.Information = 0xdeadbeef;
677 offset.QuadPart = 0;
678 ResetEvent( event );
679 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
680 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
681 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
682 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
683 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
684 ok( is_signaled( event ), "event is not signaled\n" );
685 ok( !apc_count, "apc was called\n" );
686 SleepEx( 1, TRUE ); /* alertable sleep */
687 ok( apc_count == 1, "apc was not called\n" );
688
689 apc_count = 0;
690 U(iosb).Status = 0xdeadbabe;
691 iosb.Information = 0xdeadbeef;
692 offset.QuadPart = 0;
693 ResetEvent( event );
694 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
695 ok( status == STATUS_SUCCESS ||
696 status == STATUS_PENDING, /* vista */
697 "wrong status %x\n", status );
698 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
699 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
700 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
701 ok( is_signaled( event ), "event is not signaled\n" );
702 ok( !apc_count, "apc was called\n" );
703 SleepEx( 1, TRUE ); /* alertable sleep */
704 ok( apc_count == 1, "apc was not called\n" );
705
706 /* read beyond eof */
707 apc_count = 0;
708 U(iosb).Status = 0xdeadbabe;
709 iosb.Information = 0xdeadbeef;
710 offset.QuadPart = strlen(text) + 2;
711 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
712 ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
713 if (status == STATUS_PENDING) /* vista */
714 {
715 WaitForSingleObject( event, 1000 );
716 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
717 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
718 ok( is_signaled( event ), "event is not signaled\n" );
719 ok( !apc_count, "apc was called\n" );
720 SleepEx( 1, TRUE ); /* alertable sleep */
721 ok( apc_count == 1, "apc was not called\n" );
722 }
723 CloseHandle( handle );
724
725 /* now a non-overlapped file */
726 if (!(handle = create_temp_file(0))) return;
727 apc_count = 0;
728 U(iosb).Status = 0xdeadbabe;
729 iosb.Information = 0xdeadbeef;
730 offset.QuadPart = 0;
731 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
732 ok( status == STATUS_END_OF_FILE ||
733 status == STATUS_SUCCESS ||
734 status == STATUS_PENDING, /* vista */
735 "wrong status %x\n", status );
736 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
737 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
738 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
739 ok( is_signaled( event ), "event is not signaled\n" );
740 ok( !apc_count, "apc was called\n" );
741 SleepEx( 1, TRUE ); /* alertable sleep */
742 ok( apc_count == 1, "apc was not called\n" );
743
744 apc_count = 0;
745 U(iosb).Status = 0xdeadbabe;
746 iosb.Information = 0xdeadbeef;
747 offset.QuadPart = 0;
748 ResetEvent( event );
749 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
750 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
751 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
752 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
753 ok( is_signaled( event ), "event is not signaled\n" );
754 ok( !apc_count, "apc was called\n" );
755 SleepEx( 1, TRUE ); /* alertable sleep */
756 todo_wine ok( !apc_count, "apc was called\n" );
757
758 /* read beyond eof */
759 apc_count = 0;
760 U(iosb).Status = 0xdeadbabe;
761 iosb.Information = 0xdeadbeef;
762 offset.QuadPart = strlen(text) + 2;
763 ResetEvent( event );
764 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
765 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
766 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
767 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
768 ok( is_signaled( event ), "event is not signaled\n" );
769 ok( !apc_count, "apc was called\n" );
770 SleepEx( 1, TRUE ); /* alertable sleep */
771 ok( !apc_count, "apc was called\n" );
772
773 CloseHandle( handle );
774
775 CloseHandle( event );
776 }
777
778 static void append_file_test(void)
779 {
780 static const char text[6] = "foobar";
781 HANDLE handle;
782 NTSTATUS status;
783 IO_STATUS_BLOCK iosb;
784 LARGE_INTEGER offset;
785 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
786 DWORD ret;
787
788 GetTempPathA( MAX_PATH, path );
789 GetTempFileNameA( path, "foo", 0, buffer );
790
791 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
792 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
793
794 U(iosb).Status = -1;
795 iosb.Information = -1;
796 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
797 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
798 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
799 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
800
801 CloseHandle(handle);
802
803 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
804 It matches the O_WRONLY|O_APPEND open() posix behavior */
805 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
806 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
807
808 U(iosb).Status = -1;
809 iosb.Information = -1;
810 offset.QuadPart = 1;
811 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
812 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
813 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
814 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
815
816 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
817 ok(ret == 4, "expected 4, got %u\n", ret);
818
819 U(iosb).Status = -1;
820 iosb.Information = -1;
821 offset.QuadPart = 3;
822 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
823 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
824 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
825 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
826
827 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
828 ok(ret == 6, "expected 6, got %u\n", ret);
829
830 CloseHandle(handle);
831
832 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
833 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
834
835 memset(buf, 0, sizeof(buf));
836 U(iosb).Status = -1;
837 iosb.Information = -1;
838 offset.QuadPart = 0;
839 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
840 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
841 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
842 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
843 buf[6] = 0;
844 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
845
846 U(iosb).Status = -1;
847 iosb.Information = -1;
848 offset.QuadPart = 0;
849 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
850 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
851 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
852 ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
853
854 memset(buf, 0, sizeof(buf));
855 U(iosb).Status = -1;
856 iosb.Information = -1;
857 offset.QuadPart = 0;
858 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
859 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
860 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
861 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
862 buf[6] = 0;
863 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
864
865 CloseHandle(handle);
866 DeleteFileA(buffer);
867 }
868
869 static void nt_mailslot_test(void)
870 {
871 HANDLE hslot;
872 ACCESS_MASK DesiredAccess;
873 OBJECT_ATTRIBUTES attr;
874
875 ULONG CreateOptions;
876 ULONG MailslotQuota;
877 ULONG MaxMessageSize;
878 LARGE_INTEGER TimeOut;
879 IO_STATUS_BLOCK IoStatusBlock;
880 NTSTATUS rc;
881 UNICODE_STRING str;
882 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
883 'R',':','\\','F','R','E','D','\0' };
884
885 TimeOut.QuadPart = -1;
886
887 pRtlInitUnicodeString(&str, buffer1);
888 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
889 CreateOptions = MailslotQuota = MaxMessageSize = 0;
890 DesiredAccess = GENERIC_READ;
891
892 /*
893 * Check for NULL pointer handling
894 */
895 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
896 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
897 &TimeOut);
898 ok( rc == STATUS_ACCESS_VIOLATION ||
899 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
900 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
901
902 /*
903 * Test to see if the Timeout can be NULL
904 */
905 hslot = (HANDLE)0xdeadbeef;
906 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
907 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
908 NULL);
909 ok( rc == STATUS_SUCCESS ||
910 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
911 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
912 ok( hslot != 0, "Handle is invalid\n");
913
914 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
915
916 /*
917 * Test a valid call
918 */
919 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
920 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
921 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
922 &TimeOut);
923 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
924 ok( hslot != 0, "Handle is invalid\n");
925
926 rc = pNtClose(hslot);
927 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
928 }
929
930 static void test_iocp_setcompletion(HANDLE h)
931 {
932 NTSTATUS res;
933 ULONG count;
934 SIZE_T size = 3;
935
936 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
937
938 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
939 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
940
941 count = get_pending_msgs(h);
942 ok( count == 1, "Unexpected msg count: %d\n", count );
943
944 if (get_msg(h))
945 {
946 ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
947 ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
948 ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
949 ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
950 }
951
952 count = get_pending_msgs(h);
953 ok( !count, "Unexpected msg count: %d\n", count );
954 }
955
956 static void test_iocp_fileio(HANDLE h)
957 {
958 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
959
960 IO_STATUS_BLOCK iosb;
961 FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
962 HANDLE hPipeSrv, hPipeClt;
963 NTSTATUS res;
964
965 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
966 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
967 if (hPipeSrv != INVALID_HANDLE_VALUE )
968 {
969 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
970 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
971 if (hPipeClt != INVALID_HANDLE_VALUE)
972 {
973 U(iosb).Status = 0xdeadbeef;
974 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
975 ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
976 ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
977 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
978 CloseHandle(hPipeClt);
979 }
980 CloseHandle( hPipeSrv );
981 }
982
983 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
984 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
985 if (hPipeSrv == INVALID_HANDLE_VALUE )
986 return;
987
988 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
989 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
990 if (hPipeClt != INVALID_HANDLE_VALUE)
991 {
992 OVERLAPPED o = {0,};
993 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
994 DWORD read;
995 long count;
996
997 U(iosb).Status = 0xdeadbeef;
998 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
999 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1000 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1001
1002 memset( send_buf, 0, TEST_BUF_LEN );
1003 memset( recv_buf, 0xde, TEST_BUF_LEN );
1004 count = get_pending_msgs(h);
1005 ok( !count, "Unexpected msg count: %ld\n", count );
1006 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1007 count = get_pending_msgs(h);
1008 ok( !count, "Unexpected msg count: %ld\n", count );
1009 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1010
1011 if (get_msg(h))
1012 {
1013 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1014 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1015 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1016 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1017 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1018 }
1019 count = get_pending_msgs(h);
1020 ok( !count, "Unexpected msg count: %ld\n", count );
1021
1022 memset( send_buf, 0, TEST_BUF_LEN );
1023 memset( recv_buf, 0xde, TEST_BUF_LEN );
1024 WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1025 count = get_pending_msgs(h);
1026 ok( !count, "Unexpected msg count: %ld\n", count );
1027 ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1028 count = get_pending_msgs(h);
1029 ok( count == 1, "Unexpected msg count: %ld\n", count );
1030 if (get_msg(h))
1031 {
1032 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1033 ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1034 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1035 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1036 ok( !memcmp( send_buf, recv_buf, 2 ), "Receive buffer (%x %x) did not match send buffer (%x %x)\n", recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
1037 }
1038
1039 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1040 CloseHandle( hPipeSrv );
1041 count = get_pending_msgs(h);
1042 ok( count == 1, "Unexpected msg count: %ld\n", count );
1043 if (get_msg(h))
1044 {
1045 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1046 ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1047 /* wine sends wrong status here */
1048 ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1049 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1050 }
1051 }
1052
1053 CloseHandle( hPipeClt );
1054
1055 /* test associating a completion port with a handle after an async is queued */
1056 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1057 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1058 if (hPipeSrv == INVALID_HANDLE_VALUE )
1059 return;
1060 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1061 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1062 if (hPipeClt != INVALID_HANDLE_VALUE)
1063 {
1064 OVERLAPPED o = {0,};
1065 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1066 int apc_count = 0;
1067 DWORD read;
1068 long count;
1069
1070 memset( send_buf, 0, TEST_BUF_LEN );
1071 memset( recv_buf, 0xde, TEST_BUF_LEN );
1072 count = get_pending_msgs(h);
1073 ok( !count, "Unexpected msg count: %ld\n", count );
1074 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1075
1076 U(iosb).Status = 0xdeadbeef;
1077 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1078 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1079 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1080 count = get_pending_msgs(h);
1081 ok( !count, "Unexpected msg count: %ld\n", count );
1082
1083 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1084
1085 if (get_msg(h))
1086 {
1087 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1088 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1089 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1090 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1091 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1092 }
1093 count = get_pending_msgs(h);
1094 ok( !count, "Unexpected msg count: %ld\n", count );
1095
1096 /* using APCs on handle with associated completion port is not allowed */
1097 res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1098 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1099 }
1100
1101 CloseHandle( hPipeSrv );
1102 CloseHandle( hPipeClt );
1103
1104 /* test associating a completion port with a handle after an async using APC is queued */
1105 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1106 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1107 if (hPipeSrv == INVALID_HANDLE_VALUE )
1108 return;
1109 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1110 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1111 if (hPipeClt != INVALID_HANDLE_VALUE)
1112 {
1113 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1114 int apc_count = 0;
1115 DWORD read;
1116 long count;
1117
1118 memset( send_buf, 0, TEST_BUF_LEN );
1119 memset( recv_buf, 0xde, TEST_BUF_LEN );
1120 count = get_pending_msgs(h);
1121 ok( !count, "Unexpected msg count: %ld\n", count );
1122
1123 res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1124 ok(res == STATUS_PENDING, "NtReadFile returned %x\n", res);
1125
1126 U(iosb).Status = 0xdeadbeef;
1127 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1128 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1129 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1130 count = get_pending_msgs(h);
1131 ok( !count, "Unexpected msg count: %ld\n", count );
1132
1133 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1134
1135 ok(!apc_count, "apc_count = %u\n", apc_count);
1136 count = get_pending_msgs(h);
1137 ok( !count, "Unexpected msg count: %ld\n", count );
1138
1139 SleepEx(1, TRUE); /* alertable sleep */
1140 ok(apc_count == 1, "apc was not called\n");
1141 count = get_pending_msgs(h);
1142 ok( !count, "Unexpected msg count: %ld\n", count );
1143
1144 /* using APCs on handle with associated completion port is not allowed */
1145 res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1146 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1147 }
1148
1149 CloseHandle( hPipeSrv );
1150 CloseHandle( hPipeClt );
1151 }
1152
1153 static void test_file_full_size_information(void)
1154 {
1155 IO_STATUS_BLOCK io;
1156 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1157 FILE_FS_SIZE_INFORMATION fsi;
1158 HANDLE h;
1159 NTSTATUS res;
1160
1161 if(!(h = create_temp_file(0))) return ;
1162
1163 memset(&ffsi,0,sizeof(ffsi));
1164 memset(&fsi,0,sizeof(fsi));
1165
1166 /* Assume No Quota Settings configured on Wine Testbot */
1167 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1168 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1169 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1170 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1171
1172 /* Test for FileFsSizeInformation */
1173 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1174 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1175 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1176 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1177 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1178 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1179
1180 /* Assume file system is NTFS */
1181 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1182 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1183
1184 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1185 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1186 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1187 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1188 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1189 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1190 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1191 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1192 wine_dbgstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1193 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1194 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1195 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1196 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1197 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1198 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1199 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1200 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1201
1202 /* Assume file system is NTFS */
1203 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1204 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1205
1206 CloseHandle( h );
1207 }
1208
1209 static void test_file_basic_information(void)
1210 {
1211 IO_STATUS_BLOCK io;
1212 FILE_BASIC_INFORMATION fbi;
1213 HANDLE h;
1214 int res;
1215 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1216
1217 if (!(h = create_temp_file(0))) return;
1218
1219 /* Check default first */
1220 memset(&fbi, 0, sizeof(fbi));
1221 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1222 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1223 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1224 "attribute %x not expected\n", fbi.FileAttributes );
1225
1226 /* Then SYSTEM */
1227 /* Clear fbi to avoid setting times */
1228 memset(&fbi, 0, sizeof(fbi));
1229 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1230 U(io).Status = 0xdeadbeef;
1231 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1232 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1233 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1234
1235 memset(&fbi, 0, sizeof(fbi));
1236 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1237 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1238 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fbi.FileAttributes );
1239
1240 /* Then HIDDEN */
1241 memset(&fbi, 0, sizeof(fbi));
1242 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1243 U(io).Status = 0xdeadbeef;
1244 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1245 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1246 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1247
1248 memset(&fbi, 0, sizeof(fbi));
1249 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1250 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1251 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fbi.FileAttributes );
1252
1253 /* Check NORMAL last of all (to make sure we can clear attributes) */
1254 memset(&fbi, 0, sizeof(fbi));
1255 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1256 U(io).Status = 0xdeadbeef;
1257 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1258 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1259 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1260
1261 memset(&fbi, 0, sizeof(fbi));
1262 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1263 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1264 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1265
1266 CloseHandle( h );
1267 }
1268
1269 static void test_file_all_information(void)
1270 {
1271 IO_STATUS_BLOCK io;
1272 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1273 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1274 * don't leave enough room there.
1275 */
1276 struct {
1277 FILE_ALL_INFORMATION fai;
1278 WCHAR buf[256];
1279 } fai_buf;
1280 HANDLE h;
1281 int res;
1282 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1283
1284 if (!(h = create_temp_file(0))) return;
1285
1286 /* Check default first */
1287 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1288 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1289 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1290 "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1291
1292 /* Then SYSTEM */
1293 /* Clear fbi to avoid setting times */
1294 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1295 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1296 U(io).Status = 0xdeadbeef;
1297 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1298 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1299 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1300 U(io).Status = 0xdeadbeef;
1301 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1302 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1303 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1304
1305 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1306 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1307 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1308 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
1309
1310 /* Then HIDDEN */
1311 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1312 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1313 U(io).Status = 0xdeadbeef;
1314 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1315 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1316 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1317
1318 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1319 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1320 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1321 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
1322
1323 /* Check NORMAL last of all (to make sure we can clear attributes) */
1324 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1325 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1326 U(io).Status = 0xdeadbeef;
1327 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1328 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1329 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1330
1331 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1332 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1333 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1334 todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not FILE_ATTRIBUTE_NORMAL\n", fai_buf.fai.BasicInformation.FileAttributes );
1335
1336 CloseHandle( h );
1337 }
1338
1339 static void delete_object( WCHAR *path )
1340 {
1341 BOOL ret = DeleteFileW( path );
1342 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1343 "DeleteFileW failed with %u\n", GetLastError() );
1344 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1345 {
1346 ret = RemoveDirectoryW( path );
1347 ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
1348 }
1349 }
1350
1351 static void test_file_rename_information(void)
1352 {
1353 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1354 static const WCHAR fooW[] = {'f','o','o',0};
1355 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1356 FILE_RENAME_INFORMATION *fri;
1357 FILE_NAME_INFORMATION *fni;
1358 BOOL success, fileDeleted;
1359 UNICODE_STRING name_str;
1360 HANDLE handle, handle2;
1361 IO_STATUS_BLOCK io;
1362 NTSTATUS res;
1363
1364 GetTempPathW( MAX_PATH, tmp_path );
1365
1366 /* oldpath is a file, newpath doesn't exist */
1367 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1368 ok( res != 0, "failed to create temp file\n" );
1369 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1370 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1371
1372 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1373 ok( res != 0, "failed to create temp file\n" );
1374 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1375 DeleteFileW( newpath );
1376 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1377 fri->Replace = FALSE;
1378 fri->RootDir = NULL;
1379 fri->FileNameLength = name_str.Length;
1380 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1381 pRtlFreeUnicodeString( &name_str );
1382
1383 U(io).Status = 0xdeadbeef;
1384 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1385 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1386 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1387 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1388 ok( fileDeleted, "file should not exist\n" );
1389 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1390 ok( !fileDeleted, "file should exist\n" );
1391
1392 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1393 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1394 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1395 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1396 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1397 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1398 HeapFree( GetProcessHeap(), 0, fni );
1399
1400 CloseHandle( handle );
1401 HeapFree( GetProcessHeap(), 0, fri );
1402 delete_object( oldpath );
1403 delete_object( newpath );
1404
1405 /* oldpath is a file, newpath is a file, Replace = FALSE */
1406 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1407 ok( res != 0, "failed to create temp file\n" );
1408 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1409 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1410
1411 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1412 ok( res != 0, "failed to create temp file\n" );
1413 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1414 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1415 fri->Replace = FALSE;
1416 fri->RootDir = NULL;
1417 fri->FileNameLength = name_str.Length;
1418 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1419 pRtlFreeUnicodeString( &name_str );
1420
1421 U(io).Status = 0xdeadbeef;
1422 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1423 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1424 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1425 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1426 ok( !fileDeleted, "file should exist\n" );
1427 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1428 ok( !fileDeleted, "file should exist\n" );
1429
1430 CloseHandle( handle );
1431 HeapFree( GetProcessHeap(), 0, fri );
1432 delete_object( oldpath );
1433 delete_object( newpath );
1434
1435 /* oldpath is a file, newpath is a file, Replace = TRUE */
1436 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1437 ok( res != 0, "failed to create temp file\n" );
1438 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1439 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1440
1441 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1442 ok( res != 0, "failed to create temp file\n" );
1443 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1444 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1445 fri->Replace = TRUE;
1446 fri->RootDir = NULL;
1447 fri->FileNameLength = name_str.Length;
1448 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1449 pRtlFreeUnicodeString( &name_str );
1450
1451 U(io).Status = 0xdeadbeef;
1452 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1453 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1454 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1455 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1456 ok( fileDeleted, "file should not exist\n" );
1457 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1458 ok( !fileDeleted, "file should exist\n" );
1459
1460 CloseHandle( handle );
1461 HeapFree( GetProcessHeap(), 0, fri );
1462 delete_object( oldpath );
1463 delete_object( newpath );
1464
1465 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1466 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1467 ok( res != 0, "failed to create temp file\n" );
1468 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1469 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1470
1471 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1472 ok( res != 0, "failed to create temp file\n" );
1473 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1474 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1475
1476 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1477 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1478 fri->Replace = FALSE;
1479 fri->RootDir = NULL;
1480 fri->FileNameLength = name_str.Length;
1481 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1482 pRtlFreeUnicodeString( &name_str );
1483
1484 U(io).Status = 0xdeadbeef;
1485 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1486 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1487 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1488 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1489 ok( !fileDeleted, "file should exist\n" );
1490 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1491 ok( !fileDeleted, "file should exist\n" );
1492
1493 CloseHandle( handle );
1494 CloseHandle( handle2 );
1495 HeapFree( GetProcessHeap(), 0, fri );
1496 delete_object( oldpath );
1497 delete_object( newpath );
1498
1499 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1500 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1501 ok( res != 0, "failed to create temp file\n" );
1502 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1503 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1504
1505 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1506 ok( res != 0, "failed to create temp file\n" );
1507 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1508 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1509
1510 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1511 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1512 fri->Replace = TRUE;
1513 fri->RootDir = NULL;
1514 fri->FileNameLength = name_str.Length;
1515 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1516 pRtlFreeUnicodeString( &name_str );
1517
1518 U(io).Status = 0xdeadbeef;
1519 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1520 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1521 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1522 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1523 ok( !fileDeleted, "file should exist\n" );
1524 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1525 ok( !fileDeleted, "file should exist\n" );
1526
1527 CloseHandle( handle );
1528 CloseHandle( handle2 );
1529 HeapFree( GetProcessHeap(), 0, fri );
1530 delete_object( oldpath );
1531 delete_object( newpath );
1532
1533 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1534 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1535 ok( res != 0, "failed to create temp file\n" );
1536 DeleteFileW( oldpath );
1537 success = CreateDirectoryW( oldpath, NULL );
1538 ok( success != 0, "failed to create temp directory\n" );
1539 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1540 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1541
1542 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1543 ok( res != 0, "failed to create temp file\n" );
1544 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1545 DeleteFileW( newpath );
1546 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1547 fri->Replace = FALSE;
1548 fri->RootDir = NULL;
1549 fri->FileNameLength = name_str.Length;
1550 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1551 pRtlFreeUnicodeString( &name_str );
1552
1553 U(io).Status = 0xdeadbeef;
1554 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1555 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1556 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1557 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1558 ok( fileDeleted, "file should not exist\n" );
1559 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1560 ok( !fileDeleted, "file should exist\n" );
1561
1562 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1563 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1564 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1565 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1566 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1567 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1568 HeapFree( GetProcessHeap(), 0, fni );
1569
1570 CloseHandle( handle );
1571 HeapFree( GetProcessHeap(), 0, fri );
1572 delete_object( oldpath );
1573 delete_object( newpath );
1574
1575 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1576 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1577 ok( res != 0, "failed to create temp file\n" );
1578 DeleteFileW( oldpath );
1579 success = CreateDirectoryW( oldpath, NULL );
1580 ok( success != 0, "failed to create temp directory\n" );
1581 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1582 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1583
1584 lstrcpyW( newpath, oldpath );
1585 lstrcatW( newpath, foo_txtW );
1586 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1587 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1588
1589 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1590 ok( res != 0, "failed to create temp file\n" );
1591 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1592 DeleteFileW( newpath );
1593 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1594 fri->Replace = FALSE;
1595 fri->RootDir = NULL;
1596 fri->FileNameLength = name_str.Length;
1597 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1598 pRtlFreeUnicodeString( &name_str );
1599
1600 U(io).Status = 0xdeadbeef;
1601 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1602 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1603 todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1604 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1605 todo_wine ok( !fileDeleted, "file should exist\n" );
1606 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1607 todo_wine ok( fileDeleted, "file should not exist\n" );
1608
1609 CloseHandle( handle );
1610 CloseHandle( handle2 );
1611 HeapFree( GetProcessHeap(), 0, fri );
1612 delete_object( oldpath );
1613 if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1614 {
1615 lstrcpyW( oldpath, newpath );
1616 lstrcatW( oldpath, foo_txtW );
1617 delete_object( oldpath );
1618 }
1619 delete_object( newpath );
1620
1621 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1622 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1623 ok( res != 0, "failed to create temp file\n" );
1624 DeleteFileW( oldpath );
1625 success = CreateDirectoryW( oldpath, NULL );
1626 ok( success != 0, "failed to create temp directory\n" );
1627 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1628 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1629
1630 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1631 ok( res != 0, "failed to create temp file\n" );
1632 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1633 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1634 fri->Replace = FALSE;
1635 fri->RootDir = NULL;
1636 fri->FileNameLength = name_str.Length;
1637 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1638 pRtlFreeUnicodeString( &name_str );
1639
1640 U(io).Status = 0xdeadbeef;
1641 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1642 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1643 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1644 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1645 ok( !fileDeleted, "file should exist\n" );
1646 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1647 ok( !fileDeleted, "file should exist\n" );
1648
1649 CloseHandle( handle );
1650 HeapFree( GetProcessHeap(), 0, fri );
1651 delete_object( oldpath );
1652 delete_object( newpath );
1653
1654 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1655 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1656 ok( res != 0, "failed to create temp file\n" );
1657 DeleteFileW( oldpath );
1658 success = CreateDirectoryW( oldpath, NULL );
1659 ok( success != 0, "failed to create temp directory\n" );
1660 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1661 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1662
1663 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1664 ok( res != 0, "failed to create temp file\n" );
1665 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1666 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1667
1668 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1669 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1670 fri->Replace = FALSE;
1671 fri->RootDir = NULL;
1672 fri->FileNameLength = name_str.Length;
1673 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1674 pRtlFreeUnicodeString( &name_str );
1675
1676 U(io).Status = 0xdeadbeef;
1677 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1678 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1679 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1680 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1681 ok( !fileDeleted, "file should exist\n" );
1682 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1683 ok( !fileDeleted, "file should exist\n" );
1684
1685 CloseHandle( handle );
1686 CloseHandle( handle2 );
1687 HeapFree( GetProcessHeap(), 0, fri );
1688 delete_object( oldpath );
1689 delete_object( newpath );
1690
1691 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1692 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1693 ok( res != 0, "failed to create temp file\n" );
1694 DeleteFileW( oldpath );
1695 success = CreateDirectoryW( oldpath, NULL );
1696 ok( success != 0, "failed to create temp directory\n" );
1697 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1698 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1699
1700 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1701 ok( res != 0, "failed to create temp file\n" );
1702 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1703 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1704 fri->Replace = TRUE;
1705 fri->RootDir = NULL;
1706 fri->FileNameLength = name_str.Length;
1707 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1708 pRtlFreeUnicodeString( &name_str );
1709
1710 U(io).Status = 0xdeadbeef;
1711 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1712 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1713 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1714 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1715 ok( fileDeleted, "file should not exist\n" );
1716 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1717 ok( !fileDeleted, "file should exist\n" );
1718
1719 CloseHandle( handle );
1720 HeapFree( GetProcessHeap(), 0, fri );
1721 delete_object( oldpath );
1722 delete_object( newpath );
1723
1724 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1725 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1726 ok( res != 0, "failed to create temp file\n" );
1727 DeleteFileW( oldpath );
1728 success = CreateDirectoryW( oldpath, NULL );
1729 ok( success != 0, "failed to create temp directory\n" );
1730 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1731 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1732
1733 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1734 ok( res != 0, "failed to create temp file\n" );
1735 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1736 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1737
1738 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1739 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1740 fri->Replace = TRUE;
1741 fri->RootDir = NULL;
1742 fri->FileNameLength = name_str.Length;
1743 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1744 pRtlFreeUnicodeString( &name_str );
1745
1746 U(io).Status = 0xdeadbeef;
1747 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1748 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1749 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1750 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1751 ok( !fileDeleted, "file should exist\n" );
1752 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1753 ok( !fileDeleted, "file should exist\n" );
1754
1755 CloseHandle( handle );
1756 CloseHandle( handle2 );
1757 HeapFree( GetProcessHeap(), 0, fri );
1758 delete_object( oldpath );
1759 delete_object( newpath );
1760
1761 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1762 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1763 ok( res != 0, "failed to create temp file\n" );
1764 DeleteFileW( oldpath );
1765 success = CreateDirectoryW( oldpath, NULL );
1766 ok( success != 0, "failed to create temp directory\n" );
1767 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1768 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1769
1770 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1771 ok( res != 0, "failed to create temp file\n" );
1772 DeleteFileW( newpath );
1773 success = CreateDirectoryW( newpath, NULL );
1774 ok( success != 0, "failed to create temp directory\n" );
1775 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1776 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1777 fri->Replace = FALSE;
1778 fri->RootDir = NULL;
1779 fri->FileNameLength = name_str.Length;
1780 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1781 pRtlFreeUnicodeString( &name_str );
1782
1783 U(io).Status = 0xdeadbeef;
1784 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1785 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1786 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1787 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1788 ok( !fileDeleted, "file should exist\n" );
1789 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1790 ok( !fileDeleted, "file should exist\n" );
1791
1792 CloseHandle( handle );
1793 HeapFree( GetProcessHeap(), 0, fri );
1794 delete_object( oldpath );
1795 delete_object( newpath );
1796
1797 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1798 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1799 ok( res != 0, "failed to create temp file\n" );
1800 DeleteFileW( oldpath );
1801 success = CreateDirectoryW( oldpath, NULL );
1802 ok( success != 0, "failed to create temp directory\n" );
1803 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1804 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1805
1806 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1807 ok( res != 0, "failed to create temp file\n" );
1808 DeleteFileW( newpath );
1809 success = CreateDirectoryW( newpath, NULL );
1810 ok( success != 0, "failed to create temp directory\n" );
1811 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1812 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1813 fri->Replace = TRUE;
1814 fri->RootDir = NULL;
1815 fri->FileNameLength = name_str.Length;
1816 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1817 pRtlFreeUnicodeString( &name_str );
1818
1819 U(io).Status = 0xdeadbeef;
1820 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1821 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1822 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1823 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1824 ok( !fileDeleted, "file should exist\n" );
1825 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1826 ok( !fileDeleted, "file should exist\n" );
1827
1828 CloseHandle( handle );
1829 HeapFree( GetProcessHeap(), 0, fri );
1830 delete_object( oldpath );
1831 delete_object( newpath );
1832
1833 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
1834 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1835 ok( res != 0, "failed to create temp file\n" );
1836 DeleteFileW( oldpath );
1837 success = CreateDirectoryW( oldpath, NULL );
1838 ok( success != 0, "failed to create temp directory\n" );
1839 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1840 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1841
1842 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1843 ok( res != 0, "failed to create temp file\n" );
1844 DeleteFileW( newpath );
1845 success = CreateDirectoryW( newpath, NULL );
1846 ok( success != 0, "failed to create temp directory\n" );
1847 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1848 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1849
1850 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1851 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1852 fri->Replace = TRUE;
1853 fri->RootDir = NULL;
1854 fri->FileNameLength = name_str.Length;
1855 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1856 pRtlFreeUnicodeString( &name_str );
1857
1858 U(io).Status = 0xdeadbeef;
1859 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1860 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1861 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1862 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1863 ok( !fileDeleted, "file should exist\n" );
1864 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1865 ok( !fileDeleted, "file should exist\n" );
1866
1867 CloseHandle( handle );
1868 CloseHandle( handle2 );
1869 HeapFree( GetProcessHeap(), 0, fri );
1870 delete_object( oldpath );
1871 delete_object( newpath );
1872
1873 /* oldpath is a file, newpath is a directory, Replace = FALSE */
1874 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1875 ok( res != 0, "failed to create temp file\n" );
1876 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1877 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1878
1879 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1880 ok( res != 0, "failed to create temp file\n" );
1881 DeleteFileW( newpath );
1882 success = CreateDirectoryW( newpath, NULL );
1883 ok( success != 0, "failed to create temp directory\n" );
1884 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1885 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1886 fri->Replace = FALSE;
1887 fri->RootDir = NULL;
1888 fri->FileNameLength = name_str.Length;
1889 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1890 pRtlFreeUnicodeString( &name_str );
1891
1892 U(io).Status = 0xdeadbeef;
1893 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1894 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1895 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1896 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1897 ok( !fileDeleted, "file should exist\n" );
1898 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1899 ok( !fileDeleted, "file should exist\n" );
1900
1901 CloseHandle( handle );
1902 HeapFree( GetProcessHeap(), 0, fri );
1903 delete_object( oldpath );
1904 delete_object( newpath );
1905
1906 /* oldpath is a file, newpath is a directory, Replace = TRUE */
1907 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1908 ok( res != 0, "failed to create temp file\n" );
1909 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1910 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1911
1912 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1913 ok( res != 0, "failed to create temp file\n" );
1914 DeleteFileW( newpath );
1915 success = CreateDirectoryW( newpath, NULL );
1916 ok( success != 0, "failed to create temp directory\n" );
1917 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1918 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1919 fri->Replace = TRUE;
1920 fri->RootDir = NULL;
1921 fri->FileNameLength = name_str.Length;
1922 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1923 pRtlFreeUnicodeString( &name_str );
1924
1925 U(io).Status = 0xdeadbeef;
1926 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1927 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1928 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1929 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1930 ok( !fileDeleted, "file should exist\n" );
1931 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1932 ok( !fileDeleted, "file should exist\n" );
1933
1934 CloseHandle( handle );
1935 HeapFree( GetProcessHeap(), 0, fri );
1936 delete_object( oldpath );
1937 delete_object( newpath );
1938
1939 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
1940 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1941 ok( res != 0, "failed to create temp file\n" );
1942 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1943 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1944
1945 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1946 ok( res != 0, "failed to create temp file\n" );
1947 DeleteFileW( newpath );
1948 for (filename = newpath, p = newpath; *p; p++)
1949 if (*p == '\\') filename = p + 1;
1950 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1951 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1952
1953 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
1954 fri->Replace = FALSE;
1955 fri->RootDir = handle2;
1956 fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
1957 memcpy( fri->FileName, filename, fri->FileNameLength );
1958
1959 U(io).Status = 0xdeadbeef;
1960 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1961 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1962 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1963 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1964 ok( fileDeleted, "file should not exist\n" );
1965 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1966 ok( !fileDeleted, "file should exist\n" );
1967
1968 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1969 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1970 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1971 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1972 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1973 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1974 HeapFree( GetProcessHeap(), 0, fni );
1975
1976 CloseHandle( handle );
1977 CloseHandle( handle2 );
1978 HeapFree( GetProcessHeap(), 0, fri );
1979 delete_object( oldpath );
1980 delete_object( newpath );
1981 }
1982
1983 static void test_file_link_information(void)
1984 {
1985 static const WCHAR pipeW[] = {'\\','\\','.','\\','p','i','p','e','\\','w','i','n','e','_','t','e','s','t',0};
1986 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1987 static const WCHAR fooW[] = {'f','o','o',0};
1988 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1989 FILE_LINK_INFORMATION *fli;
1990 FILE_NAME_INFORMATION *fni;
1991 BOOL success, fileDeleted;
1992 UNICODE_STRING name_str;
1993 HANDLE handle, handle2;
1994 IO_STATUS_BLOCK io;
1995 NTSTATUS res;
1996
1997 GetTempPathW( MAX_PATH, tmp_path );
1998
1999 /* oldpath is a file, newpath doesn't exist */
2000 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2001 ok( res != 0, "failed to create temp file\n" );
2002 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2003 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2004
2005 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2006 ok( res != 0, "failed to create temp file\n" );
2007 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2008 DeleteFileW( newpath );
2009 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2010 fli->ReplaceIfExists = FALSE;
2011 fli->RootDirectory = NULL;
2012 fli->FileNameLength = name_str.Length;
2013 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2014 pRtlFreeUnicodeString( &name_str );
2015
2016 U(io).Status = 0xdeadbeef;
2017 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2018 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2019 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2020 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2021 ok( !fileDeleted, "file should exist\n" );
2022 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2023 ok( !fileDeleted, "file should exist\n" );
2024
2025 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2026 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2027 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2028 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2029 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2030 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2031 HeapFree( GetProcessHeap(), 0, fni );
2032
2033 CloseHandle( handle );
2034 HeapFree( GetProcessHeap(), 0, fli );
2035 delete_object( oldpath );
2036 delete_object( newpath );
2037
2038 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2039 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2040 ok( res != 0, "failed to create temp file\n" );
2041 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2042 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2043
2044 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2045 ok( res != 0, "failed to create temp file\n" );
2046 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2047 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2048 fli->ReplaceIfExists = FALSE;
2049 fli->RootDirectory = NULL;
2050 fli->FileNameLength = name_str.Length;
2051 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2052 pRtlFreeUnicodeString( &name_str );
2053
2054 U(io).Status = 0xdeadbeef;
2055 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2056 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2057 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2058 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2059 ok( !fileDeleted, "file should exist\n" );
2060 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2061 ok( !fileDeleted, "file should exist\n" );
2062
2063 CloseHandle( handle );
2064 HeapFree( GetProcessHeap(), 0, fli );
2065 delete_object( oldpath );
2066 delete_object( newpath );
2067
2068 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2069 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2070 ok( res != 0, "failed to create temp file\n" );
2071 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2072 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2073
2074 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2075 ok( res != 0, "failed to create temp file\n" );
2076 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2077 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2078 fli->ReplaceIfExists = TRUE;
2079 fli->RootDirectory = NULL;
2080 fli->FileNameLength = name_str.Length;
2081 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2082 pRtlFreeUnicodeString( &name_str );
2083
2084 U(io).Status = 0xdeadbeef;
2085 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2086 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2087 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2088 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2089 ok( !fileDeleted, "file should exist\n" );
2090 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2091 ok( !fileDeleted, "file should exist\n" );
2092
2093 CloseHandle( handle );
2094 HeapFree( GetProcessHeap(), 0, fli );
2095 delete_object( oldpath );
2096 delete_object( newpath );
2097
2098 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2099 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2100 ok( res != 0, "failed to create temp file\n" );
2101 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2102 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2103
2104 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2105 ok( res != 0, "failed to create temp file\n" );
2106 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2107 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2108
2109 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2110 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2111 fli->ReplaceIfExists = FALSE;
2112 fli->RootDirectory = NULL;
2113 fli->FileNameLength = name_str.Length;
2114 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2115 pRtlFreeUnicodeString( &name_str );
2116
2117 U(io).Status = 0xdeadbeef;
2118 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2119 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2120 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2121 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2122 ok( !fileDeleted, "file should exist\n" );
2123 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2124 ok( !fileDeleted, "file should exist\n" );
2125
2126 CloseHandle( handle );
2127 CloseHandle( handle2 );
2128 HeapFree( GetProcessHeap(), 0, fli );
2129 delete_object( oldpath );
2130 delete_object( newpath );
2131
2132 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2133 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2134 ok( res != 0, "failed to create temp file\n" );
2135 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2136 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2137
2138 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2139 ok( res != 0, "failed to create temp file\n" );
2140 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2141 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2142
2143 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2144 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2145 fli->ReplaceIfExists = TRUE;
2146 fli->RootDirectory = NULL;
2147 fli->FileNameLength = name_str.Length;
2148 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2149 pRtlFreeUnicodeString( &name_str );
2150
2151 U(io).Status = 0xdeadbeef;
2152 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2153 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2154 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2155 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2156 ok( !fileDeleted, "file should exist\n" );
2157 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2158 ok( !fileDeleted, "file should exist\n" );
2159
2160 CloseHandle( handle );
2161 CloseHandle( handle2 );
2162 HeapFree( GetProcessHeap(), 0, fli );
2163 delete_object( oldpath );
2164 delete_object( newpath );
2165
2166 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2167 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2168 ok( res != 0, "failed to create temp file\n" );
2169 DeleteFileW( oldpath );
2170 success = CreateDirectoryW( oldpath, NULL );
2171 ok( success != 0, "failed to create temp directory\n" );
2172 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2173 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2174
2175 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2176 ok( res != 0, "failed to create temp file\n" );
2177 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2178 DeleteFileW( newpath );
2179 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2180 fli->ReplaceIfExists = FALSE;
2181 fli->RootDirectory = NULL;
2182 fli->FileNameLength = name_str.Length;
2183 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2184 pRtlFreeUnicodeString( &name_str );
2185
2186 U(io).Status = 0xdeadbeef;
2187 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2188 todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2189 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2190 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2191 ok( !fileDeleted, "file should exist\n" );
2192 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2193 ok( fileDeleted, "file should not exist\n" );
2194
2195 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2196 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2197 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2198 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2199 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2200 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2201 HeapFree( GetProcessHeap(), 0, fni );
2202
2203 CloseHandle( handle );
2204 HeapFree( GetProcessHeap(), 0, fli );
2205 delete_object( oldpath );
2206 delete_object( newpath );
2207
2208 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2209 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2210 ok( res != 0, "failed to create temp file\n" );
2211 DeleteFileW( oldpath );
2212 success = CreateDirectoryW( oldpath, NULL );
2213 ok( success != 0, "failed to create temp directory\n" );
2214 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2215 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2216
2217 lstrcpyW( newpath, oldpath );
2218 lstrcatW( newpath, foo_txtW );
2219 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2220 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2221
2222 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2223 ok( res != 0, "failed to create temp file\n" );
2224 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2225 DeleteFileW( newpath );
2226 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2227 fli->ReplaceIfExists = FALSE;
2228 fli->RootDirectory = NULL;
2229 fli->FileNameLength = name_str.Length;
2230 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2231 pRtlFreeUnicodeString( &name_str );
2232
2233 U(io).Status = 0xdeadbeef;
2234 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2235 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2236 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2237 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2238 ok( !fileDeleted, "file should exist\n" );
2239 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2240 ok( fileDeleted, "file should not exist\n" );
2241
2242 CloseHandle( handle );
2243 CloseHandle( handle2 );
2244 HeapFree( GetProcessHeap(), 0, fli );
2245 delete_object( oldpath );
2246 delete_object( newpath );
2247
2248 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2249 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2250 ok( res != 0, "failed to create temp file\n" );
2251 DeleteFileW( oldpath );
2252 success = CreateDirectoryW( oldpath, NULL );
2253 ok( success != 0, "failed to create temp directory\n" );
2254 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2255 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2256
2257 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2258 ok( res != 0, "failed to create temp file\n" );
2259 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2260 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2261 fli->ReplaceIfExists = FALSE;
2262 fli->RootDirectory = NULL;
2263 fli->FileNameLength = name_str.Length;
2264 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2265 pRtlFreeUnicodeString( &name_str );
2266
2267 U(io).Status = 0xdeadbeef;
2268 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2269 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2270 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2271 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2272 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2273 ok( !fileDeleted, "file should exist\n" );
2274 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2275 ok( !fileDeleted, "file should exist\n" );
2276
2277 CloseHandle( handle );
2278 HeapFree( GetProcessHeap(), 0, fli );
2279 delete_object( oldpath );
2280 delete_object( newpath );
2281
2282 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2283 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2284 ok( res != 0, "failed to create temp file\n" );
2285 DeleteFileW( oldpath );
2286 success = CreateDirectoryW( oldpath, NULL );
2287 ok( success != 0, "failed to create temp directory\n" );
2288 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2289 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2290
2291 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2292 ok( res != 0, "failed to create temp file\n" );
2293 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2294 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2295
2296 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2297 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2298 fli->ReplaceIfExists = FALSE;
2299 fli->RootDirectory = NULL;
2300 fli->FileNameLength = name_str.Length;
2301 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2302 pRtlFreeUnicodeString( &name_str );
2303
2304 U(io).Status = 0xdeadbeef;
2305 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2306 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2307 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2308 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2309 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2310 ok( !fileDeleted, "file should exist\n" );
2311 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2312 ok( !fileDeleted, "file should exist\n" );
2313
2314 CloseHandle( handle );
2315 CloseHandle( handle2 );
2316 HeapFree( GetProcessHeap(), 0, fli );
2317 delete_object( oldpath );
2318 delete_object( newpath );
2319
2320 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2321 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2322 ok( res != 0, "failed to create temp file\n" );
2323 DeleteFileW( oldpath );
2324 success = CreateDirectoryW( oldpath, NULL );
2325 ok( success != 0, "failed to create temp directory\n" );
2326 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2327 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2328
2329 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2330 ok( res != 0, "failed to create temp file\n" );
2331 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2332 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2333 fli->ReplaceIfExists = TRUE;
2334 fli->RootDirectory = NULL;
2335 fli->FileNameLength = name_str.Length;
2336 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2337 pRtlFreeUnicodeString( &name_str );
2338
2339 U(io).Status = 0xdeadbeef;
2340 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2341 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2342 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2343 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2344 ok( !fileDeleted, "file should exist\n" );
2345 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2346 ok( !fileDeleted, "file should exist\n" );
2347
2348 CloseHandle( handle );
2349 HeapFree( GetProcessHeap(), 0, fli );
2350 delete_object( oldpath );
2351 delete_object( newpath );
2352
2353 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2354 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2355 ok( res != 0, "failed to create temp file\n" );
2356 DeleteFileW( oldpath );
2357 success = CreateDirectoryW( oldpath, NULL );
2358 ok( success != 0, "failed to create temp directory\n" );
2359 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2360 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2361
2362 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2363 ok( res != 0, "failed to create temp file\n" );
2364 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2365 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2366
2367 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2368 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2369 fli->ReplaceIfExists = TRUE;
2370 fli->RootDirectory = NULL;
2371 fli->FileNameLength = name_str.Length;
2372 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2373 pRtlFreeUnicodeString( &name_str );
2374
2375 U(io).Status = 0xdeadbeef;
2376 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2377 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2378 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2379 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2380 ok( !fileDeleted, "file should exist\n" );
2381 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2382 ok( !fileDeleted, "file should exist\n" );
2383
2384 CloseHandle( handle );
2385 CloseHandle( handle2 );
2386 HeapFree( GetProcessHeap(), 0, fli );
2387 delete_object( oldpath );
2388 delete_object( newpath );
2389
2390 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2391 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2392 ok( res != 0, "failed to create temp file\n" );
2393 DeleteFileW( oldpath );
2394 success = CreateDirectoryW( oldpath, NULL );
2395 ok( success != 0, "failed to create temp directory\n" );
2396 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2397 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2398
2399 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2400 ok( res != 0, "failed to create temp file\n" );
2401 DeleteFileW( newpath );
2402 success = CreateDirectoryW( newpath, NULL );
2403 ok( success != 0, "failed to create temp directory\n" );
2404 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2405 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2406 fli->ReplaceIfExists = FALSE;
2407 fli->RootDirectory = NULL;
2408 fli->FileNameLength = name_str.Length;
2409 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2410 pRtlFreeUnicodeString( &name_str );
2411
2412 U(io).Status = 0xdeadbeef;
2413 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2414 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2415 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2416 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2417 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2418 ok( !fileDeleted, "file should exist\n" );
2419 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2420 ok( !fileDeleted, "file should exist\n" );
2421
2422 CloseHandle( handle );
2423 HeapFree( GetProcessHeap(), 0, fli );
2424 delete_object( oldpath );
2425 delete_object( newpath );
2426
2427 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2428 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2429 ok( res != 0, "failed to create temp file\n" );
2430 DeleteFileW( oldpath );
2431 success = CreateDirectoryW( oldpath, NULL );
2432 ok( success != 0, "failed to create temp directory\n" );
2433 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2434 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2435
2436 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2437 ok( res != 0, "failed to create temp file\n" );
2438 DeleteFileW( newpath );
2439 success = CreateDirectoryW( newpath, NULL );
2440 ok( success != 0, "failed to create temp directory\n" );
2441 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2442 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2443 fli->ReplaceIfExists = TRUE;
2444 fli->RootDirectory = NULL;
2445 fli->FileNameLength = name_str.Length;
2446 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2447 pRtlFreeUnicodeString( &name_str );
2448
2449 U(io).Status = 0xdeadbeef;
2450 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2451 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2452 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2453 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2454 ok( !fileDeleted, "file should exist\n" );
2455 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2456 ok( !fileDeleted, "file should exist\n" );
2457
2458 CloseHandle( handle );
2459 HeapFree( GetProcessHeap(), 0, fli );
2460 delete_object( oldpath );
2461 delete_object( newpath );
2462
2463 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2464 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2465 ok( res != 0, "failed to create temp file\n" );
2466 DeleteFileW( oldpath );
2467 success = CreateDirectoryW( oldpath, NULL );
2468 ok( success != 0, "failed to create temp directory\n" );
2469 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2470 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2471
2472 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2473 ok( res != 0, "failed to create temp file\n" );
2474 DeleteFileW( newpath );
2475 success = CreateDirectoryW( newpath, NULL );
2476 ok( success != 0, "failed to create temp directory\n" );
2477 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2478 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2479
2480 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2481 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2482 fli->ReplaceIfExists = TRUE;
2483 fli->RootDirectory = NULL;
2484 fli->FileNameLength = name_str.Length;
2485 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2486 pRtlFreeUnicodeString( &name_str );
2487
2488 U(io).Status = 0xdeadbeef;
2489 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2490 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2491 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2492 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2493 ok( !fileDeleted, "file should exist\n" );
2494 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2495 ok( !fileDeleted, "file should exist\n" );
2496
2497 CloseHandle( handle );
2498 CloseHandle( handle2 );
2499 HeapFree( GetProcessHeap(), 0, fli );
2500 delete_object( oldpath );
2501 delete_object( newpath );
2502
2503 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2504 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2505 ok( res != 0, "failed to create temp file\n" );
2506 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2507 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2508
2509 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2510 ok( res != 0, "failed to create temp file\n" );
2511 DeleteFileW( newpath );
2512 success = CreateDirectoryW( newpath, NULL );
2513 ok( success != 0, "failed to create temp directory\n" );
2514 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2515 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2516 fli->ReplaceIfExists = FALSE;
2517 fli->RootDirectory = NULL;
2518 fli->FileNameLength = name_str.Length;
2519 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2520 pRtlFreeUnicodeString( &name_str );
2521
2522 U(io).Status = 0xdeadbeef;
2523 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2524 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2525 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2526 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2527 ok( !fileDeleted, "file should exist\n" );
2528 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2529 ok( !fileDeleted, "file should exist\n" );
2530
2531 CloseHandle( handle );
2532 HeapFree( GetProcessHeap(), 0, fli );
2533 delete_object( oldpath );
2534 delete_object( newpath );
2535
2536 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2537 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2538 ok( res != 0, "failed to create temp file\n" );
2539 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2540 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2541
2542 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2543 ok( res != 0, "failed to create temp file\n" );
2544 DeleteFileW( newpath );
2545 success = CreateDirectoryW( newpath, NULL );
2546 ok( success != 0, "failed to create temp directory\n" );
2547 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2548 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2549 fli->ReplaceIfExists = TRUE;
2550 fli->RootDirectory = NULL;
2551 fli->FileNameLength = name_str.Length;
2552 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2553 pRtlFreeUnicodeString( &name_str );
2554
2555 U(io).Status = 0xdeadbeef;
2556 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2557 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2558 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2559 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2560 ok( !fileDeleted, "file should exist\n" );
2561 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2562 ok( !fileDeleted, "file should exist\n" );
2563
2564 CloseHandle( handle );
2565 HeapFree( GetProcessHeap(), 0, fli );
2566 delete_object( oldpath );
2567 delete_object( newpath );
2568
2569 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2570 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2571 ok( res != 0, "failed to create temp file\n" );
2572 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2573 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2574
2575 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2576 ok( res != 0, "failed to create temp file\n" );
2577 DeleteFileW( newpath );
2578 for (filename = newpath, p = newpath; *p; p++)
2579 if (*p == '\\') filename = p + 1;
2580 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2581 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2582
2583 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2584 fli->ReplaceIfExists = FALSE;
2585 fli->RootDirectory = handle2;
2586 fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2587 memcpy( fli->FileName, filename, fli->FileNameLength );
2588
2589 U(io).Status = 0xdeadbeef;
2590 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2591 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2592 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2593 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2594 ok( !fileDeleted, "file should exist\n" );
2595 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2596 ok( !fileDeleted, "file should exist\n" );
2597
2598 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2599 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2600 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2601 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2602 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2603 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2604 HeapFree( GetProcessHeap(), 0, fni );
2605
2606 CloseHandle( handle );
2607 CloseHandle( handle2 );
2608
2609 handle = CreateEventA( NULL, FALSE, FALSE, "wine_test_event" );
2610 ok( !!handle, "Failed to create event: %u\n", GetLastError());
2611
2612 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2613 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2614 ok( res == STATUS_OBJECT_TYPE_MISMATCH, "res expected STATUS_OBJECT_TYPE_MISMATCH, got %x\n", res );
2615 HeapFree( GetProcessHeap(), 0, fni );
2616
2617 CloseHandle( handle );
2618
2619 handle = CreateNamedPipeW( pipeW, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_READMODE_BYTE, 10, 512, 512, 0, NULL);
2620 ok( handle != INVALID_HANDLE_VALUE, "Failed to create named pipe: %u\n", GetLastError());
2621
2622 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2623 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2624 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2625 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2626 ok( !lstrcmpiW(fni->FileName, pipeW + 8), "FileName expected %s, got %s\n",
2627 wine_dbgstr_w(pipeW + 8), wine_dbgstr_w(fni->FileName) );
2628 HeapFree( GetProcessHeap(), 0, fni );
2629
2630 CloseHandle( handle );
2631
2632 HeapFree( GetProcessHeap(), 0, fli );
2633 delete_object( oldpath );
2634 delete_object( newpath );
2635 }
2636
2637 static void test_file_both_information(void)
2638 {
2639 IO_STATUS_BLOCK io;
2640 FILE_BOTH_DIR_INFORMATION fbi;
2641 HANDLE h;
2642 int res;
2643
2644 if (!(h = create_temp_file(0))) return;
2645
2646 memset(&fbi, 0, sizeof(fbi));
2647 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
2648 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
2649
2650 CloseHandle( h );
2651 }
2652
2653 static void test_file_disposition_information(void)
2654 {
2655 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
2656 DWORD dirpos;
2657 HANDLE handle, handle2, mapping;
2658 NTSTATUS res;
2659 IO_STATUS_BLOCK io;
2660 FILE_DISPOSITION_INFORMATION fdi;
2661 BOOL fileDeleted;
2662 DWORD fdi2;
2663 void *ptr;
2664
2665 GetTempPathA( MAX_PATH, tmp_path );
2666
2667 /* tests for info struct size */
2668 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2669 handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2670 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2671 res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
2672 todo_wine
2673 ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %x\n", res );
2674 fdi2 = 0x100;
2675 res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
2676 ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x\n", res );
2677 CloseHandle( handle );
2678 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2679 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2680 DeleteFileA( buffer );
2681
2682 /* cannot set disposition on file not opened with delete access */
2683 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2684 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2685 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2686 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2687 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
2688 fdi.DoDeleteFile = TRUE;
2689 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2690 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
2691 CloseHandle( handle );
2692 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2693 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2694 DeleteFileA( buffer );
2695
2696 /* can set disposition on file opened with proper access */
2697 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2698 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2699 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2700 fdi.DoDeleteFile = TRUE;
2701 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2702 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2703 CloseHandle( handle );
2704 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2705 ok( fileDeleted, "File should have been deleted\n" );
2706 DeleteFileA( buffer );
2707
2708 /* cannot set disposition on readonly file */
2709 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2710 DeleteFileA( buffer );
2711 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2712 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2713 fdi.DoDeleteFile = TRUE;
2714 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2715 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2716 CloseHandle( handle );
2717 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2718 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2719 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2720 DeleteFileA( buffer );
2721
2722 /* cannot set disposition on readonly file */
2723 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2724 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2725 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2726 fdi.DoDeleteFile = TRUE;
2727 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2728 todo_wine
2729 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2730 CloseHandle( handle );
2731 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2732 todo_wine
2733 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2734 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2735 DeleteFileA( buffer );
2736
2737 /* can set disposition on file and then reset it */
2738 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2739 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2740 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2741 fdi.DoDeleteFile = TRUE;
2742 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2743 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2744 fdi.DoDeleteFile = FALSE;
2745 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2746 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2747 CloseHandle( handle );
2748 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2749 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2750 DeleteFileA( buffer );
2751
2752 /* Delete-on-close flag doesn't change file disposition until a handle is closed */
2753 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2754 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2755 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2756 fdi.DoDeleteFile = FALSE;
2757 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2758 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2759 CloseHandle( handle );
2760 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2761 ok( fileDeleted, "File should have been deleted\n" );
2762 DeleteFileA( buffer );
2763
2764 /* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
2765 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2766 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2767 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2768 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
2769 CloseHandle( handle );
2770 fdi.DoDeleteFile = FALSE;
2771 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
2772 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2773 CloseHandle( handle2 );
2774 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2775 ok( fileDeleted, "File should have been deleted\n" );
2776 DeleteFileA( buffer );
2777
2778 /* can set disposition on a directory opened with proper access */
2779 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2780 DeleteFileA( buffer );
2781 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2782 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2783 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2784 fdi.DoDeleteFile = TRUE;
2785 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2786 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2787 CloseHandle( handle );
2788 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2789 ok( fileDeleted, "Directory should have been deleted\n" );
2790 RemoveDirectoryA( buffer );
2791
2792 /* RemoveDirectory sets directory disposition and it can be undone */
2793 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2794 DeleteFileA( buffer );
2795 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2796 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2797 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2798 RemoveDirectoryA( buffer );
2799 fdi.DoDeleteFile = FALSE;
2800 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2801 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2802 CloseHandle( handle );
2803 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2804 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2805 RemoveDirectoryA( buffer );
2806
2807 /* cannot set disposition on a non-empty directory */
2808 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2809 DeleteFileA( buffer );
2810 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2811 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2812 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2813 dirpos = lstrlenA( buffer );
2814 lstrcpyA( buffer + dirpos, "\\tst" );
2815 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2816 CloseHandle( handle2 );
2817 fdi.DoDeleteFile = TRUE;
2818 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2819 todo_wine
2820 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
2821 DeleteFileA( buffer );
2822 buffer[dirpos] = '\0';
2823 CloseHandle( handle );
2824 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2825 todo_wine
2826 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2827 RemoveDirectoryA( buffer );
2828
2829 /* cannot set disposition on file with file mapping opened */
2830 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2831 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2832 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2833 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2834 ok( mapping != NULL, "failed to create file mapping\n");
2835 fdi.DoDeleteFile = TRUE;
2836 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2837 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2838 CloseHandle( handle );
2839 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2840 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2841 CloseHandle( mapping );
2842 DeleteFileA( buffer );
2843
2844 /* can set disposition on file with file mapping closed */
2845 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2846 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2847 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2848 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2849 ok( mapping != NULL, "failed to create file mapping\n");
2850 CloseHandle( mapping );
2851 fdi.DoDeleteFile = TRUE;
2852 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2853 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2854 CloseHandle( handle );
2855 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2856 ok( fileDeleted, "File should have been deleted\n" );
2857 DeleteFileA( buffer );
2858
2859 /* cannot set disposition on file which is mapped to memory */
2860 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2861 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2862 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2863 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2864 ok( mapping != NULL, "failed to create file mapping\n");
2865 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
2866 ok( ptr != NULL, "MapViewOfFile failed\n");
2867 CloseHandle( mapping );
2868 fdi.DoDeleteFile = TRUE;
2869 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2870 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2871 CloseHandle( handle );
2872 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2873 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2874 UnmapViewOfFile( ptr );
2875 DeleteFileA( buffer );
2876
2877 /* can set disposition on file which is mapped to memory and unmapped again */
2878 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2879 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2880 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2881 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2882 ok( mapping != NULL, "failed to create file mapping\n");
2883 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
2884 ok( ptr != NULL, "MapViewOfFile failed\n");
2885 CloseHandle( mapping );
2886 UnmapViewOfFile( ptr );
2887 fdi.DoDeleteFile = TRUE;
2888 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2889 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2890 CloseHandle( handle );
2891 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2892 ok( fileDeleted, "File should have been deleted\n" );
2893 DeleteFileA( buffer );
2894 }
2895
2896 static void test_iocompletion(void)
2897 {
2898 HANDLE h = INVALID_HANDLE_VALUE;
2899 NTSTATUS res;
2900
2901 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
2902
2903 ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
2904 ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
2905
2906 if ( h && h != INVALID_HANDLE_VALUE)
2907 {
2908 test_iocp_setcompletion(h);
2909 test_iocp_fileio(h);
2910 pNtClose(h);
2911 }
2912 }
2913
2914 static void test_file_name_information(void)
2915 {
2916 WCHAR *file_name, *volume_prefix, *expected;
2917 FILE_NAME_INFORMATION *info;
2918 ULONG old_redir = 1, tmp;
2919 UINT file_name_size;
2920 IO_STATUS_BLOCK io;
2921 UINT info_size;
2922 HRESULT hr;
2923 HANDLE h;
2924 UINT len;
2925
2926 /* GetVolumePathName is not present before w2k */
2927 if (!pGetVolumePathNameW) {
2928 win_skip("GetVolumePathNameW not found\n");
2929 return;
2930 }
2931
2932 file_name_size = GetSystemDirectoryW( NULL, 0 );
2933 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
2934 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
2935 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
2936
2937 len = GetSystemDirectoryW( file_name, file_name_size );
2938 ok(len == file_name_size - 1,
2939 "GetSystemDirectoryW returned %u, expected %u.\n",
2940 len, file_name_size - 1);
2941
2942 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
2943 ok(len, "GetVolumePathNameW failed.\n");
2944
2945 len = lstrlenW( volume_prefix );
2946 if (len && volume_prefix[len - 1] == '\\') --len;
2947 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
2948 expected[file_name_size - len - 1] = '\0';
2949
2950 /* A bit more than we actually need, but it keeps the calculation simple. */
2951 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
2952 info = HeapAlloc( GetProcessHeap(), 0, info_size );
2953
2954 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
2955 h = CreateFileW( file_name, GENERIC_READ,
2956 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2957 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2958 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
2959 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
2960
2961 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
2962 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
2963
2964 memset( info, 0xcc, info_size );
2965 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
2966 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
2967 hr, STATUS_BUFFER_OVERFLOW);
2968 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
2969 U(io).Status, STATUS_BUFFER_OVERFLOW);
2970 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
2971 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
2972 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
2973 "info->FileName[1] is %p, expected %p.\n",
2974 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
2975 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
2976
2977 memset( info, 0xcc, info_size );
2978 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
2979 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
2980 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
2981 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
2982 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
2983 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
2984 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
2985 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
2986 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
2987 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
2988 "io.Information is %lu, expected %u.\n",
2989 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
2990
2991 CloseHandle( h );
2992 HeapFree( GetProcessHeap(), 0, info );
2993 HeapFree( GetProcessHeap(), 0, expected );
2994 HeapFree( GetProcessHeap(), 0, volume_prefix );
2995
2996 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
2997 {
2998 skip("Not running on WoW64, skipping test.\n");
2999 HeapFree( GetProcessHeap(), 0, file_name );
3000 return;
3001 }
3002
3003 h = CreateFileW( file_name, GENERIC_READ,
3004 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3005 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3006 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3007 HeapFree( GetProcessHeap(), 0, file_name );
3008
3009 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3010 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3011 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3012
3013 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3014 ok(len == file_name_size - 1,
3015 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3016 len, file_name_size - 1);
3017
3018 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3019 ok(len, "GetVolumePathNameW failed.\n");
3020
3021 len = lstrlenW( volume_prefix );
3022 if (len && volume_prefix[len - 1] == '\\') --len;
3023 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3024 expected[file_name_size - len - 1] = '\0';
3025
3026 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3027 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3028
3029 memset( info, 0xcc, info_size );
3030 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3031 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3032 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3033 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3034 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3035
3036 CloseHandle( h );
3037 HeapFree( GetProcessHeap(), 0, info );
3038 HeapFree( GetProcessHeap(), 0, expected );
3039 HeapFree( GetProcessHeap(), 0, volume_prefix );
3040 HeapFree( GetProcessHeap(), 0, file_name );
3041 }
3042
3043 static void test_file_all_name_information(void)
3044 {
3045 WCHAR *file_name, *volume_prefix, *expected;
3046 FILE_ALL_INFORMATION *info;
3047 ULONG old_redir = 1, tmp;
3048 UINT file_name_size;
3049 IO_STATUS_BLOCK io;
3050 UINT info_size;
3051 HRESULT hr;
3052 HANDLE h;
3053 UINT len;
3054
3055 /* GetVolumePathName is not present before w2k */
3056 if (!pGetVolumePathNameW) {
3057 win_skip("GetVolumePathNameW not found\n");
3058 return;
3059 }
3060
3061 file_name_size = GetSystemDirectoryW( NULL, 0 );
3062 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3063 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3064 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3065
3066 len = GetSystemDirectoryW( file_name, file_name_size );
3067 ok(len == file_name_size - 1,
3068 "GetSystemDirectoryW returned %u, expected %u.\n",
3069 len, file_name_size - 1);
3070
3071 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3072 ok(len, "GetVolumePathNameW failed.\n");
3073
3074 len = lstrlenW( volume_prefix );
3075 if (len && volume_prefix[len - 1] == '\\') --len;
3076 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3077 expected[file_name_size - len - 1] = '\0';
3078
3079 /* A bit more than we actually need, but it keeps the calculation simple. */
3080 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3081 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3082
3083 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3084 h = CreateFileW( file_name, GENERIC_READ,
3085 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3086 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3087 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3088 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3089
3090 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
3091 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
3092 hr, STATUS_INFO_LENGTH_MISMATCH);
3093
3094 memset( info, 0xcc, info_size );
3095 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
3096 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3097 hr, STATUS_BUFFER_OVERFLOW);
3098 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3099 U(io).Status, STATUS_BUFFER_OVERFLOW);
3100 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3101 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3102 ok(info->NameInformation.FileName[2] == 0xcccc,
3103 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
3104 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3105 "info->NameInformation.FileName[1] is %p, expected %p.\n",
3106 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3107 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3108
3109 memset( info, 0xcc, info_size );
3110 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3111 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3112 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3113 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3114 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3115 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
3116 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3117 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
3118 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3119 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
3120 "info->NameInformation.FileName is %s, expected %s.\n",
3121 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3122 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
3123 + info->NameInformation.FileNameLength,
3124 "io.Information is %lu\n", io.Information );
3125
3126 CloseHandle( h );
3127 HeapFree( GetProcessHeap(), 0, info );
3128 HeapFree( GetProcessHeap(), 0, expected );
3129 HeapFree( GetProcessHeap(), 0, volume_prefix );
3130
3131 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3132 {
3133 skip("Not running on WoW64, skipping test.\n");
3134 HeapFree( GetProcessHeap(), 0, file_name );
3135 return;
3136 }
3137
3138 h = CreateFileW( file_name, GENERIC_READ,
3139 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3140 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3141 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3142 HeapFree( GetProcessHeap(), 0, file_name );
3143
3144 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3145 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3146 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3147
3148 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3149 ok(len == file_name_size - 1,
3150 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3151 len, file_name_size - 1);
3152
3153 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3154 ok(len, "GetVolumePathNameW failed.\n");
3155
3156 len = lstrlenW( volume_prefix );
3157 if (len && volume_prefix[len - 1] == '\\') --len;
3158 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3159 expected[file_name_size - len - 1] = '\0';
3160
3161 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3162 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3163
3164 memset( info, 0xcc, info_size );
3165 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3166 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3167 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3168 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
3169 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3170
3171 CloseHandle( h );
3172 HeapFree( GetProcessHeap(), 0, info );
3173 HeapFree( GetProcessHeap(), 0, expected );
3174 HeapFree( GetProcessHeap(), 0, volume_prefix );
3175 HeapFree( GetProcessHeap(), 0, file_name );
3176 }
3177
3178 static void test_file_completion_information(void)
3179 {
3180 static const char buf[] = "testdata";
3181 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
3182 OVERLAPPED ov, *pov;
3183 IO_STATUS_BLOCK io;
3184 NTSTATUS status;
3185 DWORD num_bytes;
3186 HANDLE port, h;
3187 ULONG_PTR key;
3188 BOOL ret;
3189 int i;
3190
3191 if (!(h = create_temp_file(0))) return;
3192
3193 status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
3194 ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_INVALID_INFO_CLASS /* XP */,
3195 "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
3196 if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED)
3197 {
3198 win_skip("FileIoCompletionNotificationInformation class not supported\n");
3199 CloseHandle(h);
3200 return;
3201 }
3202
3203 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3204 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3205 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %08x\n", status);
3206
3207 CloseHandle(h);
3208 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3209
3210 info.Flags = FILE_SKIP_SET_EVENT_ON_HANDLE;
3211 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3212 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3213
3214 info.Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO;
3215 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3216 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3217
3218 CloseHandle(h);
3219 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3220
3221 info.Flags = ~0U;
3222 status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3223 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3224 ok(!(info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS), "got %08x\n", info.Flags);
3225
3226 memset(&ov, 0, sizeof(ov));
3227 ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
3228 port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
3229 ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError());
3230
3231 for (i = 0; i < 10; i++)
3232 {
3233 SetLastError(0xdeadbeef);
3234 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3235 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3236 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3237 ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3238 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3239 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3240 ret = FALSE;
3241 }
3242 if (ret)
3243 {
3244 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3245
3246 key = 0;
3247 pov = NULL;
3248 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3249 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3250 ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key);
3251 ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
3252 }
3253 else
3254 win_skip("WriteFile never returned TRUE\n");
3255
3256 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3257 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3258 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3259
3260 info.Flags = 0;
3261 status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3262 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3263 ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
3264
3265 for (i = 0; i < 10; i++)
3266 {
3267 SetLastError(0xdeadbeef);
3268 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3269 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3270 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3271 ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3272 ret = FALSE;
3273 }
3274 if (ret)
3275 {
3276 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3277
3278 pov = (void *)0xdeadbeef;
3279 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
3280 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3281 ok(pov == NULL, "expected NULL, got %p\n", pov);
3282 }
3283 else
3284 win_skip("WriteFile never returned TRUE\n");
3285
3286 info.Flags = 0;
3287 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3288 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3289
3290 info.Flags = 0;
3291 status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3292 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3293 ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
3294
3295 for (i = 0; i < 10; i++)
3296 {
3297 SetLastError(0xdeadbeef);
3298 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3299 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3300 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3301 ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3302 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3303 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3304 ret = FALSE;
3305 }
3306 if (ret)
3307 {
3308 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3309
3310 pov = (void *)0xdeadbeef;
3311 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3312 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3313 ok(pov == NULL, "expected NULL, got %p\n", pov);
3314 }
3315 else
3316 win_skip("WriteFile never returned TRUE\n");
3317
3318 CloseHandle(ov.hEvent);
3319 CloseHandle(port);
3320 CloseHandle(h);
3321 }
3322
3323 static void test_file_id_information(void)
3324 {
3325 BY_HANDLE_FILE_INFORMATION info;
3326 FILE_ID_INFORMATION fid;
3327 IO_STATUS_BLOCK io;
3328 NTSTATUS status;
3329 DWORD *dwords;
3330 HANDLE h;
3331 BOOL ret;
3332
3333 if (!(h = create_temp_file(0))) return;
3334
3335 memset( &fid, 0x11, sizeof(fid) );
3336 status = pNtQueryInformationFile( h, &io, &fid, sizeof(fid), FileIdInformation );
3337 if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
3338 {
3339 win_skip( "FileIdInformation not supported\n" );
3340 CloseHandle( h );
3341 return;
3342 }
3343
3344 memset( &info, 0x22, sizeof(info) );
3345 ret = GetFileInformationByHandle( h, &info );
3346 ok( ret, "GetFileInformationByHandle failed\n" );
3347
3348 dwords = (DWORD *)&fid.VolumeSerialNumber;
3349 ok( dwords[0] == info.dwVolumeSerialNumber, "expected %08x, got %08x\n",
3350 info.dwVolumeSerialNumber, dwords[0] );
3351 ok( dwords[1] != 0x11111111, "expected != 0x11111111\n" );
3352
3353 dwords = (DWORD *)&fid.FileId;
3354 ok( dwords[0] == info.nFileIndexLow, "expected %08x, got %08x\n", info.nFileIndexLow, dwords[0] );
3355 ok( dwords[1] == info.nFileIndexHigh, "expected %08x, got %08x\n", info.nFileIndexHigh, dwords[1] );
3356 ok( dwords[2] == 0, "expected 0, got %08x\n", dwords[2] );
3357 ok( dwords[3] == 0, "expected 0, got %08x\n", dwords[3] );
3358
3359 CloseHandle( h );
3360 }
3361
3362 static void test_file_access_information(void)
3363 {
3364 FILE_ACCESS_INFORMATION info;
3365 IO_STATUS_BLOCK io;
3366 NTSTATUS status;
3367 HANDLE h;
3368
3369 if (!(h = create_temp_file(0))) return;
3370
3371 status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation );
3372 ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
3373
3374 status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation );
3375 ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status );
3376
3377 memset(&info, 0x11, sizeof(info));
3378 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation );
3379 ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status );
3380 ok( info.AccessFlags == 0x13019f, "got %08x\n", info.AccessFlags );
3381
3382 CloseHandle( h );
3383 }
3384
3385 static void test_query_volume_information_file(void)
3386 {
3387 NTSTATUS status;
3388 HANDLE dir;
3389 WCHAR path[MAX_PATH];
3390 OBJECT_ATTRIBUTES attr;
3391 IO_STATUS_BLOCK io;
3392 UNICODE_STRING nameW;
3393 FILE_FS_VOLUME_INFORMATION *ffvi;
3394 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3395
3396 GetWindowsDirectoryW( path, MAX_PATH );
3397 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3398 attr.Length = sizeof(attr);
3399 attr.RootDirectory = 0;
3400 attr.ObjectName = &nameW;
3401 attr.Attributes = OBJ_CASE_INSENSITIVE;
3402 attr.SecurityDescriptor = NULL;
3403 attr.SecurityQualityOfService = NULL;
3404
3405 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3406 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3407 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3408 pRtlFreeUnicodeString( &nameW );
3409
3410 ZeroMemory( buf, sizeof(buf) );
3411 U(io).Status = 0xdadadada;
3412 io.Information = 0xcacacaca;
3413
3414 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
3415
3416 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
3417
3418 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3419 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3420
3421 todo_wine
3422 {
3423 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3424 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3425 io.Information);
3426
3427 ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
3428 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
3429 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
3430 }
3431 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
3432
3433 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
3434
3435 CloseHandle( dir );
3436 }
3437
3438 static void test_query_attribute_information_file(void)
3439 {
3440 NTSTATUS status;
3441 HANDLE dir;
3442 WCHAR path[MAX_PATH];
3443 OBJECT_ATTRIBUTES attr;
3444 IO_STATUS_BLOCK io;
3445 UNICODE_STRING nameW;
3446 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
3447 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3448
3449 GetWindowsDirectoryW( path, MAX_PATH );
3450 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3451 attr.Length = sizeof(attr);
3452 attr.RootDirectory = 0;
3453 attr.ObjectName = &nameW;
3454 attr.Attributes = OBJ_CASE_INSENSITIVE;
3455 attr.SecurityDescriptor = NULL;
3456 attr.SecurityQualityOfService = NULL;
3457
3458 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3459 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3460 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3461 pRtlFreeUnicodeString( &nameW );
3462
3463 ZeroMemory( buf, sizeof(buf) );
3464 U(io).Status = 0xdadadada;
3465 io.Information = 0xcacacaca;
3466
3467 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
3468
3469 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
3470
3471 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3472 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3473 ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
3474 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
3475 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
3476
3477 trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
3478 ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
3479 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
3480
3481 CloseHandle( dir );
3482 }
3483
3484 static void test_NtCreateFile(void)
3485 {
3486 static const struct test_data
3487 {
3488 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
3489 } td[] =
3490 {
3491 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3492 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
3493 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3494 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3495 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3496 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3497 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3498 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3499 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3500 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3501 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3502 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3503 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3504 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3505 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3506 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3507 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3508 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
3509 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
3510 };
3511 static const WCHAR fooW[] = {'f','o','o',0};
3512 NTSTATUS status;
3513 HANDLE handle;
3514 WCHAR path[MAX_PATH];
3515 OBJECT_ATTRIBUTES attr;
3516 IO_STATUS_BLOCK io;
3517 UNICODE_STRING nameW;
3518 DWORD ret, i;
3519
3520 GetTempPathW(MAX_PATH, path);
3521 GetTempFileNameW(path, fooW, 0, path);
3522 DeleteFileW(path);
3523 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
3524
3525 attr.Length = sizeof(attr);
3526 attr.RootDirectory = NULL;
3527 attr.ObjectName = &nameW;
3528 attr.Attributes = OBJ_CASE_INSENSITIVE;
3529 attr.SecurityDescriptor = NULL;
3530 attr.SecurityQualityOfService = NULL;
3531
3532 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3533 {
3534 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
3535 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
3536 td[i].disposition, 0, NULL, 0);
3537
3538 ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
3539
3540 if (!status)
3541 {
3542 ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
3543
3544 ret = GetFileAttributesW(path);
3545 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
3546 /* FIXME: leave only 'else' case below once Wine is fixed */
3547 if (ret != td[i].attrib_out)
3548 {
3549 todo_wine
3550 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3551 SetFileAttributesW(path, td[i].attrib_out);
3552 }
3553 else
3554 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3555
3556 CloseHandle(handle);
3557 }
3558
3559 if (td[i].needs_cleanup)
3560 {
3561 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3562 DeleteFileW(path);
3563 }
3564 }
3565
3566 pRtlFreeUnicodeString( &nameW );
3567 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3568 DeleteFileW( path );
3569 }
3570
3571 static void test_readonly(void)
3572 {
3573 static const WCHAR fooW[] = {'f','o','o',0};
3574 NTSTATUS status;
3575 HANDLE handle;
3576 WCHAR path[MAX_PATH];
3577 OBJECT_ATTRIBUTES attr;
3578 IO_STATUS_BLOCK io;
3579 UNICODE_STRING nameW;
3580
3581 GetTempPathW(MAX_PATH, path);
3582 GetTempFileNameW(path, fooW, 0, path);
3583 DeleteFileW(path);
3584 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
3585
3586 attr.Length = sizeof(attr);
3587 attr.RootDirectory = NULL;
3588 attr.ObjectName = &nameW;
3589 attr.Attributes = OBJ_CASE_INSENSITIVE;
3590 attr.SecurityDescriptor = NULL;
3591 attr.SecurityQualityOfService = NULL;
3592
3593 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL, FILE_ATTRIBUTE_READONLY,
3594 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_CREATE, 0, NULL, 0);
3595 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3596 CloseHandle(handle);
3597
3598 status = pNtOpenFile(&handle, GENERIC_WRITE, &attr, &io,
3599 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3600 ok(status == STATUS_ACCESS_DENIED, "got %#x\n", status);
3601 CloseHandle(handle);
3602
3603 status = pNtOpenFile(&handle, GENERIC_READ, &attr, &io,
3604 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3605 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3606 CloseHandle(handle);
3607
3608 status = pNtOpenFile(&handle, FILE_READ_ATTRIBUTES, &attr, &io,
3609 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3610 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3611 CloseHandle(handle);
3612
3613 status = pNtOpenFile(&handle, FILE_WRITE_ATTRIBUTES, &attr, &io,
3614 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3615 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3616 CloseHandle(handle);
3617
3618 status = pNtOpenFile(&handle, DELETE, &attr, &io,
3619 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3620 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3621 CloseHandle(handle);
3622
3623 status = pNtOpenFile(&handle, READ_CONTROL, &attr, &io,
3624 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3625 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3626 CloseHandle(handle);
3627
3628 status = pNtOpenFile(&handle, WRITE_DAC, &attr, &io,
3629 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3630 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3631 CloseHandle(handle);
3632
3633 status = pNtOpenFile(&handle, WRITE_OWNER, &attr, &io,
3634 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3635 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3636 CloseHandle(handle);
3637
3638 status = pNtOpenFile(&handle, SYNCHRONIZE, &attr, &io,
3639 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3640 ok(status == STATUS_SUCCESS, "got %#x\n", status);
3641 CloseHandle( handle );
3642
3643 pRtlFreeUnicodeString(&nameW);
3644 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3645 DeleteFileW(path);
3646 }
3647
3648 static void test_read_write(void)
3649 {
3650 static const char contents[14] = "1234567890abcd";
3651 char buf[256];
3652 HANDLE hfile, event;
3653 OVERLAPPED ovl;
3654 IO_STATUS_BLOCK iob;
3655 DWORD ret, bytes, status, off;
3656 LARGE_INTEGER offset;
3657 LONG i;
3658
3659 event = CreateEventA( NULL, TRUE, FALSE, NULL );
3660
3661 U(iob).Status = -1;
3662 iob.Information = -1;
3663 offset.QuadPart = 0;
3664 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3665 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3666 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3667 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3668
3669 U(iob).Status = -1;
3670 iob.Information = -1;
3671 offset.QuadPart = 0;
3672 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, NULL, sizeof(buf), &offset, NULL);
3673 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3674 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3675 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3676
3677 U(iob).Status = -1;
3678 iob.Information = -1;
3679 offset.QuadPart = 0;
3680 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3681 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3682 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3683 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3684
3685 U(iob).Status = -1;
3686 iob.Information = -1;
3687 offset.QuadPart = 0;
3688 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3689 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3690 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3691 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3692
3693 hfile = create_temp_file(0);
3694 if (!hfile) return;
3695
3696 U(iob).Status = -1;
3697 iob.Information = -1;
3698 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3699 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3700 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3701 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3702
3703 U(iob).Status = -1;
3704 iob.Information = -1;
3705 SetEvent(event);
3706 status = pNtWriteFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3707 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3708 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3709 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3710 ok(!is_signaled(event), "event is not signaled\n");
3711
3712 U(iob).Status = -1;
3713 iob.Information = -1;
3714 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3715 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3716 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3717 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3718
3719 U(iob).Status = -1;
3720 iob.Information = -1;
3721 SetEvent(event);
3722 status = pNtReadFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3723 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3724 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3725 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3726 ok(is_signaled(event), "event is not signaled\n");
3727
3728 U(iob).Status = -1;
3729 iob.Information = -1;
3730 SetEvent(event);
3731 status = pNtReadFile(hfile, event, NULL, NULL, &iob, (void*)0xdeadbeef, sizeof(contents), NULL, NULL);
3732 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3733 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3734 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3735 ok(is_signaled(event), "event is not signaled\n");
3736
3737 U(iob).Status = -1;
3738 iob.Information = -1;
3739 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
3740 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3741 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3742 ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
3743
3744 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3745
3746 U(iob).Status = -1;
3747 iob.Information = -1;
3748 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
3749 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
3750 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3751 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3752 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
3753
3754 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3755 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3756
3757 bytes = 0xdeadbeef;
3758 SetLastError(0xdeadbeef);
3759 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
3760 ok(!ret, "ReadFile should fail\n");
3761 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3762 ok(bytes == 0, "bytes %u\n", bytes);
3763
3764 bytes = 0xdeadbeef;
3765 SetLastError(0xdeadbeef);
3766 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3767 ok(ret, "ReadFile error %d\n", GetLastError());
3768 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3769 ok(bytes == 0, "bytes %u\n", bytes);
3770
3771 bytes = 0xdeadbeef;
3772 SetLastError(0xdeadbeef);
3773 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3774 ok(ret, "ReadFile error %d\n", GetLastError());
3775 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3776 ok(bytes == 0, "bytes %u\n", bytes);
3777
3778 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3779
3780 bytes = 0;
3781 SetLastError(0xdeadbeef);
3782 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3783 ok(ret, "ReadFile error %d\n", GetLastError());
3784 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3785 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3786
3787 for (i = -20; i < -1; i++)
3788 {
3789 if (i == -2) continue;
3790
3791 U(iob).Status = -1;
3792 iob.Information = -1;
3793 offset.QuadPart = (LONGLONG)i;
3794 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3795 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3796 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3797 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3798 }
3799
3800 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
3801
3802 U(iob).Status = -1;
3803 iob.Information = -1;
3804 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3805 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3806 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3807 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3808 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3809
3810 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3811 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3812
3813 U(iob).Status = -1;
3814 iob.Information = -1;
3815 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3816 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3817 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3818 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3819
3820 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3821
3822 bytes = 0;
3823 SetLastError(0xdeadbeef);
3824 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3825 ok(ret, "ReadFile error %d\n", GetLastError());
3826 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3827 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3828 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3829
3830 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3831 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3832
3833 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3834
3835 bytes = 0;
3836 SetLastError(0xdeadbeef);
3837 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
3838 ok(ret, "WriteFile error %d\n", GetLastError());
3839 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3840
3841 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3842 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3843
3844 /* test reading beyond EOF */
3845 bytes = -1;
3846 SetLastError(0xdeadbeef);
3847 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3848 ok(ret, "ReadFile error %d\n", GetLastError());
3849 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3850 ok(bytes == 0, "bytes %u\n", bytes);
3851
3852 bytes = -1;
3853 SetLastError(0xdeadbeef);
3854 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3855 ok(ret, "ReadFile error %d\n", GetLastError());
3856 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3857 ok(bytes == 0, "bytes %u\n", bytes);
3858
3859 bytes = -1;
3860 SetLastError(0xdeadbeef);
3861 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
3862 ok(ret, "ReadFile error %d\n", GetLastError());
3863 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3864 ok(bytes == 0, "bytes %u\n", bytes);
3865
3866 S(U(ovl)).Offset = sizeof(contents);
3867 S(U(ovl)).OffsetHigh = 0;
3868 ovl.Internal = -1;
3869 ovl.InternalHigh = -1;
3870 ovl.hEvent = 0;
3871 bytes = -1;
3872 SetLastError(0xdeadbeef);
3873 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3874 ok(!ret, "ReadFile should fail\n");
3875 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
3876 ok(bytes == 0, "bytes %u\n", bytes);
3877 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
3878 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3879
3880 S(U(ovl)).Offset = sizeof(contents);
3881 S(U(ovl)).OffsetHigh = 0;
3882 ovl.Internal = -1;
3883 ovl.InternalHigh = -1;
3884 ovl.hEvent = 0;
3885 bytes = -1;
3886 SetLastError(0xdeadbeef);
3887 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
3888 ok(ret, "ReadFile error %d\n", GetLastError());
3889 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3890 ok(bytes == 0, "bytes %u\n", bytes);
3891 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3892 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3893
3894 U(iob).Status = -1;
3895 iob.Information = -1;
3896 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3897 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3898 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3899 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3900
3901 U(iob).Status = -1;
3902 iob.Information = -1;
3903 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
3904 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3905 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3906 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3907
3908 U(iob).Status = -1;
3909 iob.Information = -1;
3910 offset.QuadPart = sizeof(contents);
3911 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3912 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3913 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3914 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3915
3916 U(iob).Status = -1;
3917 iob.Information = -1;
3918 offset.QuadPart = sizeof(contents);
3919 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3920 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3921 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3922 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3923
3924 U(iob).Status = -1;
3925 iob.Information = -1;
3926 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3927 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3928 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3929 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3930 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3931
3932 U(iob).Status = -1;
3933 iob.Information = -1;
3934 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3935 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3936 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3937 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3938 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3939
3940 for (i = -20; i < 0; i++)
3941 {
3942 if (i == -2) continue;
3943
3944 U(iob).Status = -1;
3945 iob.Information = -1;
3946 offset.QuadPart = (LONGLONG)i;
3947 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3948 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3949 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3950 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3951 }
3952
3953 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3954
3955 bytes = 0;
3956 SetLastError(0xdeadbeef);
3957 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3958 ok(ret, "ReadFile error %d\n", GetLastError());
3959 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3960 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3961
3962 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3963 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3964
3965 U(iob).Status = -1;
3966 iob.Information = -1;
3967 offset.QuadPart = 0;
3968 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3969 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3970 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3971 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3972 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3973
3974 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3975 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3976
3977 U(iob).Status = -1;
3978 iob.Information = -1;
3979 offset.QuadPart = sizeof(contents) - 4;
3980 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3981 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3982 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3983 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3984
3985 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3986 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3987
3988 U(iob).Status = -1;
3989 iob.Information = -1;
3990 offset.QuadPart = 0;
3991 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3992 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3993 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3994 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3995 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3996 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3997
3998 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3999 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4000
4001 S(U(ovl)).Offset = sizeof(contents) - 4;
4002 S(U(ovl)).OffsetHigh = 0;
4003 ovl.hEvent = 0;
4004 bytes = 0;
4005 SetLastError(0xdeadbeef);
4006 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4007 ok(ret, "WriteFile error %d\n", GetLastError());
4008 ok(bytes == 4, "bytes %u\n", bytes);
4009
4010 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4011 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4012
4013 S(U(ovl)).Offset = 0;
4014 S(U(ovl)).OffsetHigh = 0;
4015 ovl.Internal = -1;
4016 ovl.InternalHigh = -1;
4017 ovl.hEvent = 0;
4018 bytes = 0;
4019 SetLastError(0xdeadbeef);
4020 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4021 ok(ret, "ReadFile error %d\n", GetLastError());
4022 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4023 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4024 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4025 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4026 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4027
4028 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4029 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4030
4031 CloseHandle(hfile);
4032
4033 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
4034 if (!hfile) return;
4035
4036 bytes = 0xdeadbeef;
4037 SetLastError(0xdeadbeef);
4038 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
4039 ok(!ret, "ReadFile should fail\n");
4040 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
4041 ok(bytes == 0, "bytes %u\n", bytes);
4042
4043 S(U(ovl)).Offset = 0;
4044 S(U(ovl)).OffsetHigh = 0;
4045 ovl.Internal = -1;
4046 ovl.InternalHigh = -1;
4047 ovl.hEvent = 0;
4048 bytes = 0xdeadbeef;
4049 SetLastError(0xdeadbeef);
4050 /* ReadFile return value depends on Windows version and testing it is not practical */
4051 ReadFile(hfile, buf, 0, &bytes, &ovl);
4052 ok(bytes == 0, "bytes %u\n", bytes);
4053 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4054 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4055
4056 bytes = 0xdeadbeef;
4057 SetLastError(0xdeadbeef);
4058 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
4059 ok(!ret, "WriteFile should fail\n");
4060 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4061 ok(bytes == 0, "bytes %u\n", bytes);
4062
4063 U(iob).Status = -1;
4064 iob.Information = -1;
4065 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
4066 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
4067 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4068 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4069
4070 for (i = -20; i < -1; i++)
4071 {
4072 U(iob).Status = -1;
4073 iob.Information = -1;
4074 offset.QuadPart = (LONGLONG)i;
4075 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4076 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
4077 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4078 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4079 }
4080
4081 U(iob).Status = -1;
4082 iob.Information = -1;
4083 offset.QuadPart = 0;
4084 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4085 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4086 if (status == STATUS_PENDING)
4087 {
4088 ret = WaitForSingleObject(hfile, 3000);
4089 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4090 }
4091 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4092 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4093
4094 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4095 ok(off == 0, "expected 0, got %u\n", off);
4096
4097 bytes = 0xdeadbeef;
4098 SetLastError(0xdeadbeef);
4099 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4100 ok(!ret, "ReadFile should fail\n");
4101 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4102 ok(bytes == 0, "bytes %u\n", bytes);
4103
4104 U(iob).Status = -1;
4105 iob.Information = -1;
4106 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
4107 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
4108 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4109 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4110
4111 for (i = -20; i < 0; i++)
4112 {
4113 U(iob).Status = -1;
4114 iob.Information = -1;
4115 offset.QuadPart = (LONGLONG)i;
4116 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4117 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
4118 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4119 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4120 }
4121
4122 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4123 ok(off == 0, "expected 0, got %u\n", off);
4124
4125 /* test reading beyond EOF */
4126 offset.QuadPart = sizeof(contents);
4127 S(U(ovl)).Offset = offset.u.LowPart;
4128 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4129 ovl.Internal = -1;
4130 ovl.InternalHigh = -1;
4131 ovl.hEvent = 0;
4132 bytes = 0xdeadbeef;
4133 SetLastError(0xdeadbeef);
4134 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4135 ok(!ret, "ReadFile should fail\n");
4136 ret = GetLastError();
4137 ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
4138 ok(bytes == 0, "bytes %u\n", bytes);
4139
4140 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4141 ok(off == 0, "expected 0, got %u\n", off);
4142
4143 if (ret == ERROR_IO_PENDING)
4144 {
4145 bytes = 0xdeadbeef;
4146 SetLastError(0xdeadbeef);
4147 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4148 ok(!ret, "GetOverlappedResult should report FALSE\n");
4149 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
4150 ok(bytes == 0, "expected 0, read %u\n", bytes);
4151 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
4152 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4153 }
4154
4155 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4156 ok(off == 0, "expected 0, got %u\n", off);
4157
4158 offset.QuadPart = sizeof(contents);
4159 S(U(ovl)).Offset = offset.u.LowPart;
4160 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4161 ovl.Internal = -1;
4162 ovl.InternalHigh = -1;
4163 ovl.hEvent = 0;
4164 bytes = 0xdeadbeef;
4165 SetLastError(0xdeadbeef);
4166 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
4167 /* ReadFile return value depends on Windows version and testing it is not practical */
4168 if (!ret)
4169 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4170 ret = GetLastError();
4171 ok(bytes == 0, "bytes %u\n", bytes);
4172
4173 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4174 ok(off == 0, "expected 0, got %u\n", off);
4175
4176 if (ret == ERROR_IO_PENDING)
4177 {
4178 bytes = 0xdeadbeef;
4179 SetLastError(0xdeadbeef);
4180 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4181 ok(ret, "GetOverlappedResult should report TRUE\n");
4182 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4183 ok(bytes == 0, "expected 0, read %u\n", bytes);
4184 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4185 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4186 }
4187
4188 offset.QuadPart = sizeof(contents);
4189 S(U(ovl)).Offset = offset.u.LowPart;
4190 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4191 ovl.Internal = -1;
4192 ovl.InternalHigh = -1;
4193 ovl.hEvent = 0;
4194 bytes = 0xdeadbeef;
4195 SetLastError(0xdeadbeef);
4196 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
4197 /* ReadFile return value depends on Windows version and testing it is not practical */
4198 if (!ret)
4199 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4200 ret = GetLastError();
4201 ok(bytes == 0, "bytes %u\n", bytes);
4202
4203 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4204 ok(off == 0, "expected 0, got %u\n", off);
4205
4206 if (ret == ERROR_IO_PENDING)
4207 {
4208 bytes = 0xdeadbeef;
4209 SetLastError(0xdeadbeef);
4210 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4211 ok(ret, "GetOverlappedResult should report TRUE\n");
4212 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4213 ok(bytes == 0, "expected 0, read %u\n", bytes);
4214 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4215 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4216 }
4217
4218 U(iob).Status = -1;
4219 iob.Information = -1;
4220 offset.QuadPart = sizeof(contents);
4221 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4222 if (status == STATUS_PENDING)
4223 {
4224 ret = WaitForSingleObject(hfile, 3000);
4225 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4226 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
4227 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4228 }
4229 else
4230 {
4231 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
4232 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4233 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
4234 }
4235
4236 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4237 ok(off == 0, "expected 0, got %u\n", off);
4238
4239 U(iob).Status = -1;
4240 iob.Information = -1;
4241 offset.QuadPart = sizeof(contents);
4242 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4243 if (status == STATUS_PENDING)
4244 {
4245 ret = WaitForSingleObject(hfile, 3000);
4246 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4247 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4248 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4249 }
4250 else
4251 {
4252 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
4253 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4254 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4255 }
4256
4257 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4258 ok(off == 0, "expected 0, got %u\n", off);
4259
4260 S(U(ovl)).Offset = 0;
4261 S(U(ovl)).OffsetHigh = 0;
4262 ovl.Internal = -1;
4263 ovl.InternalHigh = -1;
4264 ovl.hEvent = 0;
4265 bytes = 0;
4266 SetLastError(0xdeadbeef);
4267 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4268 /* ReadFile return value depends on Windows version and testing it is not practical */
4269 if (!ret)
4270 {
4271 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4272 ok(bytes == 0, "bytes %u\n", bytes);
4273 }
4274 else ok(bytes == 14, "bytes %u\n", bytes);
4275 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4276 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4277
4278 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4279 ok(off == 0, "expected 0, got %u\n", off);
4280
4281 bytes = 0xdeadbeef;
4282 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4283 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4284 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4285 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4286 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4287 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4288
4289 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4290 ok(off == 0, "expected 0, got %u\n", off);
4291
4292 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4293 SetEndOfFile(hfile);
4294 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4295
4296 U(iob).Status = -1;
4297 iob.Information = -1;
4298 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4299 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4300 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4301 if (status == STATUS_PENDING)
4302 {
4303 ret = WaitForSingleObject(hfile, 3000);
4304 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4305 }
4306 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4307 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
4308
4309 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4310 ok(off == 0, "expected 0, got %u\n", off);
4311
4312 U(iob).Status = -1;
4313 iob.Information = -1;
4314 offset.QuadPart = 0;
4315 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4316 ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4317 if (status == STATUS_PENDING)
4318 {
4319 ret = WaitForSingleObject(hfile, 3000);
4320 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4321 }
4322 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4323 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4324
4325 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4326 ok(off == 0, "expected 0, got %u\n", off);
4327
4328 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4329 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4330
4331 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4332 ok(off == 0, "expected 0, got %u\n", off);
4333
4334 S(U(ovl)).Offset = sizeof(contents) - 4;
4335 S(U(ovl)).OffsetHigh = 0;
4336 ovl.Internal = -1;
4337 ovl.InternalHigh = -1;
4338 ovl.hEvent = 0;
4339 bytes = 0;
4340 SetLastError(0xdeadbeef);
4341 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4342 /* WriteFile return value depends on Windows version and testing it is not practical */
4343 if (!ret)
4344 {
4345 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4346 ok(bytes == 0, "bytes %u\n", bytes);
4347 ret = WaitForSingleObject(hfile, 3000);
4348 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4349 }
4350 else ok(bytes == 4, "bytes %u\n", bytes);
4351 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4352 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4353
4354 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4355 ok(off == 0, "expected 0, got %u\n", off);
4356
4357 bytes = 0xdeadbeef;
4358 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4359 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4360 ok(bytes == 4, "bytes %u\n", bytes);
4361 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4362 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4363
4364 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4365 ok(off == 0, "expected 0, got %u\n", off);
4366
4367 S(U(ovl)).Offset = 0;
4368 S(U(ovl)).OffsetHigh = 0;
4369 ovl.Internal = -1;
4370 ovl.InternalHigh = -1;
4371 ovl.hEvent = 0;
4372 bytes = 0;
4373 SetLastError(0xdeadbeef);
4374 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4375 /* ReadFile return value depends on Windows version and testing it is not practical */
4376 if (!ret)
4377 {
4378 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4379 ok(bytes == 0, "bytes %u\n", bytes);
4380 ret = WaitForSingleObject(hfile, 3000);
4381 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4382 }
4383 else ok(bytes == 14, "bytes %u\n", bytes);
4384 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4385 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4386
4387 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4388 ok(off == 0, "expected 0, got %u\n", off);
4389
4390 bytes = 0xdeadbeef;
4391 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4392 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4393 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4394 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4395 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4396 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4397 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4398
4399 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4400 ok(off == 0, "expected 0, got %u\n", off);
4401
4402 CloseHandle(event);
4403 CloseHandle(hfile);
4404 }
4405
4406 static void test_ioctl(void)
4407 {
4408 HANDLE event = CreateEventA(NULL, TRUE, FALSE, NULL);
4409 IO_STATUS_BLOCK iosb;
4410 HANDLE file;
4411 NTSTATUS status;
4412
4413 file = create_temp_file(FILE_FLAG_OVERLAPPED);
4414 ok(file != INVALID_HANDLE_VALUE, "could not create temp file\n");
4415
4416 SetEvent(event);
4417 status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
4418 todo_wine
4419 ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile returned %x\n", status);
4420 ok(!is_signaled(event), "event is signaled\n");
4421
4422 status = pNtFsControlFile(file, (HANDLE)0xdeadbeef, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
4423 ok(status == STATUS_INVALID_HANDLE, "NtFsControlFile returned %x\n", status);
4424
4425 CloseHandle(event);
4426 CloseHandle(file);
4427 }
4428
4429 static void test_flush_buffers_file(void)
4430 {
4431 char path[MAX_PATH], buffer[MAX_PATH];
4432 HANDLE hfile, hfileread;
4433 NTSTATUS status;
4434 IO_STATUS_BLOCK io_status_block;
4435
4436 GetTempPathA(MAX_PATH, path);
4437 GetTempFileNameA(path, "foo", 0, buffer);
4438 hfile = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
4439 FILE_ATTRIBUTE_NORMAL, 0);
4440 ok(hfile != INVALID_HANDLE_VALUE, "failed to create temp file.\n" );
4441
4442 hfileread = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
4443 OPEN_EXISTING, 0, NULL);
4444 ok(hfileread != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
4445
4446 status = pNtFlushBuffersFile(hfile, NULL);
4447 todo_wine
4448 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
4449
4450 status = pNtFlushBuffersFile(hfile, (IO_STATUS_BLOCK *)0xdeadbeaf);
4451 todo_wine
4452 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
4453
4454 status = pNtFlushBuffersFile(hfile, &io_status_block);
4455 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
4456
4457 status = pNtFlushBuffersFile(hfileread, &io_status_block);
4458 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#x.\n", status);
4459
4460 status = pNtFlushBuffersFile(NULL, &io_status_block);
4461 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#x.\n", status);
4462
4463 CloseHandle(hfileread);
4464 CloseHandle(hfile);
4465 hfile = CreateFileA(buffer, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
4466 OPEN_EXISTING, 0, NULL);
4467 ok(hfile != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
4468
4469 status = pNtFlushBuffersFile(hfile, &io_status_block);
4470 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
4471
4472 CloseHandle(hfile);
4473 DeleteFileA(buffer);
4474 }
4475
4476 static void test_query_ea(void)
4477 {
4478 #define EA_BUFFER_SIZE 4097
4479 unsigned char data[EA_BUFFER_SIZE + 8];
4480 unsigned char *buffer = (void *)(((DWORD_PTR)data + 7) & ~7);
4481 DWORD buffer_len, i;
4482 IO_STATUS_BLOCK io;
4483 NTSTATUS status;
4484 HANDLE handle;
4485
4486 if (!(handle = create_temp_file(0))) return;
4487
4488 /* test with INVALID_HANDLE_VALUE */
4489 U(io).Status = 0xdeadbeef;
4490 io.Information = 0xdeadbeef;
4491 memset(buffer, 0xcc, EA_BUFFER_SIZE);
4492 buffer_len = EA_BUFFER_SIZE - 1;
4493 status = pNtQueryEaFile(INVALID_HANDLE_VALUE, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4494 ok(status == STATUS_OBJECT_TYPE_MISMATCH, "expected STATUS_OBJECT_TYPE_MISMATCH, got %x\n", status);
4495 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4496 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4497 ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
4498
4499 /* test with 0xdeadbeef */
4500 U(io).Status = 0xdeadbeef;
4501 io.Information = 0xdeadbeef;
4502 memset(buffer, 0xcc, EA_BUFFER_SIZE);
4503 buffer_len = EA_BUFFER_SIZE - 1;
4504 status = pNtQueryEaFile((void *)0xdeadbeef, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4505 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %x\n", status);
4506 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4507 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4508 ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
4509
4510 /* test without buffer */
4511 U(io).Status = 0xdeadbeef;
4512 io.Information = 0xdeadbeef;
4513 status = pNtQueryEaFile(handle, &io, NULL, 0, TRUE, NULL, 0, NULL, FALSE);
4514 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4515 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4516 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4517
4518 /* test with zero buffer */
4519 U(io).Status = 0xdeadbeef;
4520 io.Information = 0xdeadbeef;
4521 status = pNtQueryEaFile(handle, &io, buffer, 0, TRUE, NULL, 0, NULL, FALSE);
4522 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4523 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4524 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4525
4526 /* test with very small buffer */
4527 U(io).Status = 0xdeadbeef;
4528 io.Information = 0xdeadbeef;
4529 memset(buffer, 0xcc, EA_BUFFER_SIZE);
4530 buffer_len = 4;
4531 status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4532 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4533 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4534 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4535 for (i = 0; i < buffer_len && !buffer[i]; i++);
4536 ok(i == buffer_len, "expected %u bytes filled with 0x00, got %u bytes\n", buffer_len, i);
4537 ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
4538
4539 /* test with very big buffer */
4540 U(io).Status = 0xdeadbeef;
4541 io.Information = 0xdeadbeef;
4542 memset(buffer, 0xcc, EA_BUFFER_SIZE);
4543 buffer_len = EA_BUFFER_SIZE - 1;
4544 status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4545 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4546 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4547 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4548 for (i = 0; i < buffer_len && !buffer[i]; i++);
4549 ok(i == buffer_len, "expected %u bytes filled with 0x00, got %u bytes\n", buffer_len, i);
4550 ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
4551
4552 CloseHandle(handle);
4553 #undef EA_BUFFER_SIZE
4554 }
4555
4556 static INT build_reparse_buffer(WCHAR *filename, REPARSE_DATA_BUFFER **pbuffer)
4557 {
4558 REPARSE_DATA_BUFFER *buffer;
4559 INT buffer_len, string_len;
4560 WCHAR *dest;
4561
4562 string_len = (lstrlenW(filename)+1)*sizeof(WCHAR);
4563 buffer_len = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[1]) + string_len;
4564 buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
4565 buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
4566 buffer->ReparseDataLength = sizeof(buffer->MountPointReparseBuffer) + string_len;
4567 buffer->MountPointReparseBuffer.SubstituteNameLength = string_len - sizeof(WCHAR);
4568 buffer->MountPointReparseBuffer.PrintNameOffset = string_len;
4569 dest = &buffer->MountPointReparseBuffer.PathBuffer[0];
4570 memcpy(dest, filename, string_len);
4571 *pbuffer = buffer;
4572 return buffer_len;
4573 }
4574
4575 static void test_junction_points(void)
4576 {
4577 static const WCHAR junctionW[] = {'\\','j','u','n','c','t','i','o','n',0};
4578 WCHAR path[MAX_PATH], junction_path[MAX_PATH], target_path[MAX_PATH];
4579 static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
4580 FILE_BASIC_INFORMATION old_attrib, new_attrib;
4581 static const WCHAR fooW[] = {'f','o','o',0};
4582 static WCHAR volW[] = {'c',':','\\',0};
4583 REPARSE_GUID_DATA_BUFFER guid_buffer;
4584 static const WCHAR dotW[] = {'.',0};
4585 REPARSE_DATA_BUFFER *buffer = NULL;
4586 DWORD dwret, dwLen, dwFlags, err;
4587 INT buffer_len, string_len;
4588 IO_STATUS_BLOCK iosb;
4589 UNICODE_STRING nameW;
4590 HANDLE hJunction;
4591 WCHAR *dest;
4592 BOOL bret;
4593
4594 /* Create a temporary folder for the junction point tests */
4595 GetTempFileNameW(dotW, fooW, 0, path);
4596 DeleteFileW(path);
4597 if (!CreateDirectoryW(path, NULL))
4598 {
4599 win_skip("Unable to create a temporary junction point directory.\n");
4600 return;
4601 }
4602
4603 /* Check that the volume this folder is located on supports junction points */
4604 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
4605 volW[0] = nameW.Buffer[4];
4606 pRtlFreeUnicodeString( &nameW );
4607 GetVolumeInformationW(volW, 0, 0, 0, &dwLen, &dwFlags, 0, 0);
4608 if (!(dwFlags & FILE_SUPPORTS_REPARSE_POINTS))
4609 {
4610 skip("File system does not support junction points.\n");
4611 RemoveDirectoryW(path);
4612 return;
4613 }
4614
4615 /* Create the folder to be replaced by a junction point */
4616 lstrcpyW(junction_path, path);
4617 lstrcatW(junction_path, junctionW);
4618 bret = CreateDirectoryW(junction_path, NULL);
4619 ok(bret, "Failed to create junction point directory.\n");
4620
4621 /* Create a destination folder for the junction point to target */
4622 lstrcpyW(target_path, path);
4623 lstrcatW(target_path, targetW);
4624 bret = CreateDirectoryW(target_path, NULL);
4625 ok(bret, "Failed to create junction point target directory.\n");
4626 pRtlDosPathNameToNtPathName_U(target_path, &nameW, NULL, NULL);
4627
4628 /* Create the junction point */
4629 hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
4630 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
4631 if (hJunction == INVALID_HANDLE_VALUE)
4632 {
4633 win_skip("Failed to open junction point directory handle (0x%x).\n", GetLastError());
4634 goto cleanup;
4635 }
4636 dwret = NtQueryInformationFile(hJunction, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
4637 ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
4638 buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
4639 bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
4640 ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
4641
4642 /* Check the file attributes of the junction point */
4643 dwret = GetFileAttributesW(junction_path);
4644 ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret);
4645 ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: %d)\n", dwret);
4646
4647 /* Read back the junction point */
4648 HeapFree(GetProcessHeap(), 0, buffer);
4649 buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR);
4650 buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
4651 bret = DeviceIoControl(hJunction, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0);
4652 string_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
4653 dest = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
4654 ok(bret, "Failed to read junction point!\n");
4655 ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Junction point destination does not match ('%s' != '%s')!\n",
4656 wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer));
4657
4658 /* Delete the junction point */
4659 memset(&old_attrib, 0x00, sizeof(old_attrib));
4660 old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
4661 dwret = NtSetInformationFile(hJunction, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
4662 ok(dwret == STATUS_SUCCESS, "Failed to set junction point folder's attributes (0x%x).\n", dwret);
4663 memset(&guid_buffer, 0x00, sizeof(guid_buffer));
4664 guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
4665 bret = DeviceIoControl(hJunction, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
4666 REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &dwret, 0);
4667 ok(bret, "Failed to delete junction point! (0x%x)\n", GetLastError());
4668 memset(&new_attrib, 0x00, sizeof(new_attrib));
4669 dwret = NtQueryInformationFile(hJunction, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
4670 ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
4671 ok(old_attrib.LastAccessTime.QuadPart == new_attrib.LastAccessTime.QuadPart,
4672 "Junction point folder's access time does not match.\n");
4673 CloseHandle(hJunction);
4674
4675 /* Check deleting a junction point as if it were a directory */
4676 HeapFree(GetProcessHeap(), 0, buffer);
4677 hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
4678 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
4679 buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
4680 bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
4681 ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
4682 CloseHandle(hJunction);
4683 bret = RemoveDirectoryW(junction_path);
4684 ok(bret, "Failed to delete junction point as directory!\n");
4685 dwret = GetFileAttributesW(junction_path);
4686 ok(dwret == (DWORD)~0, "Junction point still exists (attributes: 0x%x)!\n", dwret);
4687
4688 /* Check deleting a junction point as if it were a file */
4689 HeapFree(GetProcessHeap(), 0, buffer);
4690 bret = CreateDirectoryW(junction_path, NULL);
4691 ok(bret, "Failed to create junction point target directory.\n");
4692 hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
4693 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
4694 buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
4695 bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
4696 ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
4697 CloseHandle(hJunction);
4698 bret = DeleteFileW(junction_path);
4699 ok(!bret, "Succeeded in deleting junction point as file!\n");
4700 err = GetLastError();
4701 ok(err == ERROR_ACCESS_DENIED, "Expected last error 0x%x for DeleteFile on junction point (actually 0x%x)!\n",
4702 ERROR_ACCESS_DENIED, err);
4703 dwret = GetFileAttributesW(junction_path);
4704 ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret);
4705 ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: 0x%x)\n", dwret);
4706
4707 /* Test deleting a junction point's target */
4708 dwret = GetFileAttributesW(junction_path);
4709 ok(dwret == 0x410 || broken(dwret == 0x430) /* win2k */,
4710 "Unexpected junction point attributes (0x%x != 0x410)!\n", dwret);
4711 bret = RemoveDirectoryW(target_path);
4712 ok(bret, "Failed to delete junction point target!\n");
4713 bret = CreateDirectoryW(target_path, NULL);
4714 ok(bret, "Failed to create junction point target directory.\n");
4715
4716 cleanup:
4717 /* Cleanup */
4718 pRtlFreeUnicodeString( &nameW );
4719 HeapFree(GetProcessHeap(), 0, buffer);
4720 bret = RemoveDirectoryW(junction_path);
4721 ok(bret, "Failed to remove temporary junction point directory!\n");
4722 bret = RemoveDirectoryW(target_path);
4723 ok(bret, "Failed to remove temporary target directory!\n");
4724 RemoveDirectoryW(path);
4725 }
4726
4727 START_TEST(file)
4728 {
4729 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
4730 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
4731 if (!hntdll)
4732 {
4733 skip("not running on NT, skipping test\n");
4734 return;
4735 }
4736
4737 pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
4738 pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
4739
4740 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
4741 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
4742 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
4743 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
4744 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
4745 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
4746 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
4747 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
4748 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
4749 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
4750 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
4751 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
4752 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
4753 pNtFsControlFile = (void *)GetProcAddress(hntdll, "NtFsControlFile");
4754 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
4755 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
4756 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
4757 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
4758 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
4759 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
4760 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
4761 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
4762 pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
4763 pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
4764 pNtFlushBuffersFile = (void *)GetProcAddress(hntdll, "NtFlushBuffersFile");
4765 pNtQueryEaFile = (void *)GetProcAddress(hntdll, "NtQueryEaFile");
4766
4767 test_read_write();
4768 test_NtCreateFile();
4769 test_readonly();
4770 create_file_test();
4771 open_file_test();
4772 delete_file_test();
4773 read_file_test();
4774 append_file_test();
4775 nt_mailslot_test();
4776 test_iocompletion();
4777 test_file_basic_information();
4778 test_file_all_information();
4779 test_file_both_information();
4780 test_file_name_information();
4781 test_file_full_size_information();
4782 test_file_all_name_information();
4783 test_file_rename_information();
4784 test_file_link_information();
4785 test_file_disposition_information();
4786 test_file_completion_information();
4787 test_file_id_information();
4788 test_file_access_information();
4789 test_query_volume_information_file();
4790 test_query_attribute_information_file();
4791 test_ioctl();
4792 test_flush_buffers_file();
4793 test_query_ea();
4794 test_junction_points();
4795 }