ntdll: Improve stub of NtQueryEaFile.
[wine.git] / dlls / ntdll / tests / file.c
blobc011733626f5e62107a4a26894647a77306600d2
1 /* Unit test suite for Ntdll file functions
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2011 Dmitry Timoshkov
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.
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.
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
22 * NOTES
23 * We use function pointers here as there is no import library for NTDLL on
24 * windows.
27 #include <stdio.h>
28 #include <stdarg.h>
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
34 #define WIN32_NO_STATUS
36 #include "wine/test.h"
37 #include "winternl.h"
38 #include "winuser.h"
39 #include "winioctl.h"
40 #include "winnls.h"
42 #ifndef IO_COMPLETION_ALL_ACCESS
43 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
44 #endif
46 static BOOL (WINAPI * pGetVolumePathNameW)(LPCWSTR, LPWSTR, DWORD);
47 static UINT (WINAPI *pGetSystemWow64DirectoryW)( LPWSTR, UINT );
49 static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
50 static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
51 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
52 static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
54 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
55 ULONG, ULONG, ULONG, PLARGE_INTEGER );
56 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
57 static NTSTATUS (WINAPI *pNtOpenFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
58 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
59 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
60 PIO_APC_ROUTINE apc, void* apc_user,
61 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
62 PLARGE_INTEGER offset, PULONG key);
63 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
64 PIO_APC_ROUTINE apc, void* apc_user,
65 PIO_STATUS_BLOCK io_status,
66 const void* buffer, ULONG length,
67 PLARGE_INTEGER offset, PULONG key);
68 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
69 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
70 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
71 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);
73 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
74 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
75 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
76 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
77 static NTSTATUS (WINAPI *pNtRemoveIoCompletionEx)(HANDLE,FILE_IO_COMPLETION_INFORMATION*,ULONG,ULONG*,LARGE_INTEGER*,BOOLEAN);
78 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
79 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
80 static NTSTATUS (WINAPI *pNtQueryAttributesFile)(const OBJECT_ATTRIBUTES*,FILE_BASIC_INFORMATION*);
81 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
82 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
83 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
84 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
85 static NTSTATUS (WINAPI *pNtQueryFullAttributesFile)(const OBJECT_ATTRIBUTES*, FILE_NETWORK_OPEN_INFORMATION*);
86 static NTSTATUS (WINAPI *pNtFlushBuffersFile)(HANDLE, IO_STATUS_BLOCK*);
87 static NTSTATUS (WINAPI *pNtQueryEaFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,BOOLEAN,PVOID,ULONG,PULONG,BOOLEAN);
89 static WCHAR fooW[] = {'f','o','o',0};
91 static inline BOOL is_signaled( HANDLE obj )
93 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
96 #define TEST_BUF_LEN 3
98 static HANDLE create_temp_file( ULONG flags )
100 char path[MAX_PATH], buffer[MAX_PATH];
101 HANDLE handle;
103 GetTempPathA( MAX_PATH, path );
104 GetTempFileNameA( path, "foo", 0, buffer );
105 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
106 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
107 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
108 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
111 #define CVALUE_FIRST 0xfffabbcc
112 #define CKEY_FIRST 0x1030341
113 #define CKEY_SECOND 0x132E46
115 static ULONG get_pending_msgs(HANDLE h)
117 NTSTATUS res;
118 ULONG a, req;
120 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
121 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %lx\n", res );
122 if (res != STATUS_SUCCESS) return -1;
123 ok( req == sizeof(a), "Unexpected response size: %lx\n", req );
124 return a;
127 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
129 int *count = arg;
131 trace( "apc called block %p iosb.status %lx iosb.info %Iu\n",
132 iosb, U(*iosb).Status, iosb->Information );
133 (*count)++;
134 ok( !reserved, "reserved is not 0: %lx\n", reserved );
137 static void create_file_test(void)
139 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
140 '\\','f','a','i','l','i','n','g',0};
141 static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
142 static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
143 static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
144 static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
145 static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
146 static const char testdata[] = "Hello World";
147 FILE_NETWORK_OPEN_INFORMATION info;
148 NTSTATUS status;
149 HANDLE dir, file;
150 WCHAR path[MAX_PATH];
151 OBJECT_ATTRIBUTES attr;
152 IO_STATUS_BLOCK io;
153 UNICODE_STRING nameW;
154 LARGE_INTEGER offset;
155 char buf[32];
156 DWORD ret;
158 GetCurrentDirectoryW( MAX_PATH, path );
159 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
160 attr.Length = sizeof(attr);
161 attr.RootDirectory = 0;
162 attr.ObjectName = &nameW;
163 attr.Attributes = OBJ_CASE_INSENSITIVE;
164 attr.SecurityDescriptor = NULL;
165 attr.SecurityQualityOfService = NULL;
167 /* try various open modes and options on directories */
168 status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0,
169 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
170 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
172 U(io).Status = 0xdeadbeef;
173 offset.QuadPart = 0;
174 status = pNtReadFile( dir, NULL, NULL, NULL, &io, buf, sizeof(buf), &offset, NULL );
175 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtReadFile error %08lx\n", status );
176 if (status == STATUS_PENDING)
178 ret = WaitForSingleObject( dir, 1000 );
179 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %lu\n", ret );
180 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
181 "expected STATUS_INVALID_DEVICE_REQUEST, got %08lx\n", U(io).Status );
184 U(io).Status = 0xdeadbeef;
185 offset.QuadPart = 0;
186 status = pNtWriteFile( dir, NULL, NULL, NULL, &io, testdata, sizeof(testdata), &offset, NULL);
187 todo_wine
188 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtWriteFile error %08lx\n", status );
189 if (status == STATUS_PENDING)
191 ret = WaitForSingleObject( dir, 1000 );
192 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %lu\n", ret );
193 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
194 "expected STATUS_INVALID_DEVICE_REQUEST, got %08lx\n", U(io).Status );
197 CloseHandle( dir );
199 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
200 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
201 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
202 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
204 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
205 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
206 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
207 CloseHandle( dir );
209 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
210 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
211 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
213 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
214 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
215 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
217 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
218 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
219 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
221 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
222 FILE_OPEN, 0, NULL, 0 );
223 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
224 CloseHandle( dir );
226 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
227 FILE_CREATE, 0, NULL, 0 );
228 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
229 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
231 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
232 FILE_OPEN_IF, 0, NULL, 0 );
233 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
234 CloseHandle( dir );
236 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
237 FILE_SUPERSEDE, 0, NULL, 0 );
238 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
239 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
241 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
242 FILE_OVERWRITE, 0, NULL, 0 );
243 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
244 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
246 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
247 FILE_OVERWRITE_IF, 0, NULL, 0 );
248 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
249 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
251 pRtlFreeUnicodeString( &nameW );
253 pRtlInitUnicodeString( &nameW, systemrootW );
254 attr.Length = sizeof(attr);
255 attr.RootDirectory = NULL;
256 attr.ObjectName = &nameW;
257 attr.Attributes = OBJ_CASE_INSENSITIVE;
258 attr.SecurityDescriptor = NULL;
259 attr.SecurityQualityOfService = NULL;
260 dir = NULL;
261 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
262 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
263 todo_wine
264 ok( status == STATUS_INVALID_PARAMETER,
265 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
267 /* Invalid chars in file/dirnames */
268 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
269 attr.ObjectName = &nameW;
270 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
271 FILE_SHARE_READ, FILE_CREATE,
272 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
273 ok(status == STATUS_OBJECT_NAME_INVALID,
274 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status);
276 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
277 0, FILE_CREATE,
278 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
279 ok(status == STATUS_OBJECT_NAME_INVALID,
280 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status);
281 pRtlFreeUnicodeString(&nameW);
283 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
284 attr.ObjectName = &nameW;
285 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
286 FILE_SHARE_READ, FILE_CREATE,
287 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
288 ok(status == STATUS_OBJECT_NAME_INVALID,
289 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status);
291 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
292 0, FILE_CREATE,
293 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
294 ok(status == STATUS_OBJECT_NAME_INVALID,
295 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status);
296 pRtlFreeUnicodeString(&nameW);
298 pRtlInitUnicodeString( &nameW, pathInvalidNtW );
299 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
300 FILE_SHARE_READ, FILE_CREATE,
301 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
302 ok( status == STATUS_OBJECT_NAME_INVALID,
303 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
305 status = pNtQueryFullAttributesFile( &attr, &info );
306 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
307 "query %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
309 pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
310 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
311 FILE_SHARE_READ, FILE_CREATE,
312 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
313 ok( status == STATUS_OBJECT_NAME_INVALID,
314 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
316 status = pNtQueryFullAttributesFile( &attr, &info );
317 ok( status == STATUS_OBJECT_NAME_INVALID,
318 "query %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
320 pRtlInitUnicodeString( &nameW, pathInvalidDosW );
321 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
322 FILE_SHARE_READ, FILE_CREATE,
323 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
324 ok( status == STATUS_OBJECT_NAME_INVALID,
325 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
327 status = pNtQueryFullAttributesFile( &attr, &info );
328 ok( status == STATUS_OBJECT_NAME_INVALID,
329 "query %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
332 static void open_file_test(void)
334 static const WCHAR testdirW[] = {'o','p','e','n','f','i','l','e','t','e','s','t',0};
335 static const char testdata[] = "Hello World";
336 NTSTATUS status;
337 HANDLE dir, root, handle, file;
338 WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
339 BYTE data[1024];
340 OBJECT_ATTRIBUTES attr;
341 IO_STATUS_BLOCK io;
342 UNICODE_STRING nameW;
343 UINT i, len;
344 BOOL ret, restart = TRUE;
345 DWORD numbytes;
347 len = GetWindowsDirectoryW( path, MAX_PATH );
348 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
349 attr.Length = sizeof(attr);
350 attr.RootDirectory = 0;
351 attr.ObjectName = &nameW;
352 attr.Attributes = 0;
353 attr.SecurityDescriptor = NULL;
354 attr.SecurityQualityOfService = NULL;
355 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
356 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
357 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
358 pRtlFreeUnicodeString( &nameW );
360 path[3] = 0; /* root of the drive */
361 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
362 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
363 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
364 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
365 pRtlFreeUnicodeString( &nameW );
367 /* test opening system dir with RootDirectory set to windows dir */
368 GetSystemDirectoryW( path, MAX_PATH );
369 while (path[len] == '\\') len++;
370 nameW.Buffer = path + len;
371 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
372 attr.RootDirectory = dir;
373 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
374 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
375 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
376 CloseHandle( handle );
378 /* try uppercase name */
379 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
380 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
381 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
382 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
383 CloseHandle( handle );
385 /* try with leading backslash */
386 nameW.Buffer--;
387 nameW.Length += sizeof(WCHAR);
388 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
389 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
390 ok( status == STATUS_INVALID_PARAMETER ||
391 status == STATUS_OBJECT_NAME_INVALID ||
392 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
393 "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
394 if (!status) CloseHandle( handle );
396 /* try with empty name */
397 nameW.Length = 0;
398 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
399 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
400 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
401 CloseHandle( handle );
402 CloseHandle( dir );
404 attr.RootDirectory = 0;
405 wcscat( path, L"\\cmd.exe" );
406 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
407 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
408 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
409 ok( status == STATUS_NOT_A_DIRECTORY, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
410 CloseHandle( handle );
411 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
412 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE );
413 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
414 CloseHandle( handle );
415 pRtlFreeUnicodeString( &nameW );
417 wcscat( path, L"\\cmd.exe" );
418 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
419 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
420 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
421 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
422 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
423 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE );
424 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
425 pRtlFreeUnicodeString( &nameW );
427 GetTempPathW( MAX_PATH, path );
428 lstrcatW( path, testdirW );
429 CreateDirectoryW( path, NULL );
431 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
432 attr.RootDirectory = NULL;
433 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
434 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
435 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
436 pRtlFreeUnicodeString( &nameW );
438 GetTempFileNameW( path, fooW, 0, tmpfile );
439 file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
440 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError() );
441 numbytes = 0xdeadbeef;
442 ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
443 ok( ret, "WriteFile failed with error %lu\n", GetLastError() );
444 ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
445 CloseHandle( file );
447 /* try open by file id */
449 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
450 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
452 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
454 restart = FALSE;
456 if (!info->FileId.QuadPart) continue;
458 nameW.Buffer = (WCHAR *)&info->FileId;
459 nameW.Length = sizeof(info->FileId);
460 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
461 attr.RootDirectory = dir;
462 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
463 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
464 FILE_SHARE_READ,
465 FILE_OPEN_BY_FILE_ID |
466 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
467 ok( status == STATUS_SUCCESS, "open %s failed %lx\n", wine_dbgstr_w(info->FileName), status );
468 if (!status)
470 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
472 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
474 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
476 /* check that it's the same file/directory */
478 /* don't check the size for directories */
479 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
480 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
481 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
483 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
484 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
486 CloseHandle( handle );
488 /* try same thing from drive root */
489 attr.RootDirectory = root;
490 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
491 FILE_SHARE_READ|FILE_SHARE_WRITE,
492 FILE_OPEN_BY_FILE_ID |
493 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
494 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
495 "open %s failed %lx\n", wine_dbgstr_w(info->FileName), status );
496 if (!status) CloseHandle( handle );
500 CloseHandle( dir );
501 CloseHandle( root );
503 pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
504 attr.Length = sizeof(attr);
505 attr.RootDirectory = 0;
506 attr.ObjectName = &nameW;
507 attr.Attributes = OBJ_CASE_INSENSITIVE;
508 attr.SecurityDescriptor = NULL;
509 attr.SecurityQualityOfService = NULL;
510 status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
511 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
512 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
513 pRtlFreeUnicodeString( &nameW );
515 numbytes = 0xdeadbeef;
516 memset( data, 0, sizeof(data) );
517 ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
518 ok( ret, "ReadFile failed with error %lu\n", GetLastError() );
519 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
520 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
522 nameW.Length = sizeof(fooW) - sizeof(WCHAR);
523 nameW.Buffer = fooW;
524 attr.RootDirectory = file;
525 attr.ObjectName = &nameW;
526 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
527 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
528 ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
529 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08lx\n", status );
531 nameW.Length = 0;
532 nameW.Buffer = NULL;
533 attr.RootDirectory = file;
534 attr.ObjectName = &nameW;
535 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
536 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
537 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(tmpfile), status );
539 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
540 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %lu\n", numbytes );
541 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
542 ok( numbytes == 0, "SetFilePointer returned %lu\n", numbytes );
544 numbytes = 0xdeadbeef;
545 memset( data, 0, sizeof(data) );
546 ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
547 ok( ret, "ReadFile failed with error %lu\n", GetLastError() );
548 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
549 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
551 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
552 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %lu\n", numbytes );
553 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
554 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %lu\n", numbytes );
556 CloseHandle( file );
557 CloseHandle( root );
558 DeleteFileW( tmpfile );
559 RemoveDirectoryW( path );
562 static void delete_file_test(void)
564 NTSTATUS ret;
565 OBJECT_ATTRIBUTES attr;
566 UNICODE_STRING nameW;
567 WCHAR pathW[MAX_PATH];
568 WCHAR pathsubW[MAX_PATH];
569 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
570 static const WCHAR subdirW[] = {'\\','s','u','b',0};
572 ret = GetTempPathW(MAX_PATH, pathW);
573 if (!ret)
575 ok(0, "couldn't get temp dir\n");
576 return;
578 if (ret + ARRAY_SIZE(testdirW)-1 + ARRAY_SIZE(subdirW)-1 >= MAX_PATH)
580 ok(0, "MAX_PATH exceeded in constructing paths\n");
581 return;
584 lstrcatW(pathW, testdirW);
585 lstrcpyW(pathsubW, pathW);
586 lstrcatW(pathsubW, subdirW);
588 ret = CreateDirectoryW(pathW, NULL);
589 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
590 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
592 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
593 return;
596 attr.Length = sizeof(attr);
597 attr.RootDirectory = 0;
598 attr.Attributes = OBJ_CASE_INSENSITIVE;
599 attr.ObjectName = &nameW;
600 attr.SecurityDescriptor = NULL;
601 attr.SecurityQualityOfService = NULL;
603 /* test NtDeleteFile on an empty directory */
604 ret = pNtDeleteFile(&attr);
605 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
606 ret = RemoveDirectoryW(pathW);
607 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
609 /* test NtDeleteFile on a non-empty directory */
610 ret = CreateDirectoryW(pathW, NULL);
611 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
612 ret = CreateDirectoryW(pathsubW, NULL);
613 ok(ret == TRUE, "couldn't create directory subdir\n");
614 ret = pNtDeleteFile(&attr);
615 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
616 ret = RemoveDirectoryW(pathsubW);
617 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
618 ret = RemoveDirectoryW(pathW);
619 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
621 pRtlFreeUnicodeString( &nameW );
624 #define TEST_OVERLAPPED_READ_SIZE 4096
626 static void read_file_test(void)
628 DECLSPEC_ALIGN(TEST_OVERLAPPED_READ_SIZE) static unsigned char aligned_buffer[TEST_OVERLAPPED_READ_SIZE];
629 const char text[] = "foobar";
630 HANDLE handle;
631 IO_STATUS_BLOCK iosb;
632 NTSTATUS status;
633 int apc_count = 0;
634 char buffer[128];
635 LARGE_INTEGER offset;
636 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
638 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
639 apc_count = 0;
640 U(iosb).Status = 0xdeadbabe;
641 iosb.Information = 0xdeadbeef;
642 offset.QuadPart = 0;
643 ResetEvent( event );
644 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
645 ok( status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
646 "wrong status %lx.\n", status );
647 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
648 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %lx\n", U(iosb).Status );
649 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
650 ok( is_signaled( event ), "event is not signaled\n" );
651 ok( !apc_count, "apc was called\n" );
652 SleepEx( 1, TRUE ); /* alertable sleep */
653 ok( apc_count == 1, "apc was not called\n" );
655 apc_count = 0;
656 U(iosb).Status = 0xdeadbabe;
657 iosb.Information = 0xdeadbeef;
658 offset.QuadPart = 0;
659 ResetEvent( event );
660 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
661 ok(status == STATUS_PENDING
662 || broken(status == STATUS_SUCCESS) /* before Vista */,
663 "wrong status %lx.\n", status);
664 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
665 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %lx\n", U(iosb).Status );
666 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
667 ok( is_signaled( event ), "event is not signaled\n" );
668 ok( !apc_count, "apc was called\n" );
669 SleepEx( 1, TRUE ); /* alertable sleep */
670 ok( apc_count == 1, "apc was not called\n" );
672 /* read beyond eof */
673 apc_count = 0;
674 U(iosb).Status = 0xdeadbabe;
675 iosb.Information = 0xdeadbeef;
676 offset.QuadPart = strlen(text) + 2;
677 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
678 ok(status == STATUS_PENDING || broken(status == STATUS_END_OF_FILE) /* before Vista */,
679 "expected STATUS_PENDING, got %#lx\n", status);
680 if (status == STATUS_PENDING) /* vista */
682 WaitForSingleObject( event, 1000 );
683 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %lx\n", U(iosb).Status );
684 ok( iosb.Information == 0, "wrong info %Iu\n", iosb.Information );
685 ok( is_signaled( event ), "event is not signaled\n" );
686 ok( !apc_count, "apc was called\n" );
687 SleepEx( 1, TRUE ); /* alertable sleep */
688 ok( apc_count == 1, "apc was not called\n" );
690 CloseHandle( handle );
692 /* now a non-overlapped file */
693 if (!(handle = create_temp_file(0))) return;
694 apc_count = 0;
695 U(iosb).Status = 0xdeadbabe;
696 iosb.Information = 0xdeadbeef;
697 offset.QuadPart = 0;
698 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
699 ok( status == STATUS_END_OF_FILE ||
700 status == STATUS_SUCCESS ||
701 status == STATUS_PENDING, /* vista */
702 "wrong status %lx\n", status );
703 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
704 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %lx\n", U(iosb).Status );
705 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
706 ok( is_signaled( event ), "event is not signaled\n" );
707 ok( !apc_count, "apc was called\n" );
708 SleepEx( 1, TRUE ); /* alertable sleep */
709 ok( apc_count == 1, "apc was not called\n" );
711 apc_count = 0;
712 U(iosb).Status = 0xdeadbabe;
713 iosb.Information = 0xdeadbeef;
714 offset.QuadPart = 0;
715 ResetEvent( event );
716 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
717 ok( status == STATUS_SUCCESS, "wrong status %lx\n", status );
718 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %lx\n", U(iosb).Status );
719 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
720 ok( is_signaled( event ), "event is not signaled\n" );
721 ok( !apc_count, "apc was called\n" );
722 SleepEx( 1, TRUE ); /* alertable sleep */
723 todo_wine ok( !apc_count, "apc was called\n" );
725 /* read beyond eof */
726 apc_count = 0;
727 U(iosb).Status = 0xdeadbabe;
728 iosb.Information = 0xdeadbeef;
729 offset.QuadPart = strlen(text) + 2;
730 ResetEvent( event );
731 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
732 ok( status == STATUS_END_OF_FILE, "wrong status %lx\n", status );
733 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %lx\n", U(iosb).Status );
734 ok( iosb.Information == 0, "wrong info %Iu\n", iosb.Information );
735 ok( is_signaled( event ), "event is not signaled\n" );
736 ok( !apc_count, "apc was called\n" );
737 SleepEx( 1, TRUE ); /* alertable sleep */
738 ok( !apc_count, "apc was called\n" );
740 CloseHandle( handle );
742 if (!(handle = create_temp_file(FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING)))
743 return;
745 apc_count = 0;
746 offset.QuadPart = 0;
747 U(iosb).Status = 0xdeadbabe;
748 iosb.Information = 0xdeadbeef;
749 offset.QuadPart = 0;
750 ResetEvent(event);
751 status = pNtWriteFile(handle, event, apc, &apc_count, &iosb,
752 aligned_buffer, sizeof(aligned_buffer), &offset, NULL);
753 ok(status == STATUS_END_OF_FILE || status == STATUS_PENDING
754 || broken(status == STATUS_SUCCESS) /* before Vista */,
755 "Wrong status %lx.\n", status);
756 ok(U(iosb).Status == STATUS_SUCCESS, "Wrong status %lx.\n", U(iosb).Status);
757 ok(iosb.Information == sizeof(aligned_buffer), "Wrong info %Iu.\n", iosb.Information);
758 ok(is_signaled(event), "event is not signaled.\n");
759 ok(!apc_count, "apc was called.\n");
760 SleepEx(1, TRUE); /* alertable sleep */
761 ok(apc_count == 1, "apc was not called.\n");
763 apc_count = 0;
764 offset.QuadPart = 0;
765 U(iosb).Status = 0xdeadbabe;
766 iosb.Information = 0xdeadbeef;
767 offset.QuadPart = 0;
768 ResetEvent(event);
769 status = pNtReadFile(handle, event, apc, &apc_count, &iosb,
770 aligned_buffer, sizeof(aligned_buffer), &offset, NULL);
771 ok(status == STATUS_PENDING, "Wrong status %lx.\n", status);
772 WaitForSingleObject(event, 1000);
773 ok(U(iosb).Status == STATUS_SUCCESS, "Wrong status %lx.\n", U(iosb).Status);
774 ok(iosb.Information == sizeof(aligned_buffer), "Wrong info %Iu.\n", iosb.Information);
775 ok(is_signaled(event), "event is not signaled.\n");
776 ok(!apc_count, "apc was called.\n");
777 SleepEx(1, TRUE); /* alertable sleep */
778 ok(apc_count == 1, "apc was not called.\n");
780 CloseHandle(handle);
781 CloseHandle(event);
784 static void append_file_test(void)
786 static const char text[6] = "foobar";
787 HANDLE handle;
788 NTSTATUS status;
789 IO_STATUS_BLOCK iosb;
790 LARGE_INTEGER offset;
791 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
792 DWORD ret;
794 GetTempPathA( MAX_PATH, path );
795 GetTempFileNameA( path, "foo", 0, buffer );
797 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
798 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
800 U(iosb).Status = -1;
801 iosb.Information = -1;
802 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
803 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
804 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iosb).Status);
805 ok(iosb.Information == 2, "expected 2, got %Iu\n", iosb.Information);
807 CloseHandle(handle);
809 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
810 It matches the O_WRONLY|O_APPEND open() posix behavior */
811 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
812 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
814 U(iosb).Status = -1;
815 iosb.Information = -1;
816 offset.QuadPart = 1;
817 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
818 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
819 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iosb).Status);
820 ok(iosb.Information == 2, "expected 2, got %Iu\n", iosb.Information);
822 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
823 ok(ret == 4, "expected 4, got %lu\n", ret);
825 U(iosb).Status = -1;
826 iosb.Information = -1;
827 offset.QuadPart = 3;
828 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
829 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
830 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iosb).Status);
831 ok(iosb.Information == 2, "expected 2, got %Iu\n", iosb.Information);
833 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
834 ok(ret == 6, "expected 6, got %lu\n", ret);
836 CloseHandle(handle);
838 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
839 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
841 memset(buf, 0, sizeof(buf));
842 U(iosb).Status = -1;
843 iosb.Information = -1;
844 offset.QuadPart = 0;
845 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
846 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
847 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iosb).Status);
848 ok(iosb.Information == 6, "expected 6, got %Iu\n", iosb.Information);
849 buf[6] = 0;
850 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
852 U(iosb).Status = -1;
853 iosb.Information = -1;
854 offset.QuadPart = 0;
855 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
856 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
857 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iosb).Status);
858 ok(iosb.Information == 3, "expected 3, got %Iu\n", iosb.Information);
860 memset(buf, 0, sizeof(buf));
861 U(iosb).Status = -1;
862 iosb.Information = -1;
863 offset.QuadPart = 0;
864 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
865 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
866 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iosb).Status);
867 ok(iosb.Information == 6, "expected 6, got %Iu\n", iosb.Information);
868 buf[6] = 0;
869 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
871 CloseHandle(handle);
872 DeleteFileA(buffer);
875 static void nt_mailslot_test(void)
877 HANDLE hslot;
878 ACCESS_MASK DesiredAccess;
879 OBJECT_ATTRIBUTES attr;
881 ULONG CreateOptions;
882 ULONG MailslotQuota;
883 ULONG MaxMessageSize;
884 LARGE_INTEGER TimeOut;
885 IO_STATUS_BLOCK IoStatusBlock;
886 NTSTATUS rc;
887 UNICODE_STRING str;
888 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
889 'R',':','\\','F','R','E','D','\0' };
891 TimeOut.QuadPart = -1;
893 pRtlInitUnicodeString(&str, buffer1);
894 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
895 CreateOptions = MailslotQuota = MaxMessageSize = 0;
896 DesiredAccess = GENERIC_READ;
899 * Check for NULL pointer handling
901 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
902 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
903 &TimeOut);
904 ok( rc == STATUS_ACCESS_VIOLATION ||
905 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
906 "rc = %lx not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
909 * Test to see if the Timeout can be NULL
911 hslot = (HANDLE)0xdeadbeef;
912 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
913 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
914 NULL);
915 ok( rc == STATUS_SUCCESS ||
916 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
917 "rc = %lx not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
918 ok( hslot != 0, "Handle is invalid\n");
920 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
923 * Test a valid call
925 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
926 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
927 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
928 &TimeOut);
929 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %lx\n", rc);
930 ok( hslot != 0, "Handle is invalid\n");
932 rc = pNtClose(hslot);
933 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
936 static void WINAPI user_apc_proc(ULONG_PTR arg)
938 unsigned int *apc_count = (unsigned int *)arg;
939 ++*apc_count;
942 static void test_set_io_completion(void)
944 FILE_IO_COMPLETION_INFORMATION info[2] = {{0}};
945 LARGE_INTEGER timeout = {{0}};
946 unsigned int apc_count;
947 IO_STATUS_BLOCK iosb;
948 ULONG_PTR key, value;
949 NTSTATUS res;
950 ULONG count;
951 SIZE_T size = 3;
952 HANDLE h;
954 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
956 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
957 ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#lx\n", res );
958 ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h );
960 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
961 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletion failed: %#lx\n", res );
963 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
964 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %lx\n", res );
966 count = get_pending_msgs(h);
967 ok( count == 1, "Unexpected msg count: %ld\n", count );
969 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
970 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
971 ok( key == CKEY_FIRST, "Invalid completion key: %#Ix\n", key );
972 ok( iosb.Information == size, "Invalid iosb.Information: %Iu\n", iosb.Information );
973 ok( U(iosb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid iosb.Status: %#lx\n", U(iosb).Status );
974 ok( value == CVALUE_FIRST, "Invalid completion value: %#Ix\n", value );
976 count = get_pending_msgs(h);
977 ok( !count, "Unexpected msg count: %ld\n", count );
979 if (!pNtRemoveIoCompletionEx)
981 skip("NtRemoveIoCompletionEx() not present\n");
982 pNtClose( h );
983 return;
986 count = 0xdeadbeef;
987 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
988 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#lx\n", res );
989 ok( count == 1, "wrong count %lu\n", count );
991 res = pNtSetIoCompletion( h, 123, 456, 789, size );
992 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
994 count = 0xdeadbeef;
995 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
996 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
997 ok( count == 1, "wrong count %lu\n", count );
998 ok( info[0].CompletionKey == 123, "wrong key %#Ix\n", info[0].CompletionKey );
999 ok( info[0].CompletionValue == 456, "wrong value %#Ix\n", info[0].CompletionValue );
1000 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1001 info[0].IoStatusBlock.Information );
1002 ok( U(info[0].IoStatusBlock).Status == 789, "wrong status %#lx\n", U(info[0].IoStatusBlock).Status);
1004 res = pNtSetIoCompletion( h, 123, 456, 789, size );
1005 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1007 res = pNtSetIoCompletion( h, 12, 34, 56, size );
1008 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1010 count = 0xdeadbeef;
1011 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
1012 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1013 ok( count == 2, "wrong count %lu\n", count );
1014 ok( info[0].CompletionKey == 123, "wrong key %#Ix\n", info[0].CompletionKey );
1015 ok( info[0].CompletionValue == 456, "wrong value %#Ix\n", info[0].CompletionValue );
1016 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1017 info[0].IoStatusBlock.Information );
1018 ok( U(info[0].IoStatusBlock).Status == 789, "wrong status %#lx\n", U(info[0].IoStatusBlock).Status);
1019 ok( info[1].CompletionKey == 12, "wrong key %#Ix\n", info[1].CompletionKey );
1020 ok( info[1].CompletionValue == 34, "wrong value %#Ix\n", info[1].CompletionValue );
1021 ok( info[1].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1022 info[1].IoStatusBlock.Information );
1023 ok( U(info[1].IoStatusBlock).Status == 56, "wrong status %#lx\n", U(info[1].IoStatusBlock).Status);
1025 res = pNtSetIoCompletion( h, 123, 456, 789, size );
1026 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1028 res = pNtSetIoCompletion( h, 12, 34, 56, size );
1029 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1031 count = 0xdeadbeef;
1032 res = pNtRemoveIoCompletionEx( h, info, 1, &count, NULL, FALSE );
1033 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1034 ok( count == 1, "wrong count %lu\n", count );
1035 ok( info[0].CompletionKey == 123, "wrong key %#Ix\n", info[0].CompletionKey );
1036 ok( info[0].CompletionValue == 456, "wrong value %#Ix\n", info[0].CompletionValue );
1037 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1038 info[0].IoStatusBlock.Information );
1039 ok( U(info[0].IoStatusBlock).Status == 789, "wrong status %#lx\n", U(info[0].IoStatusBlock).Status);
1041 count = 0xdeadbeef;
1042 res = pNtRemoveIoCompletionEx( h, info, 1, &count, NULL, FALSE );
1043 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1044 ok( count == 1, "wrong count %lu\n", count );
1045 ok( info[0].CompletionKey == 12, "wrong key %#Ix\n", info[0].CompletionKey );
1046 ok( info[0].CompletionValue == 34, "wrong value %#Ix\n", info[0].CompletionValue );
1047 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1048 info[0].IoStatusBlock.Information );
1049 ok( U(info[0].IoStatusBlock).Status == 56, "wrong status %#lx\n", U(info[0].IoStatusBlock).Status);
1051 apc_count = 0;
1052 QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count );
1054 count = 0xdeadbeef;
1055 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
1056 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1057 ok( count == 1, "wrong count %lu\n", count );
1058 ok( !apc_count, "wrong apc count %d\n", apc_count );
1060 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE );
1061 ok( res == STATUS_USER_APC, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1062 ok( count == 1, "wrong count %lu\n", count );
1063 ok( apc_count == 1, "wrong apc count %u\n", apc_count );
1065 apc_count = 0;
1066 QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count );
1068 res = pNtSetIoCompletion( h, 123, 456, 789, size );
1069 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1071 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE );
1072 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1073 ok( count == 1, "wrong count %lu\n", count );
1074 ok( !apc_count, "wrong apc count %u\n", apc_count );
1076 SleepEx( 1, TRUE );
1078 pNtClose( h );
1081 static void test_file_io_completion(void)
1083 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1085 IO_STATUS_BLOCK iosb;
1086 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1087 FILE_COMPLETION_INFORMATION fci;
1088 LARGE_INTEGER timeout = {{0}};
1089 HANDLE server, client;
1090 ULONG_PTR key, value;
1091 OVERLAPPED o = {0};
1092 int apc_count = 0;
1093 NTSTATUS res;
1094 DWORD read;
1095 long count;
1096 HANDLE h;
1098 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
1099 ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#lx\n", res );
1100 ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h );
1101 fci.CompletionPort = h;
1102 fci.CompletionKey = CKEY_SECOND;
1104 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND,
1105 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1106 4, 1024, 1024, 1000, NULL );
1107 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1108 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1109 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1110 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1112 U(iosb).Status = 0xdeadbeef;
1113 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1114 ok( res == STATUS_INVALID_PARAMETER, "NtSetInformationFile failed: %#lx\n", res );
1115 todo_wine
1116 ok( U(iosb).Status == 0xdeadbeef, "wrong status %#lx\n", U(iosb).Status );
1117 CloseHandle( client );
1118 CloseHandle( server );
1120 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1121 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1122 4, 1024, 1024, 1000, NULL );
1123 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1124 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1125 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1126 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1128 U(iosb).Status = 0xdeadbeef;
1129 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1130 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %#lx\n", res );
1131 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %#lx\n", U(iosb).Status );
1133 memset( send_buf, 0, TEST_BUF_LEN );
1134 memset( recv_buf, 0xde, TEST_BUF_LEN );
1135 count = get_pending_msgs(h);
1136 ok( !count, "Unexpected msg count: %ld\n", count );
1137 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1138 count = get_pending_msgs(h);
1139 ok( !count, "Unexpected msg count: %ld\n", count );
1140 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1142 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1143 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1144 ok( key == CKEY_SECOND, "Invalid completion key: %#Ix\n", key );
1145 ok( iosb.Information == 3, "Invalid iosb.Information: %Id\n", iosb.Information );
1146 ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#lx\n", U(iosb).Status );
1147 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#Ix\n", value );
1148 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ),
1149 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1150 recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1151 count = get_pending_msgs(h);
1152 ok( !count, "Unexpected msg count: %ld\n", count );
1154 memset( send_buf, 0, TEST_BUF_LEN );
1155 memset( recv_buf, 0xde, TEST_BUF_LEN );
1156 WriteFile( client, send_buf, 2, &read, NULL );
1157 count = get_pending_msgs(h);
1158 ok( !count, "Unexpected msg count: %ld\n", count );
1159 ReadFile( server, recv_buf, 2, &read, &o);
1160 count = get_pending_msgs(h);
1161 ok( count == 1, "Unexpected msg count: %ld\n", count );
1163 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1164 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1165 ok( key == CKEY_SECOND, "Invalid completion key: %#Ix\n", key );
1166 ok( iosb.Information == 2, "Invalid iosb.Information: %Id\n", iosb.Information );
1167 ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#lx\n", U(iosb).Status );
1168 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#Ix\n", value );
1169 ok( !memcmp( send_buf, recv_buf, 2 ),
1170 "Receive buffer (%02x %02x) did not match send buffer (%02x %02x)\n",
1171 recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
1173 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1174 CloseHandle( server );
1175 count = get_pending_msgs(h);
1176 ok( count == 1, "Unexpected msg count: %ld\n", count );
1178 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1179 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1180 ok( key == CKEY_SECOND, "Invalid completion key: %Ix\n", key );
1181 ok( iosb.Information == 0, "Invalid iosb.Information: %Id\n", iosb.Information );
1182 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "Invalid iosb.Status: %lx\n", U(iosb).Status );
1183 ok( value == (ULONG_PTR)&o, "Invalid completion value: %Ix\n", value );
1185 CloseHandle( client );
1187 /* test associating a completion port with a handle after an async is queued */
1188 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1189 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1190 4, 1024, 1024, 1000, NULL );
1191 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1192 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1193 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1194 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1196 memset( send_buf, 0, TEST_BUF_LEN );
1197 memset( recv_buf, 0xde, TEST_BUF_LEN );
1198 count = get_pending_msgs(h);
1199 ok( !count, "Unexpected msg count: %ld\n", count );
1200 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1202 U(iosb).Status = 0xdeadbeef;
1203 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1204 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %lx\n", res );
1205 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %lx\n", U(iosb).Status );
1206 count = get_pending_msgs(h);
1207 ok( !count, "Unexpected msg count: %ld\n", count );
1209 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1211 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1212 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1213 ok( key == CKEY_SECOND, "Invalid completion key: %#Ix\n", key );
1214 ok( iosb.Information == 3, "Invalid iosb.Information: %Id\n", iosb.Information );
1215 ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#lx\n", U(iosb).Status );
1216 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#Ix\n", value );
1217 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ),
1218 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1219 recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1221 count = get_pending_msgs(h);
1222 ok( !count, "Unexpected msg count: %ld\n", count );
1224 /* using APCs on handle with associated completion port is not allowed */
1225 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1226 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %lx\n", res);
1228 CloseHandle( server );
1229 CloseHandle( client );
1231 /* test associating a completion port with a handle after an async using APC is queued */
1232 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1233 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1234 4, 1024, 1024, 1000, NULL );
1235 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1236 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1237 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1238 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1240 apc_count = 0;
1241 memset( send_buf, 0, TEST_BUF_LEN );
1242 memset( recv_buf, 0xde, TEST_BUF_LEN );
1243 count = get_pending_msgs(h);
1244 ok( !count, "Unexpected msg count: %ld\n", count );
1246 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1247 ok(res == STATUS_PENDING, "NtReadFile returned %lx\n", res);
1249 U(iosb).Status = 0xdeadbeef;
1250 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1251 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %lx\n", res );
1252 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %lx\n", U(iosb).Status );
1253 count = get_pending_msgs(h);
1254 ok( !count, "Unexpected msg count: %ld\n", count );
1256 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1258 ok(!apc_count, "apc_count = %u\n", apc_count);
1259 count = get_pending_msgs(h);
1260 ok( !count, "Unexpected msg count: %ld\n", count );
1262 SleepEx(1, TRUE); /* alertable sleep */
1263 ok(apc_count == 1, "apc was not called\n");
1264 count = get_pending_msgs(h);
1265 ok( !count, "Unexpected msg count: %ld\n", count );
1267 /* using APCs on handle with associated completion port is not allowed */
1268 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1269 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %lx\n", res);
1271 CloseHandle( server );
1272 CloseHandle( client );
1273 pNtClose( h );
1276 static void test_file_full_size_information(void)
1278 IO_STATUS_BLOCK io;
1279 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1280 FILE_FS_SIZE_INFORMATION fsi;
1281 HANDLE h;
1282 NTSTATUS res;
1284 if(!(h = create_temp_file(0))) return ;
1286 memset(&ffsi,0,sizeof(ffsi));
1287 memset(&fsi,0,sizeof(fsi));
1289 /* Assume No Quota Settings configured on Wine Testbot */
1290 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1291 ok(res == STATUS_SUCCESS, "cannot get attributes, res %lx\n", res);
1292 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1293 ok(res == STATUS_SUCCESS, "cannot get attributes, res %lx\n", res);
1295 /* Test for FileFsSizeInformation */
1296 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1297 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1298 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1299 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1300 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1301 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1303 /* Assume file system is NTFS */
1304 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %ld\n",fsi.BytesPerSector);
1305 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %ld\n",fsi.SectorsPerAllocationUnit);
1307 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1308 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1309 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1310 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1311 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1312 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1313 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1314 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1315 wine_dbgstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1316 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1317 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1318 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1319 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1320 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1321 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1322 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1323 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1325 /* Assume file system is NTFS */
1326 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %ld\n",ffsi.BytesPerSector);
1327 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %ld\n",ffsi.SectorsPerAllocationUnit);
1329 CloseHandle( h );
1332 static void test_file_basic_information(void)
1334 FILE_BASIC_INFORMATION fbi, fbi2;
1335 IO_STATUS_BLOCK io;
1336 HANDLE h;
1337 int res;
1338 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1340 if (!(h = create_temp_file(0))) return;
1342 /* Check default first */
1343 memset(&fbi, 0, sizeof(fbi));
1344 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1345 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1346 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1347 "attribute %lx not expected\n", fbi.FileAttributes );
1349 memset(&fbi2, 0, sizeof(fbi2));
1350 fbi2.LastWriteTime.QuadPart = -1;
1351 U(io).Status = 0xdeadbeef;
1352 res = pNtSetInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1353 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1354 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %lx\n", U(io).Status );
1356 memset(&fbi2, 0, sizeof(fbi2));
1357 fbi2.LastAccessTime.QuadPart = 0x200deadcafebeef;
1358 U(io).Status = 0xdeadbeef;
1359 res = pNtSetInformationFile(h, &io, &fbi2, sizeof(fbi2), FileBasicInformation);
1360 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1361 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %lx\n", U(io).Status );
1362 res = pNtQueryInformationFile(h, &io, &fbi, sizeof(fbi), FileBasicInformation);
1363 ok ( res == STATUS_SUCCESS, "can't get system attribute, NtQueryInformationFile returned %x\n", res );
1364 ok ( U(io).Status == STATUS_SUCCESS, "can't get system attribute, io.Status is %lx\n", U(io).Status );
1365 ok ( fbi2.LastAccessTime.QuadPart == fbi.LastAccessTime.QuadPart,
1366 "large access time set/get does not match.\n" );
1368 memset(&fbi2, 0, sizeof(fbi2));
1369 res = pNtQueryInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1370 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1371 ok ( fbi2.LastWriteTime.QuadPart == fbi.LastWriteTime.QuadPart, "unexpected write time.\n");
1373 memset(&fbi2, 0, sizeof(fbi2));
1374 U(io).Status = 0xdeadbeef;
1375 res = pNtSetInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1376 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1377 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %lx\n", U(io).Status );
1379 memset(&fbi2, 0, sizeof(fbi2));
1380 res = pNtQueryInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1381 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1382 ok ( fbi2.LastWriteTime.QuadPart == fbi.LastWriteTime.QuadPart, "unexpected write time.\n");
1384 /* Then SYSTEM */
1385 /* Clear fbi to avoid setting times */
1386 memset(&fbi, 0, sizeof(fbi));
1387 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1388 U(io).Status = 0xdeadbeef;
1389 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1390 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1391 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %lx\n", U(io).Status );
1393 memset(&fbi, 0, sizeof(fbi));
1394 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1395 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1396 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1398 /* Then HIDDEN */
1399 memset(&fbi, 0, sizeof(fbi));
1400 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1401 U(io).Status = 0xdeadbeef;
1402 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1403 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1404 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %lx\n", U(io).Status );
1406 memset(&fbi, 0, sizeof(fbi));
1407 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1408 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1409 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1411 /* Check NORMAL last of all (to make sure we can clear attributes) */
1412 memset(&fbi, 0, sizeof(fbi));
1413 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1414 U(io).Status = 0xdeadbeef;
1415 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1416 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1417 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %lx\n", U(io).Status );
1419 memset(&fbi, 0, sizeof(fbi));
1420 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1421 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1422 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %lx not 0\n", fbi.FileAttributes );
1424 CloseHandle( h );
1427 static void test_file_all_information(void)
1429 IO_STATUS_BLOCK io;
1430 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1431 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1432 * don't leave enough room there.
1434 struct {
1435 FILE_ALL_INFORMATION fai;
1436 WCHAR buf[256];
1437 } fai_buf;
1438 HANDLE h;
1439 int res;
1440 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1442 if (!(h = create_temp_file(0))) return;
1444 /* Check default first */
1445 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1446 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1447 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1448 "attribute %lx not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1450 /* Then SYSTEM */
1451 /* Clear fbi to avoid setting times */
1452 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1453 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1454 U(io).Status = 0xdeadbeef;
1455 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1456 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1457 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %lx\n", U(io).Status);
1458 U(io).Status = 0xdeadbeef;
1459 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1460 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1461 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %lx\n", U(io).Status );
1463 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1464 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1465 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1466 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fai_buf.fai.BasicInformation.FileAttributes );
1468 /* Then HIDDEN */
1469 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1470 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1471 U(io).Status = 0xdeadbeef;
1472 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1473 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1474 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %lx\n", U(io).Status );
1476 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1477 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1478 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1479 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\n", fai_buf.fai.BasicInformation.FileAttributes );
1481 /* Check NORMAL last of all (to make sure we can clear attributes) */
1482 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1483 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1484 U(io).Status = 0xdeadbeef;
1485 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1486 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1487 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %lx\n", U(io).Status );
1489 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1490 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1491 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1492 todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %lx not FILE_ATTRIBUTE_NORMAL\n", fai_buf.fai.BasicInformation.FileAttributes );
1494 CloseHandle( h );
1497 static void delete_object( WCHAR *path )
1499 BOOL ret = DeleteFileW( path );
1500 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1501 "DeleteFileW failed with %lu\n", GetLastError() );
1502 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1504 ret = RemoveDirectoryW( path );
1505 ok( ret, "RemoveDirectoryW failed with %lu\n", GetLastError() );
1509 static void test_file_rename_information(void)
1511 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1512 static const WCHAR fooW[] = {'f','o','o',0};
1513 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1514 FILE_RENAME_INFORMATION *fri;
1515 FILE_NAME_INFORMATION *fni;
1516 BOOL success, fileDeleted;
1517 UNICODE_STRING name_str;
1518 HANDLE handle, handle2;
1519 IO_STATUS_BLOCK io;
1520 NTSTATUS res;
1522 GetTempPathW( MAX_PATH, tmp_path );
1524 /* oldpath is a file, newpath doesn't exist */
1525 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1526 ok( res != 0, "failed to create temp file\n" );
1527 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1528 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1530 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1531 ok( res != 0, "failed to create temp file\n" );
1532 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1533 DeleteFileW( newpath );
1534 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1535 fri->ReplaceIfExists = FALSE;
1536 fri->RootDirectory = NULL;
1537 fri->FileNameLength = name_str.Length;
1538 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1539 pRtlFreeUnicodeString( &name_str );
1541 U(io).Status = 0xdeadbeef;
1542 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1543 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
1544 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1545 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1546 ok( fileDeleted, "file should not exist\n" );
1547 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1548 ok( !fileDeleted, "file should exist\n" );
1550 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1551 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1552 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1553 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1554 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1555 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1556 HeapFree( GetProcessHeap(), 0, fni );
1558 CloseHandle( handle );
1559 HeapFree( GetProcessHeap(), 0, fri );
1560 delete_object( oldpath );
1561 delete_object( newpath );
1563 /* oldpath is a file, newpath is a file, Replace = FALSE */
1564 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1565 ok( res != 0, "failed to create temp file\n" );
1566 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1567 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1569 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1570 ok( res != 0, "failed to create temp file\n" );
1571 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1572 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1573 fri->ReplaceIfExists = FALSE;
1574 fri->RootDirectory = NULL;
1575 fri->FileNameLength = name_str.Length;
1576 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1577 pRtlFreeUnicodeString( &name_str );
1579 U(io).Status = 0xdeadbeef;
1580 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1581 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1582 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1583 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1584 ok( !fileDeleted, "file should exist\n" );
1585 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1586 ok( !fileDeleted, "file should exist\n" );
1588 CloseHandle( handle );
1589 HeapFree( GetProcessHeap(), 0, fri );
1590 delete_object( oldpath );
1591 delete_object( newpath );
1593 /* oldpath is a file, newpath is a file, Replace = TRUE */
1594 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1595 ok( res != 0, "failed to create temp file\n" );
1596 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1597 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1599 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1600 ok( res != 0, "failed to create temp file\n" );
1601 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1602 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1603 fri->ReplaceIfExists = TRUE;
1604 fri->RootDirectory = NULL;
1605 fri->FileNameLength = name_str.Length;
1606 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1607 pRtlFreeUnicodeString( &name_str );
1609 U(io).Status = 0xdeadbeef;
1610 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1611 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
1612 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1613 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1614 ok( fileDeleted, "file should not exist\n" );
1615 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1616 ok( !fileDeleted, "file should exist\n" );
1618 CloseHandle( handle );
1619 HeapFree( GetProcessHeap(), 0, fri );
1620 delete_object( oldpath );
1621 delete_object( newpath );
1623 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1624 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1625 ok( res != 0, "failed to create temp file\n" );
1626 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1627 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1629 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1630 ok( res != 0, "failed to create temp file\n" );
1631 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1632 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1634 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1635 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1636 fri->ReplaceIfExists = FALSE;
1637 fri->RootDirectory = NULL;
1638 fri->FileNameLength = name_str.Length;
1639 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1640 pRtlFreeUnicodeString( &name_str );
1642 U(io).Status = 0xdeadbeef;
1643 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1644 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1645 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1646 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1647 ok( !fileDeleted, "file should exist\n" );
1648 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1649 ok( !fileDeleted, "file should exist\n" );
1651 CloseHandle( handle );
1652 CloseHandle( handle2 );
1653 HeapFree( GetProcessHeap(), 0, fri );
1654 delete_object( oldpath );
1655 delete_object( newpath );
1657 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1658 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1659 ok( res != 0, "failed to create temp file\n" );
1660 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1661 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
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" );
1668 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1669 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1670 fri->ReplaceIfExists = TRUE;
1671 fri->RootDirectory = NULL;
1672 fri->FileNameLength = name_str.Length;
1673 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1674 pRtlFreeUnicodeString( &name_str );
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 %lx\n", U(io).Status );
1679 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\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" );
1685 CloseHandle( handle );
1686 CloseHandle( handle2 );
1687 HeapFree( GetProcessHeap(), 0, fri );
1688 delete_object( oldpath );
1689 delete_object( newpath );
1691 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
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" );
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 DeleteFileW( newpath );
1704 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1705 fri->ReplaceIfExists = FALSE;
1706 fri->RootDirectory = NULL;
1707 fri->FileNameLength = name_str.Length;
1708 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1709 pRtlFreeUnicodeString( &name_str );
1711 U(io).Status = 0xdeadbeef;
1712 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1713 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
1714 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1715 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1716 ok( fileDeleted, "file should not exist\n" );
1717 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1718 ok( !fileDeleted, "file should exist\n" );
1720 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1721 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1722 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1723 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1724 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1725 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1726 HeapFree( GetProcessHeap(), 0, fni );
1728 CloseHandle( handle );
1729 HeapFree( GetProcessHeap(), 0, fri );
1730 delete_object( oldpath );
1731 delete_object( newpath );
1733 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1734 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1735 ok( res != 0, "failed to create temp file\n" );
1736 DeleteFileW( oldpath );
1737 success = CreateDirectoryW( oldpath, NULL );
1738 ok( success != 0, "failed to create temp directory\n" );
1739 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1740 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1742 lstrcpyW( newpath, oldpath );
1743 lstrcatW( newpath, foo_txtW );
1744 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1745 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1747 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1748 ok( res != 0, "failed to create temp file\n" );
1749 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1750 DeleteFileW( newpath );
1751 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1752 fri->ReplaceIfExists = FALSE;
1753 fri->RootDirectory = NULL;
1754 fri->FileNameLength = name_str.Length;
1755 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1756 pRtlFreeUnicodeString( &name_str );
1758 U(io).Status = 0xdeadbeef;
1759 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1760 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1761 todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
1762 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1763 todo_wine ok( !fileDeleted, "file should exist\n" );
1764 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1765 todo_wine ok( fileDeleted, "file should not exist\n" );
1767 CloseHandle( handle );
1768 CloseHandle( handle2 );
1769 HeapFree( GetProcessHeap(), 0, fri );
1770 delete_object( oldpath );
1771 if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1773 lstrcpyW( oldpath, newpath );
1774 lstrcatW( oldpath, foo_txtW );
1775 delete_object( oldpath );
1777 delete_object( newpath );
1779 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1780 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1781 ok( res != 0, "failed to create temp file\n" );
1782 DeleteFileW( oldpath );
1783 success = CreateDirectoryW( oldpath, NULL );
1784 ok( success != 0, "failed to create temp directory\n" );
1785 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1786 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1788 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1789 ok( res != 0, "failed to create temp file\n" );
1790 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1791 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1792 fri->ReplaceIfExists = FALSE;
1793 fri->RootDirectory = NULL;
1794 fri->FileNameLength = name_str.Length;
1795 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1796 pRtlFreeUnicodeString( &name_str );
1798 U(io).Status = 0xdeadbeef;
1799 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1800 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1801 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1802 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1803 ok( !fileDeleted, "file should exist\n" );
1804 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1805 ok( !fileDeleted, "file should exist\n" );
1807 CloseHandle( handle );
1808 HeapFree( GetProcessHeap(), 0, fri );
1809 delete_object( oldpath );
1810 delete_object( newpath );
1812 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1813 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1814 ok( res != 0, "failed to create temp file\n" );
1815 DeleteFileW( oldpath );
1816 success = CreateDirectoryW( oldpath, NULL );
1817 ok( success != 0, "failed to create temp directory\n" );
1818 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1819 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1821 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1822 ok( res != 0, "failed to create temp file\n" );
1823 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1824 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1826 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1827 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1828 fri->ReplaceIfExists = FALSE;
1829 fri->RootDirectory = NULL;
1830 fri->FileNameLength = name_str.Length;
1831 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1832 pRtlFreeUnicodeString( &name_str );
1834 U(io).Status = 0xdeadbeef;
1835 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1836 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1837 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1838 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1839 ok( !fileDeleted, "file should exist\n" );
1840 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1841 ok( !fileDeleted, "file should exist\n" );
1843 CloseHandle( handle );
1844 CloseHandle( handle2 );
1845 HeapFree( GetProcessHeap(), 0, fri );
1846 delete_object( oldpath );
1847 delete_object( newpath );
1849 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1850 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1851 ok( res != 0, "failed to create temp file\n" );
1852 DeleteFileW( oldpath );
1853 success = CreateDirectoryW( oldpath, NULL );
1854 ok( success != 0, "failed to create temp directory\n" );
1855 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1856 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1858 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1859 ok( res != 0, "failed to create temp file\n" );
1860 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1861 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1862 fri->ReplaceIfExists = TRUE;
1863 fri->RootDirectory = NULL;
1864 fri->FileNameLength = name_str.Length;
1865 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1866 pRtlFreeUnicodeString( &name_str );
1868 U(io).Status = 0xdeadbeef;
1869 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1870 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
1871 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1872 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1873 ok( fileDeleted, "file should not exist\n" );
1874 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1875 ok( !fileDeleted, "file should exist\n" );
1877 CloseHandle( handle );
1878 HeapFree( GetProcessHeap(), 0, fri );
1879 delete_object( oldpath );
1880 delete_object( newpath );
1882 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1883 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1884 ok( res != 0, "failed to create temp file\n" );
1885 DeleteFileW( oldpath );
1886 success = CreateDirectoryW( oldpath, NULL );
1887 ok( success != 0, "failed to create temp directory\n" );
1888 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1889 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1891 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1892 ok( res != 0, "failed to create temp file\n" );
1893 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1894 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1896 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1897 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1898 fri->ReplaceIfExists = TRUE;
1899 fri->RootDirectory = NULL;
1900 fri->FileNameLength = name_str.Length;
1901 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1902 pRtlFreeUnicodeString( &name_str );
1904 U(io).Status = 0xdeadbeef;
1905 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1906 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1907 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
1908 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1909 ok( !fileDeleted, "file should exist\n" );
1910 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1911 ok( !fileDeleted, "file should exist\n" );
1913 CloseHandle( handle );
1914 CloseHandle( handle2 );
1915 HeapFree( GetProcessHeap(), 0, fri );
1916 delete_object( oldpath );
1917 delete_object( newpath );
1919 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1920 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1921 ok( res != 0, "failed to create temp file\n" );
1922 DeleteFileW( oldpath );
1923 success = CreateDirectoryW( oldpath, NULL );
1924 ok( success != 0, "failed to create temp directory\n" );
1925 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1926 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1928 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1929 ok( res != 0, "failed to create temp file\n" );
1930 DeleteFileW( newpath );
1931 success = CreateDirectoryW( newpath, NULL );
1932 ok( success != 0, "failed to create temp directory\n" );
1933 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1934 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1935 fri->ReplaceIfExists = FALSE;
1936 fri->RootDirectory = NULL;
1937 fri->FileNameLength = name_str.Length;
1938 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1939 pRtlFreeUnicodeString( &name_str );
1941 U(io).Status = 0xdeadbeef;
1942 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1943 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1944 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1945 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1946 ok( !fileDeleted, "file should exist\n" );
1947 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1948 ok( !fileDeleted, "file should exist\n" );
1950 CloseHandle( handle );
1951 HeapFree( GetProcessHeap(), 0, fri );
1952 delete_object( oldpath );
1953 delete_object( newpath );
1955 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1956 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1957 ok( res != 0, "failed to create temp file\n" );
1958 DeleteFileW( oldpath );
1959 success = CreateDirectoryW( oldpath, NULL );
1960 ok( success != 0, "failed to create temp directory\n" );
1961 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1962 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1964 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1965 ok( res != 0, "failed to create temp file\n" );
1966 DeleteFileW( newpath );
1967 success = CreateDirectoryW( newpath, NULL );
1968 ok( success != 0, "failed to create temp directory\n" );
1969 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1970 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1971 fri->ReplaceIfExists = TRUE;
1972 fri->RootDirectory = NULL;
1973 fri->FileNameLength = name_str.Length;
1974 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1975 pRtlFreeUnicodeString( &name_str );
1977 U(io).Status = 0xdeadbeef;
1978 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1979 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
1980 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
1981 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1982 ok( !fileDeleted, "file should exist\n" );
1983 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1984 ok( !fileDeleted, "file should exist\n" );
1986 CloseHandle( handle );
1987 HeapFree( GetProcessHeap(), 0, fri );
1988 delete_object( oldpath );
1989 delete_object( newpath );
1991 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
1992 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1993 ok( res != 0, "failed to create temp file\n" );
1994 DeleteFileW( oldpath );
1995 success = CreateDirectoryW( oldpath, NULL );
1996 ok( success != 0, "failed to create temp directory\n" );
1997 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1998 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2000 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2001 ok( res != 0, "failed to create temp file\n" );
2002 DeleteFileW( newpath );
2003 success = CreateDirectoryW( newpath, NULL );
2004 ok( success != 0, "failed to create temp directory\n" );
2005 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2006 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2008 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2009 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2010 fri->ReplaceIfExists = TRUE;
2011 fri->RootDirectory = NULL;
2012 fri->FileNameLength = name_str.Length;
2013 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2014 pRtlFreeUnicodeString( &name_str );
2016 U(io).Status = 0xdeadbeef;
2017 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2018 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2019 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\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" );
2025 CloseHandle( handle );
2026 CloseHandle( handle2 );
2027 HeapFree( GetProcessHeap(), 0, fri );
2028 delete_object( oldpath );
2029 delete_object( newpath );
2031 /* oldpath is a file, newpath is a directory, Replace = FALSE */
2032 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2033 ok( res != 0, "failed to create temp file\n" );
2034 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2035 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2037 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2038 ok( res != 0, "failed to create temp file\n" );
2039 DeleteFileW( newpath );
2040 success = CreateDirectoryW( newpath, NULL );
2041 ok( success != 0, "failed to create temp directory\n" );
2042 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2043 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2044 fri->ReplaceIfExists = FALSE;
2045 fri->RootDirectory = NULL;
2046 fri->FileNameLength = name_str.Length;
2047 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2048 pRtlFreeUnicodeString( &name_str );
2050 U(io).Status = 0xdeadbeef;
2051 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2052 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2053 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
2054 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2055 ok( !fileDeleted, "file should exist\n" );
2056 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2057 ok( !fileDeleted, "file should exist\n" );
2059 CloseHandle( handle );
2060 HeapFree( GetProcessHeap(), 0, fri );
2061 delete_object( oldpath );
2062 delete_object( newpath );
2064 /* oldpath is a file, newpath is a directory, Replace = TRUE */
2065 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2066 ok( res != 0, "failed to create temp file\n" );
2067 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2068 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2070 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2071 ok( res != 0, "failed to create temp file\n" );
2072 DeleteFileW( newpath );
2073 success = CreateDirectoryW( newpath, NULL );
2074 ok( success != 0, "failed to create temp directory\n" );
2075 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2076 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2077 fri->ReplaceIfExists = TRUE;
2078 fri->RootDirectory = NULL;
2079 fri->FileNameLength = name_str.Length;
2080 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2081 pRtlFreeUnicodeString( &name_str );
2083 U(io).Status = 0xdeadbeef;
2084 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2085 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2086 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2087 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2088 ok( !fileDeleted, "file should exist\n" );
2089 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2090 ok( !fileDeleted, "file should exist\n" );
2092 CloseHandle( handle );
2093 HeapFree( GetProcessHeap(), 0, fri );
2094 delete_object( oldpath );
2095 delete_object( newpath );
2097 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
2098 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2099 ok( res != 0, "failed to create temp file\n" );
2100 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2101 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2103 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2104 ok( res != 0, "failed to create temp file\n" );
2105 DeleteFileW( newpath );
2106 for (filename = newpath, p = newpath; *p; p++)
2107 if (*p == '\\') filename = p + 1;
2108 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2109 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2111 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2112 fri->ReplaceIfExists = FALSE;
2113 fri->RootDirectory = handle2;
2114 fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2115 memcpy( fri->FileName, filename, fri->FileNameLength );
2117 U(io).Status = 0xdeadbeef;
2118 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2119 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
2120 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2121 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2122 ok( fileDeleted, "file should not exist\n" );
2123 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2124 ok( !fileDeleted, "file should exist\n" );
2126 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2127 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2128 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2129 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2130 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
2131 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
2132 HeapFree( GetProcessHeap(), 0, fni );
2134 CloseHandle( handle );
2135 CloseHandle( handle2 );
2136 HeapFree( GetProcessHeap(), 0, fri );
2137 delete_object( oldpath );
2138 delete_object( newpath );
2140 /* oldpath == newpath */
2141 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2142 ok( res != 0, "failed to create temp file\n" );
2143 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2144 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2146 pRtlDosPathNameToNtPathName_U( oldpath, &name_str, NULL, NULL );
2147 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2148 fri->ReplaceIfExists = FALSE;
2149 fri->RootDirectory = NULL;
2150 fri->FileNameLength = name_str.Length;
2151 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2152 pRtlFreeUnicodeString( &name_str );
2154 U(io).Status = 0xdeadbeef;
2155 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2156 ok( U(io).Status == STATUS_SUCCESS, "got io status %#lx\n", U(io).Status );
2157 ok( res == STATUS_SUCCESS, "got status %lx\n", res );
2158 ok( GetFileAttributesW( oldpath ) != INVALID_FILE_ATTRIBUTES, "file should exist\n" );
2160 CloseHandle( handle );
2161 HeapFree( GetProcessHeap(), 0, fri );
2162 delete_object( oldpath );
2165 static void test_file_link_information(void)
2167 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
2168 static const WCHAR fooW[] = {'f','o','o',0};
2169 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
2170 FILE_LINK_INFORMATION *fli;
2171 FILE_NAME_INFORMATION *fni;
2172 WIN32_FIND_DATAW find_data;
2173 BOOL success, fileDeleted;
2174 UNICODE_STRING name_str;
2175 HANDLE handle, handle2;
2176 IO_STATUS_BLOCK io;
2177 NTSTATUS res;
2179 GetTempPathW( MAX_PATH, tmp_path );
2181 /* oldpath is a file, newpath doesn't exist */
2182 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2183 ok( res != 0, "failed to create temp file\n" );
2184 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2185 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2187 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2188 ok( res != 0, "failed to create temp file\n" );
2189 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2190 DeleteFileW( newpath );
2191 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2192 fli->ReplaceIfExists = FALSE;
2193 fli->RootDirectory = NULL;
2194 fli->FileNameLength = name_str.Length;
2195 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2196 pRtlFreeUnicodeString( &name_str );
2198 U(io).Status = 0xdeadbeef;
2199 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2200 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
2201 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2202 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2203 ok( !fileDeleted, "file should exist\n" );
2204 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2205 ok( !fileDeleted, "file should exist\n" );
2207 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2208 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2209 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2210 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2211 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2212 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2213 HeapFree( GetProcessHeap(), 0, fni );
2215 CloseHandle( handle );
2216 HeapFree( GetProcessHeap(), 0, fli );
2217 delete_object( oldpath );
2218 delete_object( newpath );
2220 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2221 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2222 ok( res != 0, "failed to create temp file\n" );
2223 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2224 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2226 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2227 ok( res != 0, "failed to create temp file\n" );
2228 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2229 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2230 fli->ReplaceIfExists = FALSE;
2231 fli->RootDirectory = NULL;
2232 fli->FileNameLength = name_str.Length;
2233 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2234 pRtlFreeUnicodeString( &name_str );
2236 U(io).Status = 0xdeadbeef;
2237 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2238 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2239 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
2240 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2241 ok( !fileDeleted, "file should exist\n" );
2242 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2243 ok( !fileDeleted, "file should exist\n" );
2245 CloseHandle( handle );
2246 HeapFree( GetProcessHeap(), 0, fli );
2247 delete_object( oldpath );
2248 delete_object( newpath );
2250 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2251 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2252 ok( res != 0, "failed to create temp file\n" );
2253 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2254 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2256 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2257 ok( res != 0, "failed to create temp file\n" );
2258 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2259 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2260 fli->ReplaceIfExists = TRUE;
2261 fli->RootDirectory = NULL;
2262 fli->FileNameLength = name_str.Length;
2263 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2264 pRtlFreeUnicodeString( &name_str );
2266 U(io).Status = 0xdeadbeef;
2267 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2268 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
2269 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2270 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2271 ok( !fileDeleted, "file should exist\n" );
2272 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2273 ok( !fileDeleted, "file should exist\n" );
2275 CloseHandle( handle );
2276 HeapFree( GetProcessHeap(), 0, fli );
2277 delete_object( oldpath );
2278 delete_object( newpath );
2280 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, different casing on link */
2281 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2282 ok( res != 0, "failed to create temp file\n" );
2283 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2284 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2286 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2287 ok( res != 0, "failed to create temp file\n" );
2288 wcsrchr( newpath, '\\' )[1] = 'F';
2289 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2290 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2291 fli->ReplaceIfExists = TRUE;
2292 fli->RootDirectory = NULL;
2293 fli->FileNameLength = name_str.Length;
2294 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2295 pRtlFreeUnicodeString( &name_str );
2297 U(io).Status = 0xdeadbeef;
2298 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2299 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
2300 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2301 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2302 ok( !fileDeleted, "file should exist\n" );
2303 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2304 ok( !fileDeleted, "file should exist\n" );
2306 CloseHandle( handle );
2307 handle = FindFirstFileW( newpath, &find_data );
2308 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileW: failed, error %ld\n", GetLastError());
2309 if (handle != INVALID_HANDLE_VALUE)
2311 todo_wine ok(!lstrcmpW(wcsrchr(newpath, '\\') + 1, find_data.cFileName),
2312 "Link did not change casing on existing target file: got %s\n", wine_dbgstr_w(find_data.cFileName));
2315 FindClose( handle );
2316 HeapFree( GetProcessHeap(), 0, fli );
2317 delete_object( oldpath );
2318 delete_object( newpath );
2320 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2321 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2322 ok( res != 0, "failed to create temp file\n" );
2323 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2324 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2326 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2327 ok( res != 0, "failed to create temp file\n" );
2328 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2329 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2331 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2332 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2333 fli->ReplaceIfExists = FALSE;
2334 fli->RootDirectory = NULL;
2335 fli->FileNameLength = name_str.Length;
2336 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2337 pRtlFreeUnicodeString( &name_str );
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 %lx\n", U(io).Status );
2342 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\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" );
2348 CloseHandle( handle );
2349 CloseHandle( handle2 );
2350 HeapFree( GetProcessHeap(), 0, fli );
2351 delete_object( oldpath );
2352 delete_object( newpath );
2354 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2355 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2356 ok( res != 0, "failed to create temp file\n" );
2357 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2358 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2360 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2361 ok( res != 0, "failed to create temp file\n" );
2362 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2363 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2365 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2366 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2367 fli->ReplaceIfExists = TRUE;
2368 fli->RootDirectory = NULL;
2369 fli->FileNameLength = name_str.Length;
2370 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2371 pRtlFreeUnicodeString( &name_str );
2373 U(io).Status = 0xdeadbeef;
2374 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2375 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2376 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2377 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2378 ok( !fileDeleted, "file should exist\n" );
2379 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2380 ok( !fileDeleted, "file should exist\n" );
2382 CloseHandle( handle );
2383 CloseHandle( handle2 );
2384 HeapFree( GetProcessHeap(), 0, fli );
2385 delete_object( oldpath );
2386 delete_object( newpath );
2388 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2389 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2390 ok( res != 0, "failed to create temp file\n" );
2391 DeleteFileW( oldpath );
2392 success = CreateDirectoryW( oldpath, NULL );
2393 ok( success != 0, "failed to create temp directory\n" );
2394 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2395 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2397 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2398 ok( res != 0, "failed to create temp file\n" );
2399 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2400 DeleteFileW( newpath );
2401 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2402 fli->ReplaceIfExists = FALSE;
2403 fli->RootDirectory = NULL;
2404 fli->FileNameLength = name_str.Length;
2405 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2406 pRtlFreeUnicodeString( &name_str );
2408 U(io).Status = 0xdeadbeef;
2409 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2410 todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2411 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2412 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2413 ok( !fileDeleted, "file should exist\n" );
2414 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2415 ok( fileDeleted, "file should not exist\n" );
2417 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2418 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2419 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2420 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2421 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2422 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2423 HeapFree( GetProcessHeap(), 0, fni );
2425 CloseHandle( handle );
2426 HeapFree( GetProcessHeap(), 0, fli );
2427 delete_object( oldpath );
2428 delete_object( newpath );
2430 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2431 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2432 ok( res != 0, "failed to create temp file\n" );
2433 DeleteFileW( oldpath );
2434 success = CreateDirectoryW( oldpath, NULL );
2435 ok( success != 0, "failed to create temp directory\n" );
2436 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2437 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2439 lstrcpyW( newpath, oldpath );
2440 lstrcatW( newpath, foo_txtW );
2441 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2442 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2444 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2445 ok( res != 0, "failed to create temp file\n" );
2446 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2447 DeleteFileW( newpath );
2448 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2449 fli->ReplaceIfExists = FALSE;
2450 fli->RootDirectory = NULL;
2451 fli->FileNameLength = name_str.Length;
2452 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2453 pRtlFreeUnicodeString( &name_str );
2455 U(io).Status = 0xdeadbeef;
2456 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2457 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2458 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2459 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2460 ok( !fileDeleted, "file should exist\n" );
2461 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2462 ok( fileDeleted, "file should not exist\n" );
2464 CloseHandle( handle );
2465 CloseHandle( handle2 );
2466 HeapFree( GetProcessHeap(), 0, fli );
2467 delete_object( oldpath );
2468 delete_object( newpath );
2470 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2471 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2472 ok( res != 0, "failed to create temp file\n" );
2473 DeleteFileW( oldpath );
2474 success = CreateDirectoryW( oldpath, NULL );
2475 ok( success != 0, "failed to create temp directory\n" );
2476 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2477 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2479 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2480 ok( res != 0, "failed to create temp file\n" );
2481 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2482 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2483 fli->ReplaceIfExists = FALSE;
2484 fli->RootDirectory = NULL;
2485 fli->FileNameLength = name_str.Length;
2486 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2487 pRtlFreeUnicodeString( &name_str );
2489 U(io).Status = 0xdeadbeef;
2490 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2491 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2492 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2493 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2494 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2495 ok( !fileDeleted, "file should exist\n" );
2496 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2497 ok( !fileDeleted, "file should exist\n" );
2499 CloseHandle( handle );
2500 HeapFree( GetProcessHeap(), 0, fli );
2501 delete_object( oldpath );
2502 delete_object( newpath );
2504 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2505 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2506 ok( res != 0, "failed to create temp file\n" );
2507 DeleteFileW( oldpath );
2508 success = CreateDirectoryW( oldpath, NULL );
2509 ok( success != 0, "failed to create temp directory\n" );
2510 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2511 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2513 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2514 ok( res != 0, "failed to create temp file\n" );
2515 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2516 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2518 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2519 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2520 fli->ReplaceIfExists = FALSE;
2521 fli->RootDirectory = NULL;
2522 fli->FileNameLength = name_str.Length;
2523 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2524 pRtlFreeUnicodeString( &name_str );
2526 U(io).Status = 0xdeadbeef;
2527 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2528 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2529 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2530 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2531 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2532 ok( !fileDeleted, "file should exist\n" );
2533 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2534 ok( !fileDeleted, "file should exist\n" );
2536 CloseHandle( handle );
2537 CloseHandle( handle2 );
2538 HeapFree( GetProcessHeap(), 0, fli );
2539 delete_object( oldpath );
2540 delete_object( newpath );
2542 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2543 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2544 ok( res != 0, "failed to create temp file\n" );
2545 DeleteFileW( oldpath );
2546 success = CreateDirectoryW( oldpath, NULL );
2547 ok( success != 0, "failed to create temp directory\n" );
2548 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2549 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2551 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2552 ok( res != 0, "failed to create temp file\n" );
2553 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2554 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2555 fli->ReplaceIfExists = TRUE;
2556 fli->RootDirectory = NULL;
2557 fli->FileNameLength = name_str.Length;
2558 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2559 pRtlFreeUnicodeString( &name_str );
2561 U(io).Status = 0xdeadbeef;
2562 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2563 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2564 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2565 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2566 ok( !fileDeleted, "file should exist\n" );
2567 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2568 ok( !fileDeleted, "file should exist\n" );
2570 CloseHandle( handle );
2571 HeapFree( GetProcessHeap(), 0, fli );
2572 delete_object( oldpath );
2573 delete_object( newpath );
2575 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2576 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2577 ok( res != 0, "failed to create temp file\n" );
2578 DeleteFileW( oldpath );
2579 success = CreateDirectoryW( oldpath, NULL );
2580 ok( success != 0, "failed to create temp directory\n" );
2581 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2582 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2584 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2585 ok( res != 0, "failed to create temp file\n" );
2586 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2587 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2589 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2590 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2591 fli->ReplaceIfExists = TRUE;
2592 fli->RootDirectory = NULL;
2593 fli->FileNameLength = name_str.Length;
2594 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2595 pRtlFreeUnicodeString( &name_str );
2597 U(io).Status = 0xdeadbeef;
2598 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2599 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2600 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2601 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2602 ok( !fileDeleted, "file should exist\n" );
2603 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2604 ok( !fileDeleted, "file should exist\n" );
2606 CloseHandle( handle );
2607 CloseHandle( handle2 );
2608 HeapFree( GetProcessHeap(), 0, fli );
2609 delete_object( oldpath );
2610 delete_object( newpath );
2612 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2613 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2614 ok( res != 0, "failed to create temp file\n" );
2615 DeleteFileW( oldpath );
2616 success = CreateDirectoryW( oldpath, NULL );
2617 ok( success != 0, "failed to create temp directory\n" );
2618 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2619 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2621 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2622 ok( res != 0, "failed to create temp file\n" );
2623 DeleteFileW( newpath );
2624 success = CreateDirectoryW( newpath, NULL );
2625 ok( success != 0, "failed to create temp directory\n" );
2626 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2627 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2628 fli->ReplaceIfExists = FALSE;
2629 fli->RootDirectory = NULL;
2630 fli->FileNameLength = name_str.Length;
2631 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2632 pRtlFreeUnicodeString( &name_str );
2634 U(io).Status = 0xdeadbeef;
2635 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2636 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2637 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2638 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2639 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2640 ok( !fileDeleted, "file should exist\n" );
2641 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2642 ok( !fileDeleted, "file should exist\n" );
2644 CloseHandle( handle );
2645 HeapFree( GetProcessHeap(), 0, fli );
2646 delete_object( oldpath );
2647 delete_object( newpath );
2649 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2650 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2651 ok( res != 0, "failed to create temp file\n" );
2652 DeleteFileW( oldpath );
2653 success = CreateDirectoryW( oldpath, NULL );
2654 ok( success != 0, "failed to create temp directory\n" );
2655 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2656 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2658 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2659 ok( res != 0, "failed to create temp file\n" );
2660 DeleteFileW( newpath );
2661 success = CreateDirectoryW( newpath, NULL );
2662 ok( success != 0, "failed to create temp directory\n" );
2663 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2664 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2665 fli->ReplaceIfExists = TRUE;
2666 fli->RootDirectory = NULL;
2667 fli->FileNameLength = name_str.Length;
2668 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2669 pRtlFreeUnicodeString( &name_str );
2671 U(io).Status = 0xdeadbeef;
2672 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2673 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2674 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2675 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2676 ok( !fileDeleted, "file should exist\n" );
2677 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2678 ok( !fileDeleted, "file should exist\n" );
2680 CloseHandle( handle );
2681 HeapFree( GetProcessHeap(), 0, fli );
2682 delete_object( oldpath );
2683 delete_object( newpath );
2685 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2686 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2687 ok( res != 0, "failed to create temp file\n" );
2688 DeleteFileW( oldpath );
2689 success = CreateDirectoryW( oldpath, NULL );
2690 ok( success != 0, "failed to create temp directory\n" );
2691 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2692 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2694 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2695 ok( res != 0, "failed to create temp file\n" );
2696 DeleteFileW( newpath );
2697 success = CreateDirectoryW( newpath, NULL );
2698 ok( success != 0, "failed to create temp directory\n" );
2699 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2700 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2702 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2703 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2704 fli->ReplaceIfExists = TRUE;
2705 fli->RootDirectory = NULL;
2706 fli->FileNameLength = name_str.Length;
2707 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2708 pRtlFreeUnicodeString( &name_str );
2710 U(io).Status = 0xdeadbeef;
2711 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2712 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2713 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2714 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2715 ok( !fileDeleted, "file should exist\n" );
2716 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2717 ok( !fileDeleted, "file should exist\n" );
2719 CloseHandle( handle );
2720 CloseHandle( handle2 );
2721 HeapFree( GetProcessHeap(), 0, fli );
2722 delete_object( oldpath );
2723 delete_object( newpath );
2725 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2726 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2727 ok( res != 0, "failed to create temp file\n" );
2728 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2729 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2731 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2732 ok( res != 0, "failed to create temp file\n" );
2733 DeleteFileW( newpath );
2734 success = CreateDirectoryW( newpath, NULL );
2735 ok( success != 0, "failed to create temp directory\n" );
2736 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2737 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2738 fli->ReplaceIfExists = FALSE;
2739 fli->RootDirectory = NULL;
2740 fli->FileNameLength = name_str.Length;
2741 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2742 pRtlFreeUnicodeString( &name_str );
2744 U(io).Status = 0xdeadbeef;
2745 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2746 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2747 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
2748 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2749 ok( !fileDeleted, "file should exist\n" );
2750 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2751 ok( !fileDeleted, "file should exist\n" );
2753 CloseHandle( handle );
2754 HeapFree( GetProcessHeap(), 0, fli );
2755 delete_object( oldpath );
2756 delete_object( newpath );
2758 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2759 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2760 ok( res != 0, "failed to create temp file\n" );
2761 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2762 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2764 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2765 ok( res != 0, "failed to create temp file\n" );
2766 DeleteFileW( newpath );
2767 success = CreateDirectoryW( newpath, NULL );
2768 ok( success != 0, "failed to create temp directory\n" );
2769 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2770 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2771 fli->ReplaceIfExists = TRUE;
2772 fli->RootDirectory = NULL;
2773 fli->FileNameLength = name_str.Length;
2774 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2775 pRtlFreeUnicodeString( &name_str );
2777 U(io).Status = 0xdeadbeef;
2778 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2779 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", U(io).Status );
2780 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2781 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2782 ok( !fileDeleted, "file should exist\n" );
2783 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2784 ok( !fileDeleted, "file should exist\n" );
2786 CloseHandle( handle );
2787 HeapFree( GetProcessHeap(), 0, fli );
2788 delete_object( oldpath );
2789 delete_object( newpath );
2791 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2792 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2793 ok( res != 0, "failed to create temp file\n" );
2794 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2795 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2797 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2798 ok( res != 0, "failed to create temp file\n" );
2799 DeleteFileW( newpath );
2800 for (filename = newpath, p = newpath; *p; p++)
2801 if (*p == '\\') filename = p + 1;
2802 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2803 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2805 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2806 fli->ReplaceIfExists = FALSE;
2807 fli->RootDirectory = handle2;
2808 fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2809 memcpy( fli->FileName, filename, fli->FileNameLength );
2811 U(io).Status = 0xdeadbeef;
2812 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2813 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", U(io).Status );
2814 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2815 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2816 ok( !fileDeleted, "file should exist\n" );
2817 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2818 ok( !fileDeleted, "file should exist\n" );
2820 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2821 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2822 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2823 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2824 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2825 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2826 HeapFree( GetProcessHeap(), 0, fni );
2828 CloseHandle( handle );
2829 CloseHandle( handle2 );
2830 HeapFree( GetProcessHeap(), 0, fli );
2831 delete_object( oldpath );
2832 delete_object( newpath );
2834 /* oldpath == newpath */
2835 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2836 ok( res != 0, "failed to create temp file\n" );
2837 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2838 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2840 pRtlDosPathNameToNtPathName_U( oldpath, &name_str, NULL, NULL );
2841 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2842 fli->ReplaceIfExists = FALSE;
2843 fli->RootDirectory = NULL;
2844 fli->FileNameLength = name_str.Length;
2845 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2846 pRtlFreeUnicodeString( &name_str );
2848 U(io).Status = 0xdeadbeef;
2849 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2850 todo_wine ok( U(io).Status == 0xdeadbeef, "got io status %#lx\n", U(io).Status );
2851 ok( res == STATUS_OBJECT_NAME_COLLISION, "got status %lx\n", res );
2853 fli->ReplaceIfExists = TRUE;
2854 U(io).Status = 0xdeadbeef;
2855 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2856 ok( U(io).Status == STATUS_SUCCESS, "got io status %#lx\n", U(io).Status );
2857 ok( res == STATUS_SUCCESS, "got status %lx\n", res );
2858 ok( GetFileAttributesW( oldpath ) != INVALID_FILE_ATTRIBUTES, "file should exist\n" );
2860 CloseHandle( handle );
2861 HeapFree( GetProcessHeap(), 0, fli );
2862 delete_object( oldpath );
2864 /* oldpath == newpath, different casing on link */
2865 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2866 ok( res != 0, "failed to create temp file\n" );
2867 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2868 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2870 wcsrchr( oldpath, '\\' )[1] = 'F';
2871 pRtlDosPathNameToNtPathName_U( oldpath, &name_str, NULL, NULL );
2872 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2873 fli->ReplaceIfExists = FALSE;
2874 fli->RootDirectory = NULL;
2875 fli->FileNameLength = name_str.Length;
2876 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2877 pRtlFreeUnicodeString( &name_str );
2879 U(io).Status = 0xdeadbeef;
2880 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2881 todo_wine ok( U(io).Status == 0xdeadbeef, "got io status %#lx\n", U(io).Status );
2882 ok( res == STATUS_OBJECT_NAME_COLLISION, "got status %lx\n", res );
2884 fli->ReplaceIfExists = TRUE;
2885 U(io).Status = 0xdeadbeef;
2886 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2887 ok( U(io).Status == STATUS_SUCCESS, "got io status %#lx\n", U(io).Status );
2888 ok( res == STATUS_SUCCESS, "got status %lx\n", res );
2889 ok( GetFileAttributesW( oldpath ) != INVALID_FILE_ATTRIBUTES, "file should exist\n" );
2891 CloseHandle( handle );
2892 handle = FindFirstFileW( oldpath, &find_data );
2893 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileW: failed, error %ld\n", GetLastError());
2894 if (handle != INVALID_HANDLE_VALUE)
2896 todo_wine ok(!lstrcmpW(wcsrchr(oldpath, '\\') + 1, find_data.cFileName),
2897 "Link did not change casing on same file: got %s\n", wine_dbgstr_w(find_data.cFileName));
2900 FindClose( handle );
2901 HeapFree( GetProcessHeap(), 0, fli );
2902 delete_object( oldpath );
2905 static void test_file_both_information(void)
2907 IO_STATUS_BLOCK io;
2908 FILE_BOTH_DIR_INFORMATION fbi;
2909 HANDLE h;
2910 int res;
2912 if (!(h = create_temp_file(0))) return;
2914 memset(&fbi, 0, sizeof(fbi));
2915 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
2916 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
2918 CloseHandle( h );
2921 static NTSTATUS nt_get_file_attrs(const char *name, DWORD *attrs)
2923 WCHAR nameW[MAX_PATH];
2924 FILE_BASIC_INFORMATION info;
2925 UNICODE_STRING nt_name;
2926 OBJECT_ATTRIBUTES attr;
2927 NTSTATUS status;
2929 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, MAX_PATH );
2931 *attrs = INVALID_FILE_ATTRIBUTES;
2933 if (!pRtlDosPathNameToNtPathName_U( nameW, &nt_name, NULL, NULL ))
2934 return STATUS_UNSUCCESSFUL;
2936 attr.Length = sizeof(attr);
2937 attr.RootDirectory = 0;
2938 attr.Attributes = OBJ_CASE_INSENSITIVE;
2939 attr.ObjectName = &nt_name;
2940 attr.SecurityDescriptor = NULL;
2941 attr.SecurityQualityOfService = NULL;
2943 status = pNtQueryAttributesFile( &attr, &info );
2944 pRtlFreeUnicodeString( &nt_name );
2946 if (status == STATUS_SUCCESS)
2947 *attrs = info.FileAttributes;
2949 return status;
2952 static void test_file_disposition_information(void)
2954 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
2955 DWORD dirpos;
2956 HANDLE handle, handle2, handle3, mapping;
2957 NTSTATUS res;
2958 IO_STATUS_BLOCK io;
2959 FILE_DISPOSITION_INFORMATION fdi;
2960 BOOL fileDeleted;
2961 DWORD fdi2, size;
2962 void *view;
2964 GetTempPathA( MAX_PATH, tmp_path );
2966 /* tests for info struct size */
2967 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2968 handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2969 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2970 res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
2971 todo_wine
2972 ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %lx\n", res );
2973 fdi2 = 0x100;
2974 res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
2975 ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %lx\n", res );
2976 CloseHandle( handle );
2977 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2978 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2979 DeleteFileA( buffer );
2981 /* cannot set disposition on file not opened with delete access */
2982 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2983 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2984 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2985 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2986 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %lx)\n", res );
2987 fdi.DoDeleteFile = TRUE;
2988 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2989 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %lx)\n", res );
2990 CloseHandle( handle );
2991 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2992 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2993 DeleteFileA( buffer );
2995 /* can set disposition on file opened with proper access */
2996 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2997 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2998 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2999 fdi.DoDeleteFile = TRUE;
3000 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3001 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3002 CloseHandle( handle );
3003 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3004 ok( fileDeleted, "File should have been deleted\n" );
3006 /* file exists until all handles to it get closed */
3007 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3008 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3009 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3010 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3011 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
3012 fdi.DoDeleteFile = TRUE;
3013 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3014 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3015 res = nt_get_file_attrs( buffer, &fdi2 );
3016 todo_wine
3017 ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res );
3018 /* can't open the deleted file */
3019 handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3020 todo_wine
3021 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3022 if (handle3 != INVALID_HANDLE_VALUE)
3023 CloseHandle( handle3 );
3024 todo_wine
3025 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3026 /* can't open the deleted file (wrong sharing mode) */
3027 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, 0, 0);
3028 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3029 todo_wine
3030 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3031 CloseHandle( handle );
3032 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3033 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3034 CloseHandle( handle2 );
3035 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3036 ok( fileDeleted, "File should have been deleted\n" );
3038 /* file exists until all handles to it get closed */
3039 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3040 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
3041 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3042 /* can open the marked for delete file (proper sharing mode) */
3043 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3044 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
3045 res = nt_get_file_attrs( buffer, &fdi2 );
3046 ok( res == STATUS_SUCCESS, "got %#lx\n", res );
3047 /* can't open the marked for delete file (wrong sharing mode) */
3048 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, 0, 0);
3049 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3050 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3051 CloseHandle( handle );
3052 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3053 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3054 CloseHandle( handle2 );
3055 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3056 ok( fileDeleted, "File should have been deleted\n" );
3058 /* cannot set disposition on readonly file */
3059 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3060 DeleteFileA( buffer );
3061 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
3062 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3063 fdi.DoDeleteFile = TRUE;
3064 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3065 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %lx)\n", res );
3066 CloseHandle( handle );
3067 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3068 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3069 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
3070 DeleteFileA( buffer );
3072 /* cannot set disposition on readonly file */
3073 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3074 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
3075 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3076 fdi.DoDeleteFile = TRUE;
3077 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3078 todo_wine
3079 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %lx)\n", res );
3080 CloseHandle( handle );
3081 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3082 todo_wine
3083 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3084 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
3085 DeleteFileA( buffer );
3087 /* can set disposition on file and then reset it */
3088 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3089 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
3090 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3091 fdi.DoDeleteFile = TRUE;
3092 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3093 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3094 fdi.DoDeleteFile = FALSE;
3095 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3096 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3097 CloseHandle( handle );
3098 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3099 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3100 DeleteFileA( buffer );
3102 /* can't reset disposition if delete-on-close flag is specified */
3103 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3104 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
3105 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3106 fdi.DoDeleteFile = FALSE;
3107 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3108 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3109 CloseHandle( handle );
3110 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3111 ok( fileDeleted, "File should have been deleted\n" );
3113 /* can't reset disposition on duplicated handle if delete-on-close flag is specified */
3114 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3115 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
3116 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3117 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
3118 CloseHandle( handle );
3119 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3120 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3121 fdi.DoDeleteFile = FALSE;
3122 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
3123 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3124 CloseHandle( handle2 );
3125 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3126 ok( fileDeleted, "File should have been deleted\n" );
3128 /* DeleteFile fails for wrong sharing mode */
3129 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3130 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
3131 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3132 fileDeleted = DeleteFileA( buffer );
3133 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3134 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3135 CloseHandle( handle );
3136 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3137 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3138 DeleteFileA( buffer );
3140 /* DeleteFile succeeds for proper sharing mode */
3141 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3142 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3143 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3144 fileDeleted = DeleteFileA( buffer );
3145 ok( fileDeleted, "File should have been deleted\n" );
3146 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3147 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3148 res = nt_get_file_attrs( buffer, &fdi2 );
3149 todo_wine
3150 ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res );
3151 /* can't open the deleted file */
3152 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0);
3153 ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3154 todo_wine
3155 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3156 CloseHandle( handle );
3157 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3158 ok( fileDeleted, "File should have been deleted\n" );
3160 /* can set disposition on a directory opened with proper access */
3161 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3162 DeleteFileA( buffer );
3163 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3164 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3165 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3166 fdi.DoDeleteFile = TRUE;
3167 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3168 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3169 CloseHandle( handle );
3170 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3171 ok( fileDeleted, "Directory should have been deleted\n" );
3173 /* RemoveDirectory fails for wrong sharing mode */
3174 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3175 DeleteFileA( buffer );
3176 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3177 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3178 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3179 fileDeleted = RemoveDirectoryA( buffer );
3180 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3181 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3182 CloseHandle( handle );
3183 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3184 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3185 RemoveDirectoryA( buffer );
3187 /* RemoveDirectory succeeds for proper sharing mode */
3188 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3189 DeleteFileA( buffer );
3190 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3191 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3192 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3193 fileDeleted = RemoveDirectoryA( buffer );
3194 ok( fileDeleted, "Directory should have been deleted\n" );
3195 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3196 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3197 res = nt_get_file_attrs( buffer, &fdi2 );
3198 todo_wine
3199 ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res );
3200 /* can't open the deleted directory */
3201 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3202 todo_wine
3203 ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3204 todo_wine
3205 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3206 if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2 );
3207 CloseHandle( handle );
3208 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3209 ok( fileDeleted, "Directory should have been deleted\n" );
3211 /* directory exists until all handles to it get closed */
3212 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3213 DeleteFileA( buffer );
3214 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3215 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3216 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3217 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3218 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3219 fdi.DoDeleteFile = TRUE;
3220 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
3221 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3222 res = nt_get_file_attrs( buffer, &fdi2 );
3223 todo_wine
3224 ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res );
3225 /* can't open the deleted directory */
3226 handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3227 todo_wine
3228 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3229 if (handle3 != INVALID_HANDLE_VALUE)
3230 CloseHandle( handle3 );
3231 todo_wine
3232 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3233 /* can't open the deleted directory (wrong sharing mode) */
3234 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3235 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3236 todo_wine
3237 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3238 CloseHandle( handle2 );
3239 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3240 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3241 CloseHandle( handle );
3242 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3243 ok( fileDeleted, "Directory should have been deleted\n" );
3245 /* directory exists until all handles to it get closed */
3246 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3247 DeleteFileA( buffer );
3248 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3249 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
3250 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3251 /* can open the marked for delete directory (proper sharing mode) */
3252 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3253 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3254 /* can't open the marked for delete file (wrong sharing mode) */
3255 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3256 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3257 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3258 CloseHandle( handle );
3259 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3260 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3261 CloseHandle( handle2 );
3262 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3263 ok( fileDeleted, "Directory should have been deleted\n" );
3265 /* can open a non-empty directory with FILE_FLAG_DELETE_ON_CLOSE */
3266 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3267 DeleteFileA( buffer );
3268 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3269 dirpos = lstrlenA( buffer );
3270 lstrcpyA( buffer + dirpos, "\\tst" );
3271 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3272 CloseHandle( handle2 );
3273 buffer[dirpos] = '\0';
3274 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
3275 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3276 SetLastError(0xdeadbeef);
3277 CloseHandle( handle );
3278 ok(GetLastError() == 0xdeadbeef, "got %lu\n", GetLastError());
3279 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3280 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3281 buffer[dirpos] = '\\';
3282 fileDeleted = DeleteFileA( buffer );
3283 ok( fileDeleted, "File should have been deleted\n" );
3284 buffer[dirpos] = '\0';
3285 fileDeleted = RemoveDirectoryA( buffer );
3286 ok( fileDeleted, "Directory should have been deleted\n" );
3288 /* cannot set disposition on a non-empty directory */
3289 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3290 DeleteFileA( buffer );
3291 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3292 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3293 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3294 dirpos = lstrlenA( buffer );
3295 lstrcpyA( buffer + dirpos, "\\tst" );
3296 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3297 CloseHandle( handle2 );
3298 fdi.DoDeleteFile = TRUE;
3299 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3300 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %lx)\n", res );
3301 fileDeleted = DeleteFileA( buffer );
3302 ok( fileDeleted, "File should have been deleted\n" );
3303 buffer[dirpos] = '\0';
3304 CloseHandle( handle );
3305 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3306 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3307 fileDeleted = RemoveDirectoryA( buffer );
3308 ok( fileDeleted, "Directory should have been deleted\n" );
3310 /* a file with an open mapping handle cannot be deleted */
3312 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3313 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3314 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3315 WriteFile(handle, "data", 4, &size, NULL);
3316 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3317 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3319 fdi.DoDeleteFile = FALSE;
3320 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3321 ok( !res, "got %#lx\n", res );
3323 fdi.DoDeleteFile = TRUE;
3324 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3325 ok( res == STATUS_CANNOT_DELETE, "got %#lx\n", res );
3326 res = GetFileAttributesA( buffer );
3327 ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
3329 CloseHandle( mapping );
3330 CloseHandle( handle );
3331 res = DeleteFileA( buffer );
3332 ok( res, "got error %lu\n", GetLastError() );
3334 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3335 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3336 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3337 WriteFile(handle, "data", 4, &size, NULL);
3338 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3339 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3340 CloseHandle( mapping );
3342 fdi.DoDeleteFile = TRUE;
3343 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3344 ok( !res, "got %#lx\n", res );
3346 CloseHandle( handle );
3347 res = DeleteFileA( buffer );
3348 ok( !res, "expected failure\n" );
3349 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError() );
3351 /* a file with an open view cannot be deleted */
3353 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3354 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3355 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3356 WriteFile(handle, "data", 4, &size, NULL);
3357 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3358 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3359 view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4 );
3360 ok( !!view, "failed to map view, error %lu\n", GetLastError() );
3361 CloseHandle( mapping );
3363 fdi.DoDeleteFile = FALSE;
3364 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3365 ok( !res, "got %#lx\n", res );
3367 fdi.DoDeleteFile = TRUE;
3368 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3369 ok( res == STATUS_CANNOT_DELETE, "got %#lx\n", res );
3370 res = GetFileAttributesA( buffer );
3371 ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
3373 UnmapViewOfFile( view );
3374 CloseHandle( handle );
3375 res = DeleteFileA( buffer );
3376 ok( res, "got error %lu\n", GetLastError() );
3378 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3379 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3380 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3381 WriteFile(handle, "data", 4, &size, NULL);
3382 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3383 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3384 view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4 );
3385 ok( !!view, "failed to map view, error %lu\n", GetLastError() );
3386 CloseHandle( mapping );
3387 UnmapViewOfFile( view );
3389 fdi.DoDeleteFile = TRUE;
3390 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3391 ok( !res, "got %#lx\n", res );
3393 CloseHandle( handle );
3394 res = DeleteFileA( buffer );
3395 ok( !res, "expected failure\n" );
3396 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError() );
3399 static void test_file_name_information(void)
3401 WCHAR *file_name, *volume_prefix, *expected;
3402 FILE_NAME_INFORMATION *info;
3403 ULONG old_redir = 1, tmp;
3404 UINT file_name_size;
3405 IO_STATUS_BLOCK io;
3406 UINT info_size;
3407 HRESULT hr;
3408 HANDLE h;
3409 UINT len;
3411 /* GetVolumePathName is not present before w2k */
3412 if (!pGetVolumePathNameW) {
3413 win_skip("GetVolumePathNameW not found\n");
3414 return;
3417 file_name_size = GetSystemDirectoryW( NULL, 0 );
3418 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3419 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3420 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3422 len = GetSystemDirectoryW( file_name, file_name_size );
3423 ok(len == file_name_size - 1,
3424 "GetSystemDirectoryW returned %u, expected %u.\n",
3425 len, file_name_size - 1);
3427 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3428 ok(len, "GetVolumePathNameW failed.\n");
3430 len = lstrlenW( volume_prefix );
3431 if (len && volume_prefix[len - 1] == '\\') --len;
3432 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3433 expected[file_name_size - len - 1] = '\0';
3435 /* A bit more than we actually need, but it keeps the calculation simple. */
3436 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3437 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3439 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3440 h = CreateFileW( file_name, GENERIC_READ,
3441 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3442 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3443 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3444 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3446 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
3447 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#lx.\n", hr);
3449 memset( info, 0xcc, info_size );
3450 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
3451 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3452 hr, STATUS_BUFFER_OVERFLOW);
3453 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#lx, expected %#lx.\n",
3454 U(io).Status, STATUS_BUFFER_OVERFLOW);
3455 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %lu\n", info->FileNameLength);
3456 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
3457 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3458 "info->FileName[1] is %p, expected %p.\n",
3459 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3460 ok(io.Information == sizeof(*info), "io.Information is %Iu\n", io.Information);
3462 memset( info, 0xcc, info_size );
3463 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3464 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
3465 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#lx, expected %#lx.\n", U(io).Status, STATUS_SUCCESS);
3466 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %lu\n", info->FileNameLength);
3467 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
3468 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
3469 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3470 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3471 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3472 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
3473 "io.Information is %Iu, expected %lu.\n",
3474 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
3476 CloseHandle( h );
3477 HeapFree( GetProcessHeap(), 0, info );
3478 HeapFree( GetProcessHeap(), 0, expected );
3479 HeapFree( GetProcessHeap(), 0, volume_prefix );
3481 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3483 skip("Not running on WoW64, skipping test.\n");
3484 HeapFree( GetProcessHeap(), 0, file_name );
3485 return;
3488 h = CreateFileW( file_name, GENERIC_READ,
3489 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3490 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3491 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3492 HeapFree( GetProcessHeap(), 0, file_name );
3494 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3495 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3496 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3498 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3499 ok(len == file_name_size - 1,
3500 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3501 len, file_name_size - 1);
3503 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3504 ok(len, "GetVolumePathNameW failed.\n");
3506 len = lstrlenW( volume_prefix );
3507 if (len && volume_prefix[len - 1] == '\\') --len;
3508 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3509 expected[file_name_size - len - 1] = '\0';
3511 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3512 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3514 memset( info, 0xcc, info_size );
3515 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3516 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
3517 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3518 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3519 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3521 CloseHandle( h );
3522 HeapFree( GetProcessHeap(), 0, info );
3523 HeapFree( GetProcessHeap(), 0, expected );
3524 HeapFree( GetProcessHeap(), 0, volume_prefix );
3525 HeapFree( GetProcessHeap(), 0, file_name );
3528 static void test_file_all_name_information(void)
3530 WCHAR *file_name, *volume_prefix, *expected;
3531 FILE_ALL_INFORMATION *info;
3532 ULONG old_redir = 1, tmp;
3533 UINT file_name_size;
3534 IO_STATUS_BLOCK io;
3535 UINT info_size;
3536 HRESULT hr;
3537 HANDLE h;
3538 UINT len;
3540 /* GetVolumePathName is not present before w2k */
3541 if (!pGetVolumePathNameW) {
3542 win_skip("GetVolumePathNameW not found\n");
3543 return;
3546 file_name_size = GetSystemDirectoryW( NULL, 0 );
3547 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3548 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3549 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3551 len = GetSystemDirectoryW( file_name, file_name_size );
3552 ok(len == file_name_size - 1,
3553 "GetSystemDirectoryW returned %u, expected %u.\n",
3554 len, file_name_size - 1);
3556 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3557 ok(len, "GetVolumePathNameW failed.\n");
3559 len = lstrlenW( volume_prefix );
3560 if (len && volume_prefix[len - 1] == '\\') --len;
3561 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3562 expected[file_name_size - len - 1] = '\0';
3564 /* A bit more than we actually need, but it keeps the calculation simple. */
3565 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3566 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3568 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3569 h = CreateFileW( file_name, GENERIC_READ,
3570 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3571 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3572 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3573 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3575 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
3576 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3577 hr, STATUS_INFO_LENGTH_MISMATCH);
3579 memset( info, 0xcc, info_size );
3580 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
3581 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3582 hr, STATUS_BUFFER_OVERFLOW);
3583 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#lx, expected %#lx.\n",
3584 U(io).Status, STATUS_BUFFER_OVERFLOW);
3585 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3586 "info->NameInformation.FileNameLength is %lu\n", info->NameInformation.FileNameLength );
3587 ok(info->NameInformation.FileName[2] == 0xcccc,
3588 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
3589 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3590 "info->NameInformation.FileName[1] is %p, expected %p.\n",
3591 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3592 ok(io.Information == sizeof(*info), "io.Information is %Iu\n", io.Information);
3594 memset( info, 0xcc, info_size );
3595 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3596 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
3597 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#lx, expected %#lx.\n", U(io).Status, STATUS_SUCCESS);
3598 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3599 "info->NameInformation.FileNameLength is %lu\n", info->NameInformation.FileNameLength );
3600 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
3601 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3602 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
3603 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3604 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
3605 "info->NameInformation.FileName is %s, expected %s.\n",
3606 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3607 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
3608 + info->NameInformation.FileNameLength,
3609 "io.Information is %Iu\n", io.Information );
3611 CloseHandle( h );
3612 HeapFree( GetProcessHeap(), 0, info );
3613 HeapFree( GetProcessHeap(), 0, expected );
3614 HeapFree( GetProcessHeap(), 0, volume_prefix );
3616 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3618 skip("Not running on WoW64, skipping test.\n");
3619 HeapFree( GetProcessHeap(), 0, file_name );
3620 return;
3623 h = CreateFileW( file_name, GENERIC_READ,
3624 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3625 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3626 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3627 HeapFree( GetProcessHeap(), 0, file_name );
3629 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3630 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3631 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3633 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3634 ok(len == file_name_size - 1,
3635 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3636 len, file_name_size - 1);
3638 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3639 ok(len, "GetVolumePathNameW failed.\n");
3641 len = lstrlenW( volume_prefix );
3642 if (len && volume_prefix[len - 1] == '\\') --len;
3643 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3644 expected[file_name_size - len - 1] = '\0';
3646 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3647 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3649 memset( info, 0xcc, info_size );
3650 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3651 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
3652 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3653 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
3654 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3656 CloseHandle( h );
3657 HeapFree( GetProcessHeap(), 0, info );
3658 HeapFree( GetProcessHeap(), 0, expected );
3659 HeapFree( GetProcessHeap(), 0, volume_prefix );
3660 HeapFree( GetProcessHeap(), 0, file_name );
3663 #define test_completion_flags(a,b) _test_completion_flags(__LINE__,a,b)
3664 static void _test_completion_flags(unsigned line, HANDLE handle, DWORD expected_flags)
3666 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
3667 IO_STATUS_BLOCK io;
3668 NTSTATUS status;
3670 info.Flags = 0xdeadbeef;
3671 status = pNtQueryInformationFile(handle, &io, &info, sizeof(info),
3672 FileIoCompletionNotificationInformation);
3673 ok_(__FILE__,line)(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3674 ok_(__FILE__,line)(io.Status == STATUS_SUCCESS, "Status = %lx\n", io.Status);
3675 ok_(__FILE__,line)(io.Information == sizeof(info), "Information = %Iu\n", io.Information);
3676 /* FILE_SKIP_SET_USER_EVENT_ON_FAST_IO is not supported on win2k3 */
3677 ok_(__FILE__,line)((info.Flags & ~FILE_SKIP_SET_USER_EVENT_ON_FAST_IO) == expected_flags,
3678 "got %08lx\n", info.Flags);
3681 static void test_file_completion_information(void)
3683 DECLSPEC_ALIGN(TEST_OVERLAPPED_READ_SIZE) static unsigned char aligned_buf[TEST_OVERLAPPED_READ_SIZE];
3684 static const char buf[] = "testdata";
3685 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
3686 OVERLAPPED ov, *pov;
3687 IO_STATUS_BLOCK io;
3688 NTSTATUS status;
3689 DWORD num_bytes;
3690 HANDLE port, h;
3691 ULONG_PTR key;
3692 BOOL ret;
3693 int i;
3695 if (!(h = create_temp_file(0))) return;
3697 status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
3698 ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS /* XP */),
3699 "expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
3700 if (status != STATUS_INFO_LENGTH_MISMATCH)
3702 win_skip("FileIoCompletionNotificationInformation class not supported\n");
3703 CloseHandle(h);
3704 return;
3707 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3708 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3709 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3711 CloseHandle(h);
3712 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3714 info.Flags = FILE_SKIP_SET_EVENT_ON_HANDLE;
3715 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3716 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3717 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
3719 info.Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO;
3720 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3721 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3722 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
3724 info.Flags = 0;
3725 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3726 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3727 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
3729 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3730 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3731 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3732 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
3734 info.Flags = 0xdeadbeef;
3735 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3736 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3737 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
3739 CloseHandle(h);
3740 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3741 test_completion_flags(h, 0);
3743 memset(&ov, 0, sizeof(ov));
3744 ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
3745 port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
3746 ok(port != NULL, "CreateIoCompletionPort failed, error %lu\n", GetLastError());
3748 for (i = 0; i < 10; i++)
3750 SetLastError(0xdeadbeef);
3751 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3752 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* Before Vista */,
3753 "Unexpected result %#x, GetLastError() %lu.\n", ret, GetLastError());
3754 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3755 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3756 ok(ret, "GetOverlappedResult failed, error %lu\n", GetLastError());
3757 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3758 ok(ret, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
3759 ret = FALSE;
3761 if (ret)
3763 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %lu\n", num_bytes);
3765 key = 0;
3766 pov = NULL;
3767 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3768 ok(ret, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
3769 ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %Ix\n", key);
3770 ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
3773 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3774 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3775 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3776 test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
3778 for (i = 0; i < 10; i++)
3780 SetLastError(0xdeadbeef);
3781 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3782 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* Before Vista */,
3783 "Unexpected result %#x, GetLastError() %lu.\n", ret, GetLastError());
3784 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3785 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3786 ok(ret, "GetOverlappedResult failed, error %lu\n", GetLastError());
3787 ret = FALSE;
3789 if (ret)
3791 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %lu\n", num_bytes);
3793 pov = (void *)0xdeadbeef;
3794 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
3795 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3796 ok(pov == NULL, "expected NULL, got %p\n", pov);
3799 info.Flags = 0;
3800 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3801 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3802 test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
3804 for (i = 0; i < 10; i++)
3806 SetLastError(0xdeadbeef);
3807 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3808 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* Before Vista */,
3809 "Unexpected result %#x, GetLastError() %lu.\n", ret, GetLastError());
3810 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3811 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3812 ok(ret, "GetOverlappedResult failed, error %lu\n", GetLastError());
3813 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3814 ok(ret, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
3815 ret = FALSE;
3817 if (ret)
3819 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %lu\n", num_bytes);
3821 pov = (void *)0xdeadbeef;
3822 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3823 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3824 ok(pov == NULL, "expected NULL, got %p\n", pov);
3827 CloseHandle(port);
3828 CloseHandle(h);
3830 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING)))
3831 return;
3833 port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
3834 ok(port != NULL, "CreateIoCompletionPort failed, error %lu.\n", GetLastError());
3836 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3837 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3838 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %#lx.\n", status);
3839 test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
3841 ret = WriteFile(h, aligned_buf, sizeof(aligned_buf), &num_bytes, &ov);
3842 if (!ret && GetLastError() == ERROR_IO_PENDING)
3844 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3845 ok(ret, "GetOverlappedResult failed, error %lu.\n", GetLastError());
3846 ok(num_bytes == sizeof(aligned_buf), "expected sizeof(aligned_buf), got %lu.\n", num_bytes);
3847 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3848 ok(ret, "GetQueuedCompletionStatus failed, error %lu.\n", GetLastError());
3850 ok(num_bytes == sizeof(aligned_buf), "expected sizeof(buf), got %lu.\n", num_bytes);
3852 SetLastError(0xdeadbeef);
3853 ret = ReadFile(h, aligned_buf, sizeof(aligned_buf), &num_bytes, &ov);
3854 ok(!ret && GetLastError() == ERROR_IO_PENDING, "Unexpected result, ret %#x, error %lu.\n",
3855 ret, GetLastError());
3856 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3857 ok(ret, "GetOverlappedResult failed, error %lu.\n", GetLastError());
3858 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3859 ok(ret, "GetQueuedCompletionStatus failed, error %lu.\n", GetLastError());
3861 CloseHandle(ov.hEvent);
3862 CloseHandle(port);
3863 CloseHandle(h);
3866 static void test_file_id_information(void)
3868 BY_HANDLE_FILE_INFORMATION info;
3869 FILE_ID_INFORMATION fid;
3870 IO_STATUS_BLOCK io;
3871 NTSTATUS status;
3872 DWORD *dwords;
3873 HANDLE h;
3874 BOOL ret;
3876 if (!(h = create_temp_file(0))) return;
3878 memset( &fid, 0x11, sizeof(fid) );
3879 status = pNtQueryInformationFile( h, &io, &fid, sizeof(fid), FileIdInformation );
3880 if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
3882 win_skip( "FileIdInformation not supported\n" );
3883 CloseHandle( h );
3884 return;
3887 memset( &info, 0x22, sizeof(info) );
3888 ret = GetFileInformationByHandle( h, &info );
3889 ok( ret, "GetFileInformationByHandle failed\n" );
3891 dwords = (DWORD *)&fid.VolumeSerialNumber;
3892 ok( dwords[0] == info.dwVolumeSerialNumber, "expected %08lx, got %08lx\n",
3893 info.dwVolumeSerialNumber, dwords[0] );
3894 ok( dwords[1] != 0x11111111, "expected != 0x11111111\n" );
3896 dwords = (DWORD *)&fid.FileId;
3897 ok( dwords[0] == info.nFileIndexLow, "expected %08lx, got %08lx\n", info.nFileIndexLow, dwords[0] );
3898 ok( dwords[1] == info.nFileIndexHigh, "expected %08lx, got %08lx\n", info.nFileIndexHigh, dwords[1] );
3899 ok( dwords[2] == 0, "expected 0, got %08lx\n", dwords[2] );
3900 ok( dwords[3] == 0, "expected 0, got %08lx\n", dwords[3] );
3902 CloseHandle( h );
3905 static void test_file_access_information(void)
3907 FILE_ACCESS_INFORMATION info;
3908 IO_STATUS_BLOCK io;
3909 NTSTATUS status;
3910 HANDLE h;
3912 if (!(h = create_temp_file(0))) return;
3914 status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation );
3915 ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3917 status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation );
3918 ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status );
3920 memset(&info, 0x11, sizeof(info));
3921 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation );
3922 ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status );
3923 ok( info.AccessFlags == 0x13019f, "got %08lx\n", info.AccessFlags );
3925 CloseHandle( h );
3928 static void test_file_attribute_tag_information(void)
3930 FILE_ATTRIBUTE_TAG_INFORMATION info;
3931 FILE_BASIC_INFORMATION fbi = {};
3932 IO_STATUS_BLOCK io;
3933 NTSTATUS status;
3934 HANDLE h;
3936 if (!(h = create_temp_file(0))) return;
3938 status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAttributeTagInformation );
3939 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status );
3941 status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAttributeTagInformation );
3942 ok( status == STATUS_INVALID_HANDLE, "got %#lx\n", status );
3944 memset(&info, 0x11, sizeof(info));
3945 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAttributeTagInformation );
3946 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3947 info.FileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
3948 ok( info.FileAttributes == FILE_ATTRIBUTE_ARCHIVE, "got attributes %#lx\n", info.FileAttributes );
3949 ok( !info.ReparseTag, "got reparse tag %#lx\n", info.ReparseTag );
3951 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
3952 status = pNtSetInformationFile(h, &io, &fbi, sizeof(fbi), FileBasicInformation);
3953 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3955 memset(&info, 0x11, sizeof(info));
3956 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAttributeTagInformation );
3957 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3958 todo_wine ok( info.FileAttributes == FILE_ATTRIBUTE_SYSTEM, "got attributes %#lx\n", info.FileAttributes );
3959 ok( !info.ReparseTag, "got reparse tag %#lx\n", info.ReparseTag );
3961 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
3962 status = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
3963 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3965 memset(&info, 0x11, sizeof(info));
3966 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAttributeTagInformation );
3967 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3968 todo_wine ok( info.FileAttributes == FILE_ATTRIBUTE_HIDDEN, "got attributes %#lx\n", info.FileAttributes );
3969 ok( !info.ReparseTag, "got reparse tag %#lx\n", info.ReparseTag );
3971 CloseHandle( h );
3974 static void test_file_mode(void)
3976 UNICODE_STRING file_name, pipe_dev_name, mountmgr_dev_name, mailslot_dev_name;
3977 WCHAR tmp_path[MAX_PATH], dos_file_name[MAX_PATH];
3978 FILE_MODE_INFORMATION mode;
3979 OBJECT_ATTRIBUTES attr;
3980 IO_STATUS_BLOCK io;
3981 HANDLE file;
3982 unsigned i;
3983 DWORD res, access;
3984 NTSTATUS status;
3986 const struct {
3987 UNICODE_STRING *file_name;
3988 ULONG options;
3989 ULONG mode;
3990 } option_tests[] = {
3991 { &file_name, 0, 0 },
3992 { &file_name, FILE_NON_DIRECTORY_FILE, 0 },
3993 { &file_name, FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY, FILE_SEQUENTIAL_ONLY },
3994 { &file_name, FILE_WRITE_THROUGH, FILE_WRITE_THROUGH },
3995 { &file_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT },
3996 { &file_name, FILE_NO_INTERMEDIATE_BUFFERING, FILE_NO_INTERMEDIATE_BUFFERING },
3997 { &file_name, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, FILE_SYNCHRONOUS_IO_NONALERT },
3998 { &file_name, FILE_DELETE_ON_CLOSE, 0 },
3999 { &file_name, FILE_RANDOM_ACCESS | FILE_NO_COMPRESSION, 0 },
4000 { &pipe_dev_name, 0, 0 },
4001 { &pipe_dev_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT },
4002 { &mailslot_dev_name, 0, 0 },
4003 { &mailslot_dev_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT },
4004 { &mountmgr_dev_name, 0, 0 },
4005 { &mountmgr_dev_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT }
4008 static WCHAR pipe_devW[] = {'\\','?','?','\\','P','I','P','E','\\'};
4009 static WCHAR mailslot_devW[] = {'\\','?','?','\\','M','A','I','L','S','L','O','T','\\'};
4010 static WCHAR mountmgr_devW[] =
4011 {'\\','?','?','\\','M','o','u','n','t','P','o','i','n','t','M','a','n','a','g','e','r'};
4013 GetTempPathW(MAX_PATH, tmp_path);
4014 res = GetTempFileNameW(tmp_path, fooW, 0, dos_file_name);
4015 ok(res, "GetTempFileNameW failed: %lu\n", GetLastError());
4016 pRtlDosPathNameToNtPathName_U( dos_file_name, &file_name, NULL, NULL );
4018 pipe_dev_name.Buffer = pipe_devW;
4019 pipe_dev_name.Length = sizeof(pipe_devW);
4020 pipe_dev_name.MaximumLength = sizeof(pipe_devW);
4022 mailslot_dev_name.Buffer = mailslot_devW;
4023 mailslot_dev_name.Length = sizeof(mailslot_devW);
4024 mailslot_dev_name.MaximumLength = sizeof(mailslot_devW);
4026 mountmgr_dev_name.Buffer = mountmgr_devW;
4027 mountmgr_dev_name.Length = sizeof(mountmgr_devW);
4028 mountmgr_dev_name.MaximumLength = sizeof(mountmgr_devW);
4030 attr.Length = sizeof(attr);
4031 attr.RootDirectory = 0;
4032 attr.Attributes = OBJ_CASE_INSENSITIVE;
4033 attr.SecurityDescriptor = NULL;
4034 attr.SecurityQualityOfService = NULL;
4036 for (i = 0; i < ARRAY_SIZE(option_tests); i++)
4038 attr.ObjectName = option_tests[i].file_name;
4039 access = SYNCHRONIZE;
4041 if (option_tests[i].file_name == &file_name)
4043 file = CreateFileW(dos_file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
4044 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
4045 CloseHandle(file);
4046 access |= GENERIC_WRITE | DELETE;
4049 status = pNtOpenFile(&file, access, &attr, &io, 0, option_tests[i].options);
4050 ok(status == STATUS_SUCCESS, "[%u] NtOpenFile failed: %lx\n", i, status);
4052 memset(&mode, 0xcc, sizeof(mode));
4053 status = pNtQueryInformationFile(file, &io, &mode, sizeof(mode), FileModeInformation);
4054 ok(status == STATUS_SUCCESS, "[%u] can't get FileModeInformation: %lx\n", i, status);
4055 ok(mode.Mode == option_tests[i].mode, "[%u] Mode = %lx, expected %lx\n",
4056 i, mode.Mode, option_tests[i].mode);
4058 pNtClose(file);
4059 if (option_tests[i].file_name == &file_name)
4060 DeleteFileW(dos_file_name);
4063 pRtlFreeUnicodeString(&file_name);
4066 static void test_query_volume_information_file(void)
4068 NTSTATUS status;
4069 HANDLE dir;
4070 WCHAR path[MAX_PATH];
4071 OBJECT_ATTRIBUTES attr;
4072 IO_STATUS_BLOCK io;
4073 UNICODE_STRING nameW;
4074 FILE_FS_VOLUME_INFORMATION *ffvi;
4075 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
4077 GetWindowsDirectoryW( path, MAX_PATH );
4078 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
4079 attr.Length = sizeof(attr);
4080 attr.RootDirectory = 0;
4081 attr.ObjectName = &nameW;
4082 attr.Attributes = OBJ_CASE_INSENSITIVE;
4083 attr.SecurityDescriptor = NULL;
4084 attr.SecurityQualityOfService = NULL;
4086 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
4087 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
4088 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
4089 pRtlFreeUnicodeString( &nameW );
4091 ZeroMemory( buf, sizeof(buf) );
4092 U(io).Status = 0xdadadada;
4093 io.Information = 0xcacacaca;
4095 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
4097 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
4099 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", status);
4100 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", U(io).Status);
4102 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
4103 "expected %ld, got %Iu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
4104 io.Information);
4106 todo_wine ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
4107 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
4108 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
4109 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %ld\n", ffvi->VolumeLabelLength);
4111 trace("VolumeSerialNumber: %lx VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
4113 CloseHandle( dir );
4116 static void test_query_attribute_information_file(void)
4118 NTSTATUS status;
4119 HANDLE dir;
4120 WCHAR path[MAX_PATH];
4121 OBJECT_ATTRIBUTES attr;
4122 IO_STATUS_BLOCK io;
4123 UNICODE_STRING nameW;
4124 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
4125 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
4127 GetWindowsDirectoryW( path, MAX_PATH );
4128 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
4129 attr.Length = sizeof(attr);
4130 attr.RootDirectory = 0;
4131 attr.ObjectName = &nameW;
4132 attr.Attributes = OBJ_CASE_INSENSITIVE;
4133 attr.SecurityDescriptor = NULL;
4134 attr.SecurityQualityOfService = NULL;
4136 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
4137 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
4138 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
4139 pRtlFreeUnicodeString( &nameW );
4141 ZeroMemory( buf, sizeof(buf) );
4142 U(io).Status = 0xdadadada;
4143 io.Information = 0xcacacaca;
4145 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
4147 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
4149 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", status);
4150 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", U(io).Status);
4151 ok(ffai->FileSystemAttributes != 0, "Missing FileSystemAttributes\n");
4152 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
4153 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
4155 trace("FileSystemAttributes: %lx MaximumComponentNameLength: %lx FileSystemName: %s\n",
4156 ffai->FileSystemAttributes, ffai->MaximumComponentNameLength,
4157 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
4159 CloseHandle( dir );
4162 static void test_NtCreateFile(void)
4164 static const struct test_data
4166 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
4167 } td[] =
4169 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4170 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
4171 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4172 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
4173 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
4174 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4175 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
4176 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4177 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4178 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
4179 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
4180 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4181 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4182 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
4183 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4184 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4185 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4186 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
4187 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
4189 static const WCHAR fooW[] = {'f','o','o',0};
4190 NTSTATUS status;
4191 HANDLE handle;
4192 WCHAR path[MAX_PATH];
4193 OBJECT_ATTRIBUTES attr;
4194 IO_STATUS_BLOCK io;
4195 UNICODE_STRING nameW;
4196 DWORD ret, i;
4198 GetTempPathW(MAX_PATH, path);
4199 GetTempFileNameW(path, fooW, 0, path);
4200 DeleteFileW(path);
4201 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
4203 attr.Length = sizeof(attr);
4204 attr.RootDirectory = NULL;
4205 attr.ObjectName = &nameW;
4206 attr.Attributes = OBJ_CASE_INSENSITIVE;
4207 attr.SecurityDescriptor = NULL;
4208 attr.SecurityQualityOfService = NULL;
4210 for (i = 0; i < ARRAY_SIZE(td); i++)
4212 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
4213 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
4214 td[i].disposition, 0, NULL, 0);
4216 ok(status == td[i].status, "%ld: expected %#lx got %#lx\n", i, td[i].status, status);
4218 if (!status)
4220 ok(io.Information == td[i].result,"%ld: expected %#lx got %#Ix\n", i, td[i].result, io.Information);
4222 ret = GetFileAttributesW(path);
4223 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
4224 /* FIXME: leave only 'else' case below once Wine is fixed */
4225 if (ret != td[i].attrib_out)
4227 todo_wine
4228 ok(ret == td[i].attrib_out, "%ld: expected %#lx got %#lx\n", i, td[i].attrib_out, ret);
4229 SetFileAttributesW(path, td[i].attrib_out);
4231 else
4232 ok(ret == td[i].attrib_out, "%ld: expected %#lx got %#lx\n", i, td[i].attrib_out, ret);
4234 CloseHandle(handle);
4237 if (td[i].needs_cleanup)
4239 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
4240 DeleteFileW(path);
4244 pRtlFreeUnicodeString( &nameW );
4245 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
4246 DeleteFileW( path );
4248 wcscat( path, L"\\" );
4249 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
4251 status = pNtCreateFile( &handle, GENERIC_READ, &attr, &io, NULL,
4252 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_CREATE, 0, NULL, 0);
4253 ok( status == STATUS_OBJECT_NAME_INVALID, "failed %s %lx\n", debugstr_w(nameW.Buffer), status );
4254 status = pNtCreateFile( &handle, GENERIC_READ, &attr, &io, NULL,
4255 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_CREATE,
4256 FILE_DIRECTORY_FILE, NULL, 0);
4257 ok( !status, "failed %s %lx\n", debugstr_w(nameW.Buffer), status );
4258 RemoveDirectoryW( path );
4261 static void test_read_write(void)
4263 static const char contents[14] = "1234567890abcd";
4264 char buf[256];
4265 HANDLE hfile, event;
4266 OVERLAPPED ovl;
4267 IO_STATUS_BLOCK iob;
4268 DWORD ret, bytes, status, off;
4269 LARGE_INTEGER offset;
4270 LONG i;
4272 event = CreateEventA( NULL, TRUE, FALSE, NULL );
4274 U(iob).Status = -1;
4275 iob.Information = -1;
4276 offset.QuadPart = 0;
4277 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4278 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4279 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4280 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4282 U(iob).Status = -1;
4283 iob.Information = -1;
4284 offset.QuadPart = 0;
4285 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, NULL, sizeof(buf), &offset, NULL);
4286 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4287 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4288 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4290 U(iob).Status = -1;
4291 iob.Information = -1;
4292 offset.QuadPart = 0;
4293 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4294 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4295 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4296 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4298 U(iob).Status = -1;
4299 iob.Information = -1;
4300 offset.QuadPart = 0;
4301 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4302 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4303 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4304 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4306 hfile = create_temp_file(0);
4307 if (!hfile) return;
4309 U(iob).Status = -1;
4310 iob.Information = -1;
4311 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4312 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#lx\n", status);
4313 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4314 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4316 U(iob).Status = -1;
4317 iob.Information = -1;
4318 SetEvent(event);
4319 status = pNtWriteFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4320 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#lx\n", status);
4321 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4322 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4323 ok(!is_signaled(event), "event is not signaled\n");
4325 U(iob).Status = -1;
4326 iob.Information = -1;
4327 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4328 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status);
4329 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4330 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4332 U(iob).Status = -1;
4333 iob.Information = -1;
4334 SetEvent(event);
4335 status = pNtReadFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4336 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status);
4337 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4338 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4339 ok(is_signaled(event), "event is not signaled\n");
4341 U(iob).Status = -1;
4342 iob.Information = -1;
4343 SetEvent(event);
4344 status = pNtReadFile(hfile, event, NULL, NULL, &iob, (void*)0xdeadbeef, sizeof(contents), NULL, NULL);
4345 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status);
4346 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4347 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4348 ok(is_signaled(event), "event is not signaled\n");
4350 U(iob).Status = -1;
4351 iob.Information = -1;
4352 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
4353 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
4354 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4355 ok(iob.Information == 7, "expected 7, got %Iu\n", iob.Information);
4357 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4359 U(iob).Status = -1;
4360 iob.Information = -1;
4361 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4362 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
4363 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
4364 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4365 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %Iu\n", iob.Information);
4367 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4368 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4370 bytes = 0xdeadbeef;
4371 SetLastError(0xdeadbeef);
4372 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
4373 ok(!ret, "ReadFile should fail\n");
4374 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
4375 ok(bytes == 0, "bytes %lu\n", bytes);
4377 bytes = 0xdeadbeef;
4378 SetLastError(0xdeadbeef);
4379 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
4380 ok(ret, "ReadFile error %ld\n", GetLastError());
4381 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4382 ok(bytes == 0, "bytes %lu\n", bytes);
4384 bytes = 0xdeadbeef;
4385 SetLastError(0xdeadbeef);
4386 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4387 ok(ret, "ReadFile error %ld\n", GetLastError());
4388 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4389 ok(bytes == 0, "bytes %lu\n", bytes);
4391 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4393 bytes = 0;
4394 SetLastError(0xdeadbeef);
4395 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4396 ok(ret, "ReadFile error %ld\n", GetLastError());
4397 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4398 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4400 for (i = -20; i < -1; i++)
4402 if (i == -2) continue;
4404 U(iob).Status = -1;
4405 iob.Information = -1;
4406 offset.QuadPart = (LONGLONG)i;
4407 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4408 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
4409 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4410 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
4413 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4415 U(iob).Status = -1;
4416 iob.Information = -1;
4417 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
4418 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4419 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
4420 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4421 ok(iob.Information == 4, "expected 4, got %Iu\n", iob.Information);
4423 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4424 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4426 U(iob).Status = -1;
4427 iob.Information = -1;
4428 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
4429 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
4430 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", U(iob).Status);
4431 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4433 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4435 bytes = 0;
4436 SetLastError(0xdeadbeef);
4437 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4438 ok(ret, "ReadFile error %ld\n", GetLastError());
4439 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4440 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4441 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4443 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4444 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4446 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4448 bytes = 0;
4449 SetLastError(0xdeadbeef);
4450 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
4451 ok(ret, "WriteFile error %ld\n", GetLastError());
4452 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4454 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4455 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4457 /* test reading beyond EOF */
4458 bytes = -1;
4459 SetLastError(0xdeadbeef);
4460 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4461 ok(ret, "ReadFile error %ld\n", GetLastError());
4462 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4463 ok(bytes == 0, "bytes %lu\n", bytes);
4465 bytes = -1;
4466 SetLastError(0xdeadbeef);
4467 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
4468 ok(ret, "ReadFile error %ld\n", GetLastError());
4469 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4470 ok(bytes == 0, "bytes %lu\n", bytes);
4472 bytes = -1;
4473 SetLastError(0xdeadbeef);
4474 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
4475 ok(ret, "ReadFile error %ld\n", GetLastError());
4476 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4477 ok(bytes == 0, "bytes %lu\n", bytes);
4479 S(U(ovl)).Offset = sizeof(contents);
4480 S(U(ovl)).OffsetHigh = 0;
4481 ovl.Internal = -1;
4482 ovl.InternalHigh = -1;
4483 ovl.hEvent = 0;
4484 bytes = -1;
4485 SetLastError(0xdeadbeef);
4486 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4487 ok(!ret, "ReadFile should fail\n");
4488 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %ld\n", GetLastError());
4489 ok(bytes == 0, "bytes %lu\n", bytes);
4490 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#Ix\n", ovl.Internal);
4491 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
4493 S(U(ovl)).Offset = sizeof(contents);
4494 S(U(ovl)).OffsetHigh = 0;
4495 ovl.Internal = -1;
4496 ovl.InternalHigh = -1;
4497 ovl.hEvent = 0;
4498 bytes = -1;
4499 SetLastError(0xdeadbeef);
4500 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
4501 ok(ret, "ReadFile error %ld\n", GetLastError());
4502 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4503 ok(bytes == 0, "bytes %lu\n", bytes);
4504 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4505 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
4507 U(iob).Status = -1;
4508 iob.Information = -1;
4509 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
4510 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
4511 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", U(iob).Status);
4512 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4514 U(iob).Status = -1;
4515 iob.Information = -1;
4516 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
4517 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
4518 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4519 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4521 U(iob).Status = -1;
4522 iob.Information = -1;
4523 offset.QuadPart = sizeof(contents);
4524 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4525 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
4526 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", U(iob).Status);
4527 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4529 U(iob).Status = -1;
4530 iob.Information = -1;
4531 offset.QuadPart = sizeof(contents);
4532 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4533 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
4534 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4535 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4537 U(iob).Status = -1;
4538 iob.Information = -1;
4539 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
4540 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4541 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
4542 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", U(iob).Status);
4543 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4545 U(iob).Status = -1;
4546 iob.Information = -1;
4547 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
4548 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4549 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
4550 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4551 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4553 for (i = -20; i < 0; i++)
4555 if (i == -2) continue;
4557 U(iob).Status = -1;
4558 iob.Information = -1;
4559 offset.QuadPart = (LONGLONG)i;
4560 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4561 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
4562 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4563 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
4566 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4568 bytes = 0;
4569 SetLastError(0xdeadbeef);
4570 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4571 ok(ret, "ReadFile error %ld\n", GetLastError());
4572 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4573 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4575 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4576 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4578 U(iob).Status = -1;
4579 iob.Information = -1;
4580 offset.QuadPart = 0;
4581 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4582 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
4583 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4584 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
4585 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4587 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4588 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4590 U(iob).Status = -1;
4591 iob.Information = -1;
4592 offset.QuadPart = sizeof(contents) - 4;
4593 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4594 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
4595 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4596 ok(iob.Information == 4, "expected 4, got %Iu\n", iob.Information);
4598 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4599 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4601 U(iob).Status = -1;
4602 iob.Information = -1;
4603 offset.QuadPart = 0;
4604 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4605 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
4606 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4607 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
4608 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4609 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4611 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4612 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4614 S(U(ovl)).Offset = sizeof(contents) - 4;
4615 S(U(ovl)).OffsetHigh = 0;
4616 ovl.hEvent = 0;
4617 bytes = 0;
4618 SetLastError(0xdeadbeef);
4619 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4620 ok(ret, "WriteFile error %ld\n", GetLastError());
4621 ok(bytes == 4, "bytes %lu\n", bytes);
4623 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4624 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4626 S(U(ovl)).Offset = 0;
4627 S(U(ovl)).OffsetHigh = 0;
4628 ovl.Internal = -1;
4629 ovl.InternalHigh = -1;
4630 ovl.hEvent = 0;
4631 bytes = 0;
4632 SetLastError(0xdeadbeef);
4633 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4634 ok(ret, "ReadFile error %ld\n", GetLastError());
4635 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4636 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4637 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
4638 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4639 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4641 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4642 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4644 CloseHandle(hfile);
4646 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
4647 if (!hfile) return;
4649 bytes = 0xdeadbeef;
4650 SetLastError(0xdeadbeef);
4651 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
4652 ok(!ret, "ReadFile should fail\n");
4653 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
4654 ok(bytes == 0, "bytes %lu\n", bytes);
4656 S(U(ovl)).Offset = 0;
4657 S(U(ovl)).OffsetHigh = 0;
4658 ovl.Internal = -1;
4659 ovl.InternalHigh = -1;
4660 ovl.hEvent = 0;
4661 bytes = 0xdeadbeef;
4662 SetLastError(0xdeadbeef);
4663 /* ReadFile return value depends on Windows version and testing it is not practical */
4664 ReadFile(hfile, buf, 0, &bytes, &ovl);
4665 ok(bytes == 0, "bytes %lu\n", bytes);
4666 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4667 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
4669 bytes = 0xdeadbeef;
4670 SetLastError(0xdeadbeef);
4671 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
4672 ok(!ret, "WriteFile should fail\n");
4673 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
4674 ok(bytes == 0, "bytes %lu\n", bytes);
4676 U(iob).Status = -1;
4677 iob.Information = -1;
4678 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
4679 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#lx\n", status);
4680 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4681 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
4683 for (i = -20; i < -1; i++)
4685 U(iob).Status = -1;
4686 iob.Information = -1;
4687 offset.QuadPart = (LONGLONG)i;
4688 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4689 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
4690 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4691 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
4694 U(iob).Status = -1;
4695 iob.Information = -1;
4696 offset.QuadPart = 0;
4697 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4698 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
4699 "expected STATUS_PENDING, got %#lx.\n", status);
4700 if (status == STATUS_PENDING)
4702 ret = WaitForSingleObject(hfile, 3000);
4703 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
4705 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4706 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
4708 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4709 ok(off == 0, "expected 0, got %lu\n", off);
4711 bytes = 0xdeadbeef;
4712 SetLastError(0xdeadbeef);
4713 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4714 ok(!ret, "ReadFile should fail\n");
4715 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
4716 ok(bytes == 0, "bytes %lu\n", bytes);
4718 U(iob).Status = -1;
4719 iob.Information = -1;
4720 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
4721 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#lx\n", status);
4722 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4723 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
4725 for (i = -20; i < 0; i++)
4727 U(iob).Status = -1;
4728 iob.Information = -1;
4729 offset.QuadPart = (LONGLONG)i;
4730 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4731 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
4732 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4733 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
4736 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4737 ok(off == 0, "expected 0, got %lu\n", off);
4739 /* test reading beyond EOF */
4740 offset.QuadPart = sizeof(contents);
4741 S(U(ovl)).Offset = offset.u.LowPart;
4742 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4743 ovl.Internal = -1;
4744 ovl.InternalHigh = -1;
4745 ovl.hEvent = 0;
4746 bytes = 0xdeadbeef;
4747 SetLastError(0xdeadbeef);
4748 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4749 ok(!ret, "ReadFile should fail\n");
4750 ret = GetLastError();
4751 ok(ret == ERROR_IO_PENDING || broken(ret == ERROR_HANDLE_EOF) /* before Vista */,
4752 "expected ERROR_IO_PENDING, got %ld\n", ret);
4753 ok(bytes == 0, "bytes %lu\n", bytes);
4755 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4756 ok(off == 0, "expected 0, got %lu\n", off);
4758 if (ret == ERROR_IO_PENDING)
4760 bytes = 0xdeadbeef;
4761 SetLastError(0xdeadbeef);
4762 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4763 ok(!ret, "GetOverlappedResult should report FALSE\n");
4764 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %ld\n", GetLastError());
4765 ok(bytes == 0, "expected 0, read %lu\n", bytes);
4766 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#Ix\n", ovl.Internal);
4767 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
4770 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4771 ok(off == 0, "expected 0, got %lu\n", off);
4773 offset.QuadPart = sizeof(contents);
4774 S(U(ovl)).Offset = offset.u.LowPart;
4775 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4776 ovl.Internal = -1;
4777 ovl.InternalHigh = -1;
4778 ovl.hEvent = 0;
4779 bytes = 0xdeadbeef;
4780 SetLastError(0xdeadbeef);
4781 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
4782 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
4783 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret, GetLastError());
4784 ret = GetLastError();
4785 ok(bytes == 0, "bytes %lu\n", bytes);
4787 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4788 ok(off == 0, "expected 0, got %lu\n", off);
4790 if (ret == ERROR_IO_PENDING)
4792 bytes = 0xdeadbeef;
4793 SetLastError(0xdeadbeef);
4794 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4795 ok(ret, "GetOverlappedResult returned FALSE with %lu (expected TRUE)\n", GetLastError());
4796 ok(bytes == 0, "expected 0, read %lu\n", bytes);
4797 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4798 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
4801 offset.QuadPart = sizeof(contents);
4802 S(U(ovl)).Offset = offset.u.LowPart;
4803 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4804 ovl.Internal = -1;
4805 ovl.InternalHigh = -1;
4806 ovl.hEvent = 0;
4807 bytes = 0xdeadbeef;
4808 SetLastError(0xdeadbeef);
4809 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
4810 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
4811 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret, GetLastError());
4812 ret = GetLastError();
4813 ok(bytes == 0, "bytes %lu\n", bytes);
4815 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4816 ok(off == 0, "expected 0, got %lu\n", off);
4818 if (ret == ERROR_IO_PENDING)
4820 bytes = 0xdeadbeef;
4821 SetLastError(0xdeadbeef);
4822 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4823 ok(ret, "GetOverlappedResult returned FALSE with %lu (expected TRUE)\n", GetLastError());
4824 ok(bytes == 0, "expected 0, read %lu\n", bytes);
4825 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4826 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
4829 U(iob).Status = -1;
4830 iob.Information = -1;
4831 offset.QuadPart = sizeof(contents);
4832 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4833 if (status == STATUS_PENDING)
4835 ret = WaitForSingleObject(hfile, 3000);
4836 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
4837 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", U(iob).Status);
4838 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4840 else
4842 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
4843 ok(U(iob).Status == -1, "expected -1, got %#lx\n", U(iob).Status);
4844 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4847 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4848 ok(off == 0, "expected 0, got %lu\n", off);
4850 U(iob).Status = -1;
4851 iob.Information = -1;
4852 offset.QuadPart = sizeof(contents);
4853 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4854 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
4855 "expected STATUS_PENDING, got %#lx.\n", status);
4856 if (status == STATUS_PENDING)
4858 ret = WaitForSingleObject(hfile, 3000);
4859 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
4860 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4861 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4863 else
4865 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4866 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4869 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4870 ok(off == 0, "expected 0, got %lu\n", off);
4872 S(U(ovl)).Offset = 0;
4873 S(U(ovl)).OffsetHigh = 0;
4874 ovl.Internal = -1;
4875 ovl.InternalHigh = -1;
4876 ovl.hEvent = 0;
4877 bytes = 0;
4878 SetLastError(0xdeadbeef);
4879 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4880 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
4881 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret, GetLastError());
4882 if (!ret)
4883 ok(bytes == 0, "bytes %lu\n", bytes);
4884 else
4885 ok(bytes == 14, "bytes %lu\n", bytes);
4886 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4887 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
4889 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4890 ok(off == 0, "expected 0, got %lu\n", off);
4892 bytes = 0xdeadbeef;
4893 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4894 ok(ret, "GetOverlappedResult error %ld\n", GetLastError());
4895 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4896 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4897 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
4898 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4900 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4901 ok(off == 0, "expected 0, got %lu\n", off);
4903 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4904 SetEndOfFile(hfile);
4905 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4907 U(iob).Status = -1;
4908 iob.Information = -1;
4909 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4910 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4911 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
4912 "expected STATUS_PENDING, got %#lx.\n", status);
4913 if (status == STATUS_PENDING)
4915 ret = WaitForSingleObject(hfile, 3000);
4916 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
4918 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4919 ok(iob.Information == 4, "expected 4, got %Iu\n", iob.Information);
4921 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4922 ok(off == 0, "expected 0, got %lu\n", off);
4924 U(iob).Status = -1;
4925 iob.Information = -1;
4926 offset.QuadPart = 0;
4927 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4928 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
4929 "expected STATUS_PENDING, got %#lx.\n", status);
4930 if (status == STATUS_PENDING)
4932 ret = WaitForSingleObject(hfile, 3000);
4933 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
4935 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", U(iob).Status);
4936 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
4938 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4939 ok(off == 0, "expected 0, got %lu\n", off);
4941 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4942 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4944 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4945 ok(off == 0, "expected 0, got %lu\n", off);
4947 S(U(ovl)).Offset = sizeof(contents) - 4;
4948 S(U(ovl)).OffsetHigh = 0;
4949 ovl.Internal = -1;
4950 ovl.InternalHigh = -1;
4951 ovl.hEvent = 0;
4952 bytes = 0;
4953 SetLastError(0xdeadbeef);
4954 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4955 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
4956 "Unexpected result %#lx, GetLastError() %lu.\n", ret, GetLastError());
4957 if (!ret)
4959 ok(bytes == 0, "bytes %lu\n", bytes);
4960 ret = WaitForSingleObject(hfile, 3000);
4961 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
4963 else ok(bytes == 4, "bytes %lu\n", bytes);
4964 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4965 ok(ovl.InternalHigh == 4, "expected 4, got %Iu\n", ovl.InternalHigh);
4967 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4968 ok(off == 0, "expected 0, got %lu\n", off);
4970 bytes = 0xdeadbeef;
4971 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4972 ok(ret, "GetOverlappedResult error %ld\n", GetLastError());
4973 ok(bytes == 4, "bytes %lu\n", bytes);
4974 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4975 ok(ovl.InternalHigh == 4, "expected 4, got %Iu\n", ovl.InternalHigh);
4977 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4978 ok(off == 0, "expected 0, got %lu\n", off);
4980 S(U(ovl)).Offset = 0;
4981 S(U(ovl)).OffsetHigh = 0;
4982 ovl.Internal = -1;
4983 ovl.InternalHigh = -1;
4984 ovl.hEvent = 0;
4985 bytes = 0;
4986 SetLastError(0xdeadbeef);
4987 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4988 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
4989 "Unexpected result %#lx, GetLastError() %lu.\n", ret, GetLastError());
4990 if (!ret)
4992 ok(bytes == 0, "bytes %lu\n", bytes);
4993 ret = WaitForSingleObject(hfile, 3000);
4994 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
4996 else ok(bytes == 14, "bytes %lu\n", bytes);
4997 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
4998 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
5000 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5001 ok(off == 0, "expected 0, got %lu\n", off);
5003 bytes = 0xdeadbeef;
5004 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
5005 ok(ret, "GetOverlappedResult error %ld\n", GetLastError());
5006 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
5007 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5008 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
5009 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
5010 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
5012 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5013 ok(off == 0, "expected 0, got %lu\n", off);
5015 CloseHandle(event);
5016 CloseHandle(hfile);
5019 static void test_ioctl(void)
5021 HANDLE event = CreateEventA(NULL, TRUE, FALSE, NULL);
5022 FILE_PIPE_PEEK_BUFFER peek_buf;
5023 IO_STATUS_BLOCK iosb;
5024 HANDLE file;
5025 NTSTATUS status;
5027 file = create_temp_file(FILE_FLAG_OVERLAPPED);
5028 ok(file != INVALID_HANDLE_VALUE, "could not create temp file\n");
5030 SetEvent(event);
5031 status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
5032 todo_wine
5033 ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile returned %lx\n", status);
5034 ok(!is_signaled(event), "event is signaled\n");
5036 status = pNtFsControlFile(file, (HANDLE)0xdeadbeef, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
5037 ok(status == STATUS_INVALID_HANDLE, "NtFsControlFile returned %lx\n", status);
5039 memset(&iosb, 0x55, sizeof(iosb));
5040 status = pNtFsControlFile(file, NULL, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0,
5041 &peek_buf, sizeof(peek_buf));
5042 todo_wine
5043 ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile failed: %lx\n", status);
5044 ok(iosb.Status == 0x55555555, "iosb.Status = %lx\n", iosb.Status);
5046 CloseHandle(event);
5047 CloseHandle(file);
5050 static void test_flush_buffers_file(void)
5052 char path[MAX_PATH], buffer[MAX_PATH];
5053 HANDLE hfile, hfileread;
5054 NTSTATUS status;
5055 IO_STATUS_BLOCK io_status_block;
5057 GetTempPathA(MAX_PATH, path);
5058 GetTempFileNameA(path, "foo", 0, buffer);
5059 hfile = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
5060 FILE_ATTRIBUTE_NORMAL, 0);
5061 ok(hfile != INVALID_HANDLE_VALUE, "failed to create temp file.\n" );
5063 hfileread = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
5064 OPEN_EXISTING, 0, NULL);
5065 ok(hfileread != INVALID_HANDLE_VALUE, "could not open temp file, error %ld.\n", GetLastError());
5067 status = pNtFlushBuffersFile(hfile, NULL);
5068 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx.\n", status);
5070 status = pNtFlushBuffersFile(hfile, (IO_STATUS_BLOCK *)0xdeadbeaf);
5071 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx.\n", status);
5073 io_status_block.Information = 0xdeadbeef;
5074 io_status_block.Status = 0xdeadbeef;
5075 status = pNtFlushBuffersFile(hfile, &io_status_block);
5076 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5077 ok(io_status_block.Status == STATUS_SUCCESS, "Got unexpected io_status_block.Status %#lx.\n",
5078 io_status_block.Status);
5079 ok(!io_status_block.Information, "Got unexpected io_status_block.Information %#Ix.\n",
5080 io_status_block.Information);
5082 status = pNtFlushBuffersFile(hfileread, &io_status_block);
5083 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status);
5085 io_status_block.Information = 0xdeadbeef;
5086 io_status_block.Status = 0xdeadbeef;
5087 status = pNtFlushBuffersFile(NULL, &io_status_block);
5088 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#lx.\n", status);
5089 ok(io_status_block.Status == 0xdeadbeef, "Got unexpected io_status_block.Status %#lx.\n",
5090 io_status_block.Status);
5091 ok(io_status_block.Information == 0xdeadbeef, "Got unexpected io_status_block.Information %#Ix.\n",
5092 io_status_block.Information);
5094 CloseHandle(hfileread);
5095 CloseHandle(hfile);
5096 hfile = CreateFileA(buffer, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
5097 OPEN_EXISTING, 0, NULL);
5098 ok(hfile != INVALID_HANDLE_VALUE, "could not open temp file, error %ld.\n", GetLastError());
5100 status = pNtFlushBuffersFile(hfile, &io_status_block);
5101 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5103 io_status_block.Information = 0xdeadbeef;
5104 io_status_block.Status = 0xdeadbeef;
5105 status = pNtFlushBuffersFile((HANDLE)0xdeadbeef, &io_status_block);
5106 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#lx.\n", status);
5107 ok(io_status_block.Status == 0xdeadbeef, "Got unexpected io_status_block.Status %#lx.\n",
5108 io_status_block.Status);
5109 ok(io_status_block.Information == 0xdeadbeef, "Got unexpected io_status_block.Information %#Ix.\n",
5110 io_status_block.Information);
5112 CloseHandle(hfile);
5113 DeleteFileA(buffer);
5116 static void test_query_ea(void)
5118 #define EA_BUFFER_SIZE 4097
5119 unsigned char data[EA_BUFFER_SIZE + 8];
5120 unsigned char *buffer = (void *)(((DWORD_PTR)data + 7) & ~7);
5121 DWORD buffer_len, i;
5122 IO_STATUS_BLOCK io;
5123 NTSTATUS status;
5124 HANDLE handle;
5126 if (!(handle = create_temp_file(0))) return;
5128 /* test with INVALID_HANDLE_VALUE */
5129 U(io).Status = 0xdeadbeef;
5130 io.Information = 0xdeadbeef;
5131 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5132 buffer_len = EA_BUFFER_SIZE - 1;
5133 status = pNtQueryEaFile(INVALID_HANDLE_VALUE, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5134 ok(status == STATUS_OBJECT_TYPE_MISMATCH, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
5135 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", U(io).Status);
5136 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5137 ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
5139 /* test with 0xdeadbeef */
5140 U(io).Status = 0xdeadbeef;
5141 io.Information = 0xdeadbeef;
5142 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5143 buffer_len = EA_BUFFER_SIZE - 1;
5144 status = pNtQueryEaFile((void *)0xdeadbeef, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5145 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#lx\n", status);
5146 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", U(io).Status);
5147 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5148 ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
5150 /* test without buffer */
5151 U(io).Status = 0xdeadbeef;
5152 io.Information = 0xdeadbeef;
5153 status = pNtQueryEaFile(handle, &io, NULL, 0, TRUE, NULL, 0, NULL, FALSE);
5154 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5155 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", U(io).Status);
5156 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5158 /* test with zero buffer */
5159 U(io).Status = 0xdeadbeef;
5160 io.Information = 0xdeadbeef;
5161 status = pNtQueryEaFile(handle, &io, buffer, 0, TRUE, NULL, 0, NULL, FALSE);
5162 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5163 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", U(io).Status);
5164 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5166 /* test with very small buffer */
5167 U(io).Status = 0xdeadbeef;
5168 io.Information = 0xdeadbeef;
5169 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5170 buffer_len = 4;
5171 status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5172 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5173 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", U(io).Status);
5174 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5175 for (i = 0; i < buffer_len && !buffer[i]; i++);
5176 ok(i == buffer_len, "expected %lu bytes filled with 0x00, got %lu bytes\n", buffer_len, i);
5177 ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
5179 /* test with very big buffer */
5180 U(io).Status = 0xdeadbeef;
5181 io.Information = 0xdeadbeef;
5182 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5183 buffer_len = EA_BUFFER_SIZE - 1;
5184 status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5185 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5186 ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", U(io).Status);
5187 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5188 for (i = 0; i < buffer_len && !buffer[i]; i++);
5189 ok(i == buffer_len, "expected %lu bytes filled with 0x00, got %lu bytes\n", buffer_len, i);
5190 ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
5192 CloseHandle(handle);
5193 #undef EA_BUFFER_SIZE
5196 static void test_file_readonly_access(void)
5198 static const DWORD default_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
5199 static const WCHAR fooW[] = {'f', 'o', 'o', 0};
5200 WCHAR path[MAX_PATH];
5201 OBJECT_ATTRIBUTES attr;
5202 UNICODE_STRING nameW;
5203 IO_STATUS_BLOCK io;
5204 HANDLE handle;
5205 NTSTATUS status;
5206 DWORD ret;
5208 /* Set up */
5209 GetTempPathW(MAX_PATH, path);
5210 GetTempFileNameW(path, fooW, 0, path);
5211 DeleteFileW(path);
5212 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
5214 attr.Length = sizeof(attr);
5215 attr.RootDirectory = NULL;
5216 attr.ObjectName = &nameW;
5217 attr.Attributes = OBJ_CASE_INSENSITIVE;
5218 attr.SecurityDescriptor = NULL;
5219 attr.SecurityQualityOfService = NULL;
5221 status = pNtCreateFile(&handle, FILE_GENERIC_WRITE, &attr, &io, NULL, FILE_ATTRIBUTE_READONLY, default_sharing,
5222 FILE_CREATE, 0, NULL, 0);
5223 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5224 CloseHandle(handle);
5226 /* NtCreateFile FILE_GENERIC_WRITE */
5227 status = pNtCreateFile(&handle, FILE_GENERIC_WRITE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, default_sharing,
5228 FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
5229 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status);
5231 /* NtCreateFile DELETE without FILE_DELETE_ON_CLOSE */
5232 status = pNtCreateFile(&handle, DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, default_sharing, FILE_OPEN,
5233 FILE_NON_DIRECTORY_FILE, NULL, 0);
5234 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5235 CloseHandle(handle);
5237 /* NtCreateFile DELETE with FILE_DELETE_ON_CLOSE */
5238 status = pNtCreateFile(&handle, SYNCHRONIZE | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, default_sharing,
5239 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0);
5240 ok(status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %#lx.\n", status);
5242 /* NtOpenFile GENERIC_WRITE */
5243 status = pNtOpenFile(&handle, GENERIC_WRITE, &attr, &io, default_sharing, FILE_NON_DIRECTORY_FILE);
5244 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status);
5246 /* NtOpenFile DELETE without FILE_DELETE_ON_CLOSE */
5247 status = pNtOpenFile(&handle, DELETE, &attr, &io, default_sharing, FILE_NON_DIRECTORY_FILE);
5248 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5249 CloseHandle(handle);
5251 /* NtOpenFile DELETE with FILE_DELETE_ON_CLOSE */
5252 status = pNtOpenFile(&handle, DELETE, &attr, &io, default_sharing, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE);
5253 ok(status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %#lx.\n", status);
5255 ret = GetFileAttributesW(path);
5256 ok(ret & FILE_ATTRIBUTE_READONLY, "got wrong attribute: %#lx.\n", ret);
5258 /* Clean up */
5259 pRtlFreeUnicodeString(&nameW);
5260 SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL);
5261 DeleteFileW(path);
5264 static void test_mailslot_name(void)
5266 char buffer[1024] = {0};
5267 const FILE_NAME_INFORMATION *name = (const FILE_NAME_INFORMATION *)buffer;
5268 HANDLE server, client, device;
5269 IO_STATUS_BLOCK io;
5270 NTSTATUS ret;
5272 server = CreateMailslotA( "\\\\.\\mailslot\\winetest", 100, 1000, NULL );
5273 ok(server != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
5275 ret = NtQueryInformationFile( server, &io, buffer, 0, FileNameInformation );
5276 ok(ret == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", ret);
5278 memset(buffer, 0xcc, sizeof(buffer));
5279 ret = NtQueryInformationFile( server, &io, buffer,
5280 offsetof(FILE_NAME_INFORMATION, FileName[5]), FileNameInformation );
5281 todo_wine ok(ret == STATUS_BUFFER_OVERFLOW, "got %#lx\n", ret);
5282 if (ret == STATUS_BUFFER_OVERFLOW)
5284 ok(name->FileNameLength == 18, "got length %lu\n", name->FileNameLength);
5285 ok(!memcmp(name->FileName, L"\\wine", 10), "got %s\n",
5286 debugstr_wn(name->FileName, name->FileNameLength / sizeof(WCHAR)));
5289 memset(buffer, 0xcc, sizeof(buffer));
5290 ret = NtQueryInformationFile( server, &io, buffer, sizeof(buffer), FileNameInformation );
5291 todo_wine ok(!ret, "got %#lx\n", ret);
5292 if (!ret)
5294 ok(name->FileNameLength == 18, "got length %lu\n", name->FileNameLength);
5295 ok(!memcmp(name->FileName, L"\\winetest", 18), "got %s\n",
5296 debugstr_wn(name->FileName, name->FileNameLength / sizeof(WCHAR)));
5299 client = CreateFileA( "\\\\.\\mailslot\\winetest", 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
5300 ok(client != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
5302 ret = NtQueryInformationFile( client, &io, buffer, 0, FileNameInformation );
5303 ok(ret == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", ret);
5305 ret = NtQueryInformationFile( client, &io, buffer, sizeof(buffer), FileNameInformation );
5306 todo_wine ok(ret == STATUS_INVALID_PARAMETER || !ret /* win8+ */, "got %#lx\n", ret);
5307 if (!ret)
5309 ok(name->FileNameLength == 18, "got length %lu\n", name->FileNameLength);
5310 ok(!memcmp(name->FileName, L"\\winetest", 18), "got %s\n",
5311 debugstr_wn(name->FileName, name->FileNameLength / sizeof(WCHAR)));
5314 CloseHandle( server );
5315 CloseHandle( client );
5317 device = CreateFileA("\\\\.\\mailslot", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
5318 ok(device != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
5320 ret = NtQueryInformationFile( device, &io, buffer, 0, FileNameInformation );
5321 ok(ret == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", ret);
5323 ret = NtQueryInformationFile( device, &io, buffer, sizeof(buffer), FileNameInformation );
5324 todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret);
5326 CloseHandle( device );
5329 START_TEST(file)
5331 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
5332 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
5333 if (!hntdll)
5335 skip("not running on NT, skipping test\n");
5336 return;
5339 pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
5340 pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
5342 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
5343 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
5344 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
5345 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
5346 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
5347 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
5348 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
5349 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
5350 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
5351 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
5352 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
5353 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
5354 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
5355 pNtFsControlFile = (void *)GetProcAddress(hntdll, "NtFsControlFile");
5356 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
5357 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
5358 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
5359 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
5360 pNtRemoveIoCompletionEx = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletionEx");
5361 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
5362 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
5363 pNtQueryAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryAttributesFile");
5364 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
5365 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
5366 pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
5367 pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
5368 pNtFlushBuffersFile = (void *)GetProcAddress(hntdll, "NtFlushBuffersFile");
5369 pNtQueryEaFile = (void *)GetProcAddress(hntdll, "NtQueryEaFile");
5371 test_read_write();
5372 test_NtCreateFile();
5373 create_file_test();
5374 open_file_test();
5375 delete_file_test();
5376 read_file_test();
5377 append_file_test();
5378 nt_mailslot_test();
5379 test_set_io_completion();
5380 test_file_io_completion();
5381 test_file_basic_information();
5382 test_file_all_information();
5383 test_file_both_information();
5384 test_file_name_information();
5385 test_file_full_size_information();
5386 test_file_all_name_information();
5387 test_file_rename_information();
5388 test_file_link_information();
5389 test_file_disposition_information();
5390 test_file_completion_information();
5391 test_file_id_information();
5392 test_file_access_information();
5393 test_file_attribute_tag_information();
5394 test_file_mode();
5395 test_file_readonly_access();
5396 test_query_volume_information_file();
5397 test_query_attribute_information_file();
5398 test_ioctl();
5399 test_query_ea();
5400 test_flush_buffers_file();
5401 test_mailslot_name();