include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / ntdll / tests / file.c
blob7d3618a38043c224ecff73457b7ade26bba2c552
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, 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 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( io.Status == STATUS_INVALID_DEVICE_REQUEST,
181 "expected STATUS_INVALID_DEVICE_REQUEST, got %08lx\n", io.Status );
184 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( io.Status == STATUS_INVALID_DEVICE_REQUEST,
194 "expected STATUS_INVALID_DEVICE_REQUEST, got %08lx\n", 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"\\" );
418 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
419 status = NtOpenFile( &handle, FILE_LIST_DIRECTORY | SYNCHRONIZE, &attr, &io,
420 FILE_SHARE_READ | FILE_SHARE_WRITE,
421 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT );
422 ok( status == STATUS_NOT_A_DIRECTORY, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
423 CloseHandle( handle );
424 pRtlFreeUnicodeString( &nameW );
426 wcscat( path, L"\\cmd.exe" );
427 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
428 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
429 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
430 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
431 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
432 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE );
433 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
434 pRtlFreeUnicodeString( &nameW );
436 GetTempPathW( MAX_PATH, path );
437 lstrcatW( path, testdirW );
438 CreateDirectoryW( path, NULL );
440 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
441 attr.RootDirectory = NULL;
442 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
443 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
444 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
445 pRtlFreeUnicodeString( &nameW );
447 GetTempFileNameW( path, fooW, 0, tmpfile );
448 file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
449 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError() );
450 numbytes = 0xdeadbeef;
451 ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
452 ok( ret, "WriteFile failed with error %lu\n", GetLastError() );
453 ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
454 CloseHandle( file );
456 /* try open by file id */
458 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
459 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
461 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
463 restart = FALSE;
465 if (!info->FileId.QuadPart) continue;
467 nameW.Buffer = (WCHAR *)&info->FileId;
468 nameW.Length = sizeof(info->FileId);
469 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
470 attr.RootDirectory = dir;
471 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
472 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
473 FILE_SHARE_READ,
474 FILE_OPEN_BY_FILE_ID |
475 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
476 ok( status == STATUS_SUCCESS, "open %s failed %lx\n", wine_dbgstr_w(info->FileName), status );
477 if (!status)
479 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
481 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
483 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
485 /* check that it's the same file/directory */
487 /* don't check the size for directories */
488 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
489 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
490 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
492 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
493 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
495 CloseHandle( handle );
497 /* try same thing from drive root */
498 attr.RootDirectory = root;
499 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
500 FILE_SHARE_READ|FILE_SHARE_WRITE,
501 FILE_OPEN_BY_FILE_ID |
502 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
503 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
504 "open %s failed %lx\n", wine_dbgstr_w(info->FileName), status );
505 if (!status) CloseHandle( handle );
509 CloseHandle( dir );
510 CloseHandle( root );
512 pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
513 attr.Length = sizeof(attr);
514 attr.RootDirectory = 0;
515 attr.ObjectName = &nameW;
516 attr.Attributes = OBJ_CASE_INSENSITIVE;
517 attr.SecurityDescriptor = NULL;
518 attr.SecurityQualityOfService = NULL;
519 status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
520 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
521 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
522 pRtlFreeUnicodeString( &nameW );
524 numbytes = 0xdeadbeef;
525 memset( data, 0, sizeof(data) );
526 ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
527 ok( ret, "ReadFile failed with error %lu\n", GetLastError() );
528 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
529 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
531 nameW.Length = sizeof(fooW) - sizeof(WCHAR);
532 nameW.Buffer = fooW;
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 == STATUS_OBJECT_PATH_NOT_FOUND,
538 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08lx\n", status );
540 nameW.Length = 0;
541 nameW.Buffer = NULL;
542 attr.RootDirectory = file;
543 attr.ObjectName = &nameW;
544 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
545 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
546 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(tmpfile), status );
548 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
549 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %lu\n", numbytes );
550 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
551 ok( numbytes == 0, "SetFilePointer returned %lu\n", numbytes );
553 numbytes = 0xdeadbeef;
554 memset( data, 0, sizeof(data) );
555 ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
556 ok( ret, "ReadFile failed with error %lu\n", GetLastError() );
557 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
558 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
560 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
561 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %lu\n", numbytes );
562 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
563 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %lu\n", numbytes );
565 CloseHandle( file );
566 CloseHandle( root );
567 DeleteFileW( tmpfile );
568 RemoveDirectoryW( path );
571 static void delete_file_test(void)
573 NTSTATUS ret;
574 OBJECT_ATTRIBUTES attr;
575 UNICODE_STRING nameW;
576 WCHAR pathW[MAX_PATH];
577 WCHAR pathsubW[MAX_PATH];
578 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
579 static const WCHAR subdirW[] = {'\\','s','u','b',0};
581 ret = GetTempPathW(MAX_PATH, pathW);
582 if (!ret)
584 ok(0, "couldn't get temp dir\n");
585 return;
587 if (ret + ARRAY_SIZE(testdirW)-1 + ARRAY_SIZE(subdirW)-1 >= MAX_PATH)
589 ok(0, "MAX_PATH exceeded in constructing paths\n");
590 return;
593 lstrcatW(pathW, testdirW);
594 lstrcpyW(pathsubW, pathW);
595 lstrcatW(pathsubW, subdirW);
597 ret = CreateDirectoryW(pathW, NULL);
598 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
599 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
601 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
602 return;
605 attr.Length = sizeof(attr);
606 attr.RootDirectory = 0;
607 attr.Attributes = OBJ_CASE_INSENSITIVE;
608 attr.ObjectName = &nameW;
609 attr.SecurityDescriptor = NULL;
610 attr.SecurityQualityOfService = NULL;
612 /* test NtDeleteFile on an empty directory */
613 ret = pNtDeleteFile(&attr);
614 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
615 ret = RemoveDirectoryW(pathW);
616 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
618 /* test NtDeleteFile on a non-empty directory */
619 ret = CreateDirectoryW(pathW, NULL);
620 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
621 ret = CreateDirectoryW(pathsubW, NULL);
622 ok(ret == TRUE, "couldn't create directory subdir\n");
623 ret = pNtDeleteFile(&attr);
624 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
625 ret = RemoveDirectoryW(pathsubW);
626 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
627 ret = RemoveDirectoryW(pathW);
628 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
630 pRtlFreeUnicodeString( &nameW );
633 #define TEST_OVERLAPPED_READ_SIZE 4096
635 static void read_file_test(void)
637 DECLSPEC_ALIGN(TEST_OVERLAPPED_READ_SIZE) static unsigned char aligned_buffer[TEST_OVERLAPPED_READ_SIZE];
638 const char text[] = "foobar";
639 HANDLE handle;
640 IO_STATUS_BLOCK iosb;
641 NTSTATUS status;
642 int apc_count = 0;
643 char buffer[128];
644 LARGE_INTEGER offset;
645 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
647 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
648 apc_count = 0;
649 iosb.Status = 0xdeadbabe;
650 iosb.Information = 0xdeadbeef;
651 offset.QuadPart = 0;
652 ResetEvent( event );
653 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
654 ok( status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
655 "wrong status %lx.\n", status );
656 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
657 ok( iosb.Status == STATUS_SUCCESS, "wrong status %lx\n", iosb.Status );
658 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
659 ok( is_signaled( event ), "event is not signaled\n" );
660 ok( !apc_count, "apc was called\n" );
661 SleepEx( 1, TRUE ); /* alertable sleep */
662 ok( apc_count == 1, "apc was not called\n" );
664 apc_count = 0;
665 iosb.Status = 0xdeadbabe;
666 iosb.Information = 0xdeadbeef;
667 offset.QuadPart = 0;
668 ResetEvent( event );
669 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
670 ok(status == STATUS_PENDING
671 || broken(status == STATUS_SUCCESS) /* before Vista */,
672 "wrong status %lx.\n", status);
673 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
674 ok( iosb.Status == STATUS_SUCCESS, "wrong status %lx\n", iosb.Status );
675 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
676 ok( is_signaled( event ), "event is not signaled\n" );
677 ok( !apc_count, "apc was called\n" );
678 SleepEx( 1, TRUE ); /* alertable sleep */
679 ok( apc_count == 1, "apc was not called\n" );
681 /* read beyond eof */
682 apc_count = 0;
683 iosb.Status = 0xdeadbabe;
684 iosb.Information = 0xdeadbeef;
685 offset.QuadPart = strlen(text) + 2;
686 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
687 ok(status == STATUS_PENDING || broken(status == STATUS_END_OF_FILE) /* before Vista */,
688 "expected STATUS_PENDING, got %#lx\n", status);
689 if (status == STATUS_PENDING) /* vista */
691 WaitForSingleObject( event, 1000 );
692 ok( iosb.Status == STATUS_END_OF_FILE, "wrong status %lx\n", iosb.Status );
693 ok( iosb.Information == 0, "wrong info %Iu\n", iosb.Information );
694 ok( is_signaled( event ), "event is not signaled\n" );
695 ok( !apc_count, "apc was called\n" );
696 SleepEx( 1, TRUE ); /* alertable sleep */
697 ok( apc_count == 1, "apc was not called\n" );
699 CloseHandle( handle );
701 /* now a non-overlapped file */
702 if (!(handle = create_temp_file(0))) return;
703 apc_count = 0;
704 iosb.Status = 0xdeadbabe;
705 iosb.Information = 0xdeadbeef;
706 offset.QuadPart = 0;
707 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
708 ok( status == STATUS_END_OF_FILE ||
709 status == STATUS_SUCCESS ||
710 status == STATUS_PENDING, /* vista */
711 "wrong status %lx\n", status );
712 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
713 ok( iosb.Status == STATUS_SUCCESS, "wrong status %lx\n", iosb.Status );
714 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
715 ok( is_signaled( event ), "event is not signaled\n" );
716 ok( !apc_count, "apc was called\n" );
717 SleepEx( 1, TRUE ); /* alertable sleep */
718 ok( apc_count == 1, "apc was not called\n" );
720 apc_count = 0;
721 iosb.Status = 0xdeadbabe;
722 iosb.Information = 0xdeadbeef;
723 offset.QuadPart = 0;
724 ResetEvent( event );
725 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
726 ok( status == STATUS_SUCCESS, "wrong status %lx\n", status );
727 ok( iosb.Status == STATUS_SUCCESS, "wrong status %lx\n", iosb.Status );
728 ok( iosb.Information == strlen(text), "wrong info %Iu\n", iosb.Information );
729 ok( is_signaled( event ), "event is not signaled\n" );
730 ok( !apc_count, "apc was called\n" );
731 SleepEx( 1, TRUE ); /* alertable sleep */
732 todo_wine ok( !apc_count, "apc was called\n" );
734 /* read beyond eof */
735 apc_count = 0;
736 iosb.Status = 0xdeadbabe;
737 iosb.Information = 0xdeadbeef;
738 offset.QuadPart = strlen(text) + 2;
739 ResetEvent( event );
740 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
741 ok( status == STATUS_END_OF_FILE, "wrong status %lx\n", status );
742 ok( iosb.Status == STATUS_END_OF_FILE, "wrong status %lx\n", iosb.Status );
743 ok( iosb.Information == 0, "wrong info %Iu\n", iosb.Information );
744 ok( is_signaled( event ), "event is not signaled\n" );
745 ok( !apc_count, "apc was called\n" );
746 SleepEx( 1, TRUE ); /* alertable sleep */
747 ok( !apc_count, "apc was called\n" );
749 CloseHandle( handle );
751 if (!(handle = create_temp_file(FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING)))
752 return;
754 apc_count = 0;
755 offset.QuadPart = 0;
756 iosb.Status = 0xdeadbabe;
757 iosb.Information = 0xdeadbeef;
758 offset.QuadPart = 0;
759 ResetEvent(event);
760 status = pNtWriteFile(handle, event, apc, &apc_count, &iosb,
761 aligned_buffer, sizeof(aligned_buffer), &offset, NULL);
762 ok(status == STATUS_END_OF_FILE || status == STATUS_PENDING
763 || broken(status == STATUS_SUCCESS) /* before Vista */,
764 "Wrong status %lx.\n", status);
765 ok(iosb.Status == STATUS_SUCCESS, "Wrong status %lx.\n", iosb.Status);
766 ok(iosb.Information == sizeof(aligned_buffer), "Wrong info %Iu.\n", iosb.Information);
767 ok(is_signaled(event), "event is not signaled.\n");
768 ok(!apc_count, "apc was called.\n");
769 SleepEx(1, TRUE); /* alertable sleep */
770 ok(apc_count == 1, "apc was not called.\n");
772 apc_count = 0;
773 offset.QuadPart = 0;
774 iosb.Status = 0xdeadbabe;
775 iosb.Information = 0xdeadbeef;
776 offset.QuadPart = 0;
777 ResetEvent(event);
778 status = pNtReadFile(handle, event, apc, &apc_count, &iosb,
779 aligned_buffer, sizeof(aligned_buffer), &offset, NULL);
780 ok(status == STATUS_PENDING, "Wrong status %lx.\n", status);
781 WaitForSingleObject(event, 1000);
782 ok(iosb.Status == STATUS_SUCCESS, "Wrong status %lx.\n", iosb.Status);
783 ok(iosb.Information == sizeof(aligned_buffer), "Wrong info %Iu.\n", iosb.Information);
784 ok(is_signaled(event), "event is not signaled.\n");
785 ok(!apc_count, "apc was called.\n");
786 SleepEx(1, TRUE); /* alertable sleep */
787 ok(apc_count == 1, "apc was not called.\n");
789 CloseHandle(handle);
790 CloseHandle(event);
793 static void append_file_test(void)
795 static const char text[6] = "foobar";
796 HANDLE handle;
797 NTSTATUS status;
798 IO_STATUS_BLOCK iosb;
799 LARGE_INTEGER offset;
800 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
801 DWORD ret;
803 GetTempPathA( MAX_PATH, path );
804 GetTempFileNameA( path, "foo", 0, buffer );
806 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
807 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
809 iosb.Status = -1;
810 iosb.Information = -1;
811 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
812 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
813 ok(iosb.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iosb.Status);
814 ok(iosb.Information == 2, "expected 2, got %Iu\n", iosb.Information);
816 CloseHandle(handle);
818 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
819 It matches the O_WRONLY|O_APPEND open() posix behavior */
820 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
821 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
823 iosb.Status = -1;
824 iosb.Information = -1;
825 offset.QuadPart = 1;
826 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
827 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
828 ok(iosb.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iosb.Status);
829 ok(iosb.Information == 2, "expected 2, got %Iu\n", iosb.Information);
831 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
832 ok(ret == 4, "expected 4, got %lu\n", ret);
834 iosb.Status = -1;
835 iosb.Information = -1;
836 offset.QuadPart = 3;
837 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
838 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
839 ok(iosb.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iosb.Status);
840 ok(iosb.Information == 2, "expected 2, got %Iu\n", iosb.Information);
842 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
843 ok(ret == 6, "expected 6, got %lu\n", ret);
845 CloseHandle(handle);
847 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
848 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
850 memset(buf, 0, sizeof(buf));
851 iosb.Status = -1;
852 iosb.Information = -1;
853 offset.QuadPart = 0;
854 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
855 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
856 ok(iosb.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iosb.Status);
857 ok(iosb.Information == 6, "expected 6, got %Iu\n", iosb.Information);
858 buf[6] = 0;
859 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
861 iosb.Status = -1;
862 iosb.Information = -1;
863 offset.QuadPart = 0;
864 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
865 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
866 ok(iosb.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iosb.Status);
867 ok(iosb.Information == 3, "expected 3, got %Iu\n", iosb.Information);
869 memset(buf, 0, sizeof(buf));
870 iosb.Status = -1;
871 iosb.Information = -1;
872 offset.QuadPart = 0;
873 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
874 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
875 ok(iosb.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iosb.Status);
876 ok(iosb.Information == 6, "expected 6, got %Iu\n", iosb.Information);
877 buf[6] = 0;
878 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
880 CloseHandle(handle);
881 DeleteFileA(buffer);
884 static void nt_mailslot_test(void)
886 HANDLE hslot;
887 ACCESS_MASK DesiredAccess;
888 OBJECT_ATTRIBUTES attr;
890 ULONG CreateOptions;
891 ULONG MailslotQuota;
892 ULONG MaxMessageSize;
893 LARGE_INTEGER TimeOut;
894 IO_STATUS_BLOCK IoStatusBlock;
895 NTSTATUS rc;
896 UNICODE_STRING str;
897 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
898 'R',':','\\','F','R','E','D','\0' };
900 TimeOut.QuadPart = -1;
902 pRtlInitUnicodeString(&str, buffer1);
903 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
904 CreateOptions = MailslotQuota = MaxMessageSize = 0;
905 DesiredAccess = GENERIC_READ;
908 * Check for NULL pointer handling
910 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
911 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
912 &TimeOut);
913 ok( rc == STATUS_ACCESS_VIOLATION ||
914 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
915 "rc = %lx not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
918 * Test to see if the Timeout can be NULL
920 hslot = (HANDLE)0xdeadbeef;
921 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
922 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
923 NULL);
924 ok( rc == STATUS_SUCCESS ||
925 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
926 "rc = %lx not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
927 ok( hslot != 0, "Handle is invalid\n");
929 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
932 * Test a valid call
934 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
935 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
936 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
937 &TimeOut);
938 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %lx\n", rc);
939 ok( hslot != 0, "Handle is invalid\n");
941 rc = pNtClose(hslot);
942 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
945 static void WINAPI user_apc_proc(ULONG_PTR arg)
947 unsigned int *apc_count = (unsigned int *)arg;
948 ++*apc_count;
951 static void test_set_io_completion(void)
953 FILE_IO_COMPLETION_INFORMATION info[2] = {{0}};
954 LARGE_INTEGER timeout = {{0}};
955 unsigned int apc_count;
956 IO_STATUS_BLOCK iosb;
957 ULONG_PTR key, value;
958 NTSTATUS res;
959 ULONG count;
960 SIZE_T size = 3;
961 HANDLE h;
963 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
965 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
966 ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#lx\n", res );
967 ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h );
969 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
970 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletion failed: %#lx\n", res );
972 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
973 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %lx\n", res );
975 count = get_pending_msgs(h);
976 ok( count == 1, "Unexpected msg count: %ld\n", count );
978 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
979 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
980 ok( key == CKEY_FIRST, "Invalid completion key: %#Ix\n", key );
981 ok( iosb.Information == size, "Invalid iosb.Information: %Iu\n", iosb.Information );
982 ok( iosb.Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid iosb.Status: %#lx\n", iosb.Status );
983 ok( value == CVALUE_FIRST, "Invalid completion value: %#Ix\n", value );
985 count = get_pending_msgs(h);
986 ok( !count, "Unexpected msg count: %ld\n", count );
988 if (!pNtRemoveIoCompletionEx)
990 skip("NtRemoveIoCompletionEx() not present\n");
991 pNtClose( h );
992 return;
995 count = 0xdeadbeef;
996 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
997 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#lx\n", res );
998 ok( count <= 1, "wrong count %lu\n", count );
1000 res = pNtSetIoCompletion( h, 123, 456, 789, size );
1001 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1003 count = 0xdeadbeef;
1004 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
1005 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1006 ok( count == 1, "wrong count %lu\n", count );
1007 ok( info[0].CompletionKey == 123, "wrong key %#Ix\n", info[0].CompletionKey );
1008 ok( info[0].CompletionValue == 456, "wrong value %#Ix\n", info[0].CompletionValue );
1009 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1010 info[0].IoStatusBlock.Information );
1011 ok( info[0].IoStatusBlock.Status == 789, "wrong status %#lx\n", info[0].IoStatusBlock.Status);
1013 res = pNtSetIoCompletion( h, 123, 456, 789, size );
1014 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1016 res = pNtSetIoCompletion( h, 12, 34, 56, size );
1017 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1019 count = 0xdeadbeef;
1020 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
1021 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1022 ok( count == 2, "wrong count %lu\n", count );
1023 ok( info[0].CompletionKey == 123, "wrong key %#Ix\n", info[0].CompletionKey );
1024 ok( info[0].CompletionValue == 456, "wrong value %#Ix\n", info[0].CompletionValue );
1025 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1026 info[0].IoStatusBlock.Information );
1027 ok( info[0].IoStatusBlock.Status == 789, "wrong status %#lx\n", info[0].IoStatusBlock.Status);
1028 ok( info[1].CompletionKey == 12, "wrong key %#Ix\n", info[1].CompletionKey );
1029 ok( info[1].CompletionValue == 34, "wrong value %#Ix\n", info[1].CompletionValue );
1030 ok( info[1].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1031 info[1].IoStatusBlock.Information );
1032 ok( info[1].IoStatusBlock.Status == 56, "wrong status %#lx\n", info[1].IoStatusBlock.Status);
1034 res = pNtSetIoCompletion( h, 123, 456, 789, size );
1035 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1037 res = pNtSetIoCompletion( h, 12, 34, 56, size );
1038 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1040 count = 0xdeadbeef;
1041 res = pNtRemoveIoCompletionEx( h, info, 1, &count, NULL, FALSE );
1042 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1043 ok( count == 1, "wrong count %lu\n", count );
1044 ok( info[0].CompletionKey == 123, "wrong key %#Ix\n", info[0].CompletionKey );
1045 ok( info[0].CompletionValue == 456, "wrong value %#Ix\n", info[0].CompletionValue );
1046 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1047 info[0].IoStatusBlock.Information );
1048 ok( info[0].IoStatusBlock.Status == 789, "wrong status %#lx\n", info[0].IoStatusBlock.Status);
1050 count = 0xdeadbeef;
1051 res = pNtRemoveIoCompletionEx( h, info, 1, &count, NULL, FALSE );
1052 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1053 ok( count == 1, "wrong count %lu\n", count );
1054 ok( info[0].CompletionKey == 12, "wrong key %#Ix\n", info[0].CompletionKey );
1055 ok( info[0].CompletionValue == 34, "wrong value %#Ix\n", info[0].CompletionValue );
1056 ok( info[0].IoStatusBlock.Information == size, "wrong information %#Ix\n",
1057 info[0].IoStatusBlock.Information );
1058 ok( info[0].IoStatusBlock.Status == 56, "wrong status %#lx\n", info[0].IoStatusBlock.Status);
1060 apc_count = 0;
1061 QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count );
1063 count = 0xdeadbeef;
1064 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
1065 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1066 ok( count <= 1, "wrong count %lu\n", count );
1067 ok( !apc_count, "wrong apc count %d\n", apc_count );
1069 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE );
1070 ok( res == STATUS_USER_APC, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1071 ok( count <= 1, "wrong count %lu\n", count );
1072 ok( apc_count == 1, "wrong apc count %u\n", apc_count );
1074 apc_count = 0;
1075 QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count );
1077 res = pNtSetIoCompletion( h, 123, 456, 789, size );
1078 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#lx\n", res );
1080 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE );
1081 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#lx\n", res );
1082 ok( count == 1, "wrong count %lu\n", count );
1083 ok( !apc_count, "wrong apc count %u\n", apc_count );
1085 SleepEx( 1, TRUE );
1087 pNtClose( h );
1090 static void test_file_io_completion(void)
1092 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1094 IO_STATUS_BLOCK iosb;
1095 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1096 FILE_COMPLETION_INFORMATION fci;
1097 LARGE_INTEGER timeout = {{0}};
1098 HANDLE server, client;
1099 ULONG_PTR key, value;
1100 OVERLAPPED o = {0};
1101 int apc_count = 0;
1102 NTSTATUS res;
1103 DWORD read;
1104 long count;
1105 HANDLE h;
1107 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
1108 ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#lx\n", res );
1109 ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h );
1110 fci.CompletionPort = h;
1111 fci.CompletionKey = CKEY_SECOND;
1113 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND,
1114 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1115 4, 1024, 1024, 1000, NULL );
1116 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1117 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1118 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1119 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1121 iosb.Status = 0xdeadbeef;
1122 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1123 ok( res == STATUS_INVALID_PARAMETER, "NtSetInformationFile failed: %#lx\n", res );
1124 todo_wine
1125 ok( iosb.Status == 0xdeadbeef, "wrong status %#lx\n", iosb.Status );
1126 CloseHandle( client );
1127 CloseHandle( server );
1129 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1130 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1131 4, 1024, 1024, 1000, NULL );
1132 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1133 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1134 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1135 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1137 iosb.Status = 0xdeadbeef;
1138 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1139 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %#lx\n", res );
1140 ok( iosb.Status == STATUS_SUCCESS, "wrong status %#lx\n", iosb.Status );
1142 memset( send_buf, 0, TEST_BUF_LEN );
1143 memset( recv_buf, 0xde, TEST_BUF_LEN );
1144 count = get_pending_msgs(h);
1145 ok( !count, "Unexpected msg count: %ld\n", count );
1146 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1147 count = get_pending_msgs(h);
1148 ok( !count, "Unexpected msg count: %ld\n", count );
1149 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1151 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1152 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1153 ok( key == CKEY_SECOND, "Invalid completion key: %#Ix\n", key );
1154 ok( iosb.Information == 3, "Invalid iosb.Information: %Id\n", iosb.Information );
1155 ok( iosb.Status == STATUS_SUCCESS, "Invalid iosb.Status: %#lx\n", iosb.Status );
1156 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#Ix\n", value );
1157 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ),
1158 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1159 recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1160 count = get_pending_msgs(h);
1161 ok( !count, "Unexpected msg count: %ld\n", count );
1163 memset( send_buf, 0, TEST_BUF_LEN );
1164 memset( recv_buf, 0xde, TEST_BUF_LEN );
1165 WriteFile( client, send_buf, 2, &read, NULL );
1166 count = get_pending_msgs(h);
1167 ok( !count, "Unexpected msg count: %ld\n", count );
1168 ReadFile( server, recv_buf, 2, &read, &o);
1169 count = get_pending_msgs(h);
1170 ok( count == 1, "Unexpected msg count: %ld\n", count );
1172 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1173 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1174 ok( key == CKEY_SECOND, "Invalid completion key: %#Ix\n", key );
1175 ok( iosb.Information == 2, "Invalid iosb.Information: %Id\n", iosb.Information );
1176 ok( iosb.Status == STATUS_SUCCESS, "Invalid iosb.Status: %#lx\n", iosb.Status );
1177 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#Ix\n", value );
1178 ok( !memcmp( send_buf, recv_buf, 2 ),
1179 "Receive buffer (%02x %02x) did not match send buffer (%02x %02x)\n",
1180 recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
1182 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1183 CloseHandle( server );
1184 count = get_pending_msgs(h);
1185 ok( count == 1, "Unexpected msg count: %ld\n", count );
1187 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1188 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1189 ok( key == CKEY_SECOND, "Invalid completion key: %Ix\n", key );
1190 ok( iosb.Information == 0, "Invalid iosb.Information: %Id\n", iosb.Information );
1191 ok( iosb.Status == STATUS_PIPE_BROKEN, "Invalid iosb.Status: %lx\n", iosb.Status );
1192 ok( value == (ULONG_PTR)&o, "Invalid completion value: %Ix\n", value );
1194 CloseHandle( client );
1196 /* test associating a completion port with a handle after an async is queued */
1197 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1198 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1199 4, 1024, 1024, 1000, NULL );
1200 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1201 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1202 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1203 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1205 memset( send_buf, 0, TEST_BUF_LEN );
1206 memset( recv_buf, 0xde, TEST_BUF_LEN );
1207 count = get_pending_msgs(h);
1208 ok( !count, "Unexpected msg count: %ld\n", count );
1209 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1211 iosb.Status = 0xdeadbeef;
1212 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1213 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %lx\n", res );
1214 ok( iosb.Status == STATUS_SUCCESS, "iosb.Status invalid: %lx\n", iosb.Status );
1215 count = get_pending_msgs(h);
1216 ok( !count, "Unexpected msg count: %ld\n", count );
1218 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1220 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1221 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#lx\n", res );
1222 ok( key == CKEY_SECOND, "Invalid completion key: %#Ix\n", key );
1223 ok( iosb.Information == 3, "Invalid iosb.Information: %Id\n", iosb.Information );
1224 ok( iosb.Status == STATUS_SUCCESS, "Invalid iosb.Status: %#lx\n", iosb.Status );
1225 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#Ix\n", value );
1226 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ),
1227 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1228 recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1230 count = get_pending_msgs(h);
1231 ok( !count, "Unexpected msg count: %ld\n", count );
1233 /* using APCs on handle with associated completion port is not allowed */
1234 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1235 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %lx\n", res);
1237 CloseHandle( server );
1238 CloseHandle( client );
1240 /* test associating a completion port with a handle after an async using APC is queued */
1241 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1242 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1243 4, 1024, 1024, 1000, NULL );
1244 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
1245 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1246 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1247 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
1249 apc_count = 0;
1250 memset( send_buf, 0, TEST_BUF_LEN );
1251 memset( recv_buf, 0xde, TEST_BUF_LEN );
1252 count = get_pending_msgs(h);
1253 ok( !count, "Unexpected msg count: %ld\n", count );
1255 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1256 ok(res == STATUS_PENDING, "NtReadFile returned %lx\n", res);
1258 iosb.Status = 0xdeadbeef;
1259 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1260 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %lx\n", res );
1261 ok( iosb.Status == STATUS_SUCCESS, "iosb.Status invalid: %lx\n", iosb.Status );
1262 count = get_pending_msgs(h);
1263 ok( !count, "Unexpected msg count: %ld\n", count );
1265 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1267 ok(!apc_count, "apc_count = %u\n", apc_count);
1268 count = get_pending_msgs(h);
1269 ok( !count, "Unexpected msg count: %ld\n", count );
1271 SleepEx(1, TRUE); /* alertable sleep */
1272 ok(apc_count == 1, "apc was not called\n");
1273 count = get_pending_msgs(h);
1274 ok( !count, "Unexpected msg count: %ld\n", count );
1276 /* using APCs on handle with associated completion port is not allowed */
1277 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1278 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %lx\n", res);
1280 CloseHandle( server );
1281 CloseHandle( client );
1282 pNtClose( h );
1285 static void test_file_full_size_information(void)
1287 IO_STATUS_BLOCK io;
1288 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1289 FILE_FS_SIZE_INFORMATION fsi;
1290 HANDLE h;
1291 NTSTATUS res;
1293 if(!(h = create_temp_file(0))) return ;
1295 memset(&ffsi,0,sizeof(ffsi));
1296 memset(&fsi,0,sizeof(fsi));
1298 /* Assume No Quota Settings configured on Wine Testbot */
1299 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1300 ok(res == STATUS_SUCCESS, "cannot get attributes, res %lx\n", res);
1301 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1302 ok(res == STATUS_SUCCESS, "cannot get attributes, res %lx\n", res);
1304 /* Test for FileFsSizeInformation */
1305 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1306 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1307 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1308 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1309 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1310 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1312 /* Assume file system is NTFS */
1313 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %ld\n",fsi.BytesPerSector);
1314 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %ld\n",fsi.SectorsPerAllocationUnit);
1316 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1317 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1318 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1319 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1320 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1321 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1322 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1323 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1324 wine_dbgstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1325 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1326 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1327 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1328 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1329 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1330 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1331 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1332 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1334 /* Assume file system is NTFS */
1335 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %ld\n",ffsi.BytesPerSector);
1336 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %ld\n",ffsi.SectorsPerAllocationUnit);
1338 CloseHandle( h );
1341 static void test_file_basic_information(void)
1343 FILE_BASIC_INFORMATION fbi, fbi2;
1344 IO_STATUS_BLOCK io;
1345 HANDLE h;
1346 int res;
1347 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1349 if (!(h = create_temp_file(0))) return;
1351 /* Check default first */
1352 memset(&fbi, 0, sizeof(fbi));
1353 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1354 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1355 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1356 "attribute %lx not expected\n", fbi.FileAttributes );
1358 memset(&fbi2, 0, sizeof(fbi2));
1359 fbi2.LastWriteTime.QuadPart = -1;
1360 io.Status = 0xdeadbeef;
1361 res = pNtSetInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1362 ok ( res == STATUS_SUCCESS, "can't set -1 write time, NtSetInformationFile returned %x\n", res );
1363 ok ( io.Status == STATUS_SUCCESS, "can't set -1 write time, io.Status is %lx\n", io.Status );
1365 memset(&fbi2, 0, sizeof(fbi2));
1366 fbi2.LastAccessTime.QuadPart = 0x200deadcafebeef;
1367 io.Status = 0xdeadbeef;
1368 res = pNtSetInformationFile(h, &io, &fbi2, sizeof(fbi2), FileBasicInformation);
1369 ok ( res == STATUS_SUCCESS, "can't set access time, NtSetInformationFile returned %x\n", res );
1370 ok ( io.Status == STATUS_SUCCESS, "can't set access time, io.Status is %lx\n", io.Status );
1371 res = pNtQueryInformationFile(h, &io, &fbi, sizeof(fbi), FileBasicInformation);
1372 ok ( res == STATUS_SUCCESS, "can't get access time, NtQueryInformationFile returned %x\n", res );
1373 ok ( io.Status == STATUS_SUCCESS, "can't get access time, io.Status is %lx\n", io.Status );
1374 ok ( fbi2.LastAccessTime.QuadPart == fbi.LastAccessTime.QuadPart,
1375 "access time mismatch, set: %s get: %s\n",
1376 wine_dbgstr_longlong(fbi2.LastAccessTime.QuadPart),
1377 wine_dbgstr_longlong(fbi.LastAccessTime.QuadPart) );
1379 memset(&fbi2, 0, sizeof(fbi2));
1380 res = pNtQueryInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1381 ok ( res == STATUS_SUCCESS, "can't get write time 1, res %x\n", res);
1382 ok ( fbi2.LastWriteTime.QuadPart == fbi.LastWriteTime.QuadPart, "write time mismatch, %s != %s\n",
1383 wine_dbgstr_longlong(fbi2.LastWriteTime.QuadPart),
1384 wine_dbgstr_longlong(fbi.LastWriteTime.QuadPart) );
1386 memset(&fbi2, 0, sizeof(fbi2));
1387 io.Status = 0xdeadbeef;
1388 res = pNtSetInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1389 ok ( res == STATUS_SUCCESS, "can't set nothing, NtSetInformationFile returned %x\n", res );
1390 ok ( io.Status == STATUS_SUCCESS, "can't set nothing, io.Status is %lx\n", io.Status );
1392 memset(&fbi2, 0, sizeof(fbi2));
1393 res = pNtQueryInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
1394 ok ( res == STATUS_SUCCESS, "can't get write time 2, res %x\n", res);
1395 ok ( fbi2.LastWriteTime.QuadPart == fbi.LastWriteTime.QuadPart, "write time changed, %s != %s\n",
1396 wine_dbgstr_longlong(fbi2.LastWriteTime.QuadPart),
1397 wine_dbgstr_longlong(fbi.LastWriteTime.QuadPart) );
1399 /* Then SYSTEM */
1400 /* Clear fbi to avoid setting times */
1401 memset(&fbi, 0, sizeof(fbi));
1402 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1403 io.Status = 0xdeadbeef;
1404 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1405 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1406 ok ( io.Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %lx\n", io.Status );
1408 memset(&fbi, 0, sizeof(fbi));
1409 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1410 ok ( res == STATUS_SUCCESS, "can't get system attribute\n");
1411 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1413 /* Then HIDDEN */
1414 memset(&fbi, 0, sizeof(fbi));
1415 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1416 io.Status = 0xdeadbeef;
1417 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1418 ok ( res == STATUS_SUCCESS, "can't set hidden attribute, NtSetInformationFile returned %x\n", res );
1419 ok ( io.Status == STATUS_SUCCESS, "can't set hidden attribute, io.Status is %lx\n", io.Status );
1421 memset(&fbi, 0, sizeof(fbi));
1422 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1423 ok ( res == STATUS_SUCCESS, "can't get hidden attribute\n");
1424 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1426 /* Check NORMAL last of all (to make sure we can clear attributes) */
1427 memset(&fbi, 0, sizeof(fbi));
1428 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1429 io.Status = 0xdeadbeef;
1430 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1431 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1432 ok ( io.Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %lx\n", io.Status );
1434 memset(&fbi, 0, sizeof(fbi));
1435 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1436 ok ( res == STATUS_SUCCESS, "can't get normal attribute\n");
1437 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %lx not 0\n", fbi.FileAttributes );
1439 CloseHandle( h );
1442 static void test_file_all_information(void)
1444 IO_STATUS_BLOCK io;
1445 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1446 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1447 * don't leave enough room there.
1449 struct {
1450 FILE_ALL_INFORMATION fai;
1451 WCHAR buf[256];
1452 } fai_buf;
1453 HANDLE h;
1454 int res;
1455 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1457 if (!(h = create_temp_file(0))) return;
1459 /* Check default first */
1460 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1461 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1462 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1463 "attribute %lx not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1465 /* Then SYSTEM */
1466 /* Clear fbi to avoid setting times */
1467 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1468 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1469 io.Status = 0xdeadbeef;
1470 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1471 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1472 todo_wine ok ( io.Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %lx\n", io.Status);
1473 io.Status = 0xdeadbeef;
1474 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1475 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1476 ok ( io.Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %lx\n", io.Status );
1478 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1479 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1480 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1481 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fai_buf.fai.BasicInformation.FileAttributes );
1483 /* Then HIDDEN */
1484 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1485 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1486 io.Status = 0xdeadbeef;
1487 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1488 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1489 ok ( io.Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %lx\n", io.Status );
1491 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1492 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1493 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1494 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\n", fai_buf.fai.BasicInformation.FileAttributes );
1496 /* Check NORMAL last of all (to make sure we can clear attributes) */
1497 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1498 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1499 io.Status = 0xdeadbeef;
1500 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1501 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1502 ok ( io.Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %lx\n", io.Status );
1504 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1505 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1506 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1507 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 );
1509 CloseHandle( h );
1512 static void delete_object( WCHAR *path )
1514 BOOL ret = SetFileAttributesW( path, FILE_ATTRIBUTE_NORMAL );
1515 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "SetFileAttribute failed with %lu\n", GetLastError() );
1516 ret = DeleteFileW( path );
1517 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1518 "DeleteFileW failed with %lu\n", GetLastError() );
1519 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1521 ret = RemoveDirectoryW( path );
1522 ok( ret, "RemoveDirectoryW failed with %lu\n", GetLastError() );
1526 static void test_file_rename_information(FILE_INFORMATION_CLASS class)
1528 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1529 static const WCHAR fooW[] = {'f','o','o',0};
1530 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1531 FILE_RENAME_INFORMATION *fri;
1532 FILE_NAME_INFORMATION *fni;
1533 BOOL success, fileDeleted;
1534 UNICODE_STRING name_str;
1535 HANDLE handle, handle2;
1536 IO_STATUS_BLOCK io;
1537 NTSTATUS res;
1539 GetTempPathW( MAX_PATH, tmp_path );
1541 /* oldpath is a file, newpath doesn't exist */
1542 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1543 ok( res != 0, "failed to create temp file\n" );
1544 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1545 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1547 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1548 ok( res != 0, "failed to create temp file\n" );
1549 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1550 DeleteFileW( newpath );
1551 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1552 fri->Flags = 0;
1553 fri->RootDirectory = NULL;
1554 fri->FileNameLength = name_str.Length;
1555 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1556 pRtlFreeUnicodeString( &name_str );
1558 io.Status = 0xdeadbeef;
1559 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1561 if (class == FileRenameInformationEx && (res == STATUS_NOT_IMPLEMENTED || res == STATUS_INVALID_INFO_CLASS))
1563 win_skip( "FileRenameInformationEx not supported\n" );
1564 CloseHandle( handle );
1565 HeapFree( GetProcessHeap(), 0, fri );
1566 delete_object( oldpath );
1567 return;
1570 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
1571 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1572 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1573 ok( fileDeleted, "file should not exist\n" );
1574 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1575 ok( !fileDeleted, "file should exist\n" );
1577 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1578 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1579 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1580 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1581 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1582 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1583 HeapFree( GetProcessHeap(), 0, fni );
1585 CloseHandle( handle );
1586 HeapFree( GetProcessHeap(), 0, fri );
1587 delete_object( oldpath );
1588 delete_object( newpath );
1590 /* oldpath is a file, newpath is a file, Replace = FALSE */
1591 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1592 ok( res != 0, "failed to create temp file\n" );
1593 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1594 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1596 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1597 ok( res != 0, "failed to create temp file\n" );
1598 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1599 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1600 fri->Flags = 0;
1601 fri->RootDirectory = NULL;
1602 fri->FileNameLength = name_str.Length;
1603 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1604 pRtlFreeUnicodeString( &name_str );
1606 io.Status = 0xdeadbeef;
1607 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1608 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
1609 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1610 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1611 ok( !fileDeleted, "file should exist\n" );
1612 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1613 ok( !fileDeleted, "file should exist\n" );
1615 CloseHandle( handle );
1616 HeapFree( GetProcessHeap(), 0, fri );
1617 delete_object( oldpath );
1618 delete_object( newpath );
1620 /* oldpath is a file, newpath is a file, Replace = TRUE */
1621 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1622 ok( res != 0, "failed to create temp file\n" );
1623 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1624 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1626 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1627 ok( res != 0, "failed to create temp file\n" );
1628 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1629 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1630 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
1631 fri->RootDirectory = NULL;
1632 fri->FileNameLength = name_str.Length;
1633 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1634 pRtlFreeUnicodeString( &name_str );
1636 io.Status = 0xdeadbeef;
1637 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1638 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
1639 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1640 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1641 ok( fileDeleted, "file should not exist\n" );
1642 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1643 ok( !fileDeleted, "file should exist\n" );
1645 CloseHandle( handle );
1646 HeapFree( GetProcessHeap(), 0, fri );
1647 delete_object( oldpath );
1648 delete_object( newpath );
1650 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1651 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1652 ok( res != 0, "failed to create temp file\n" );
1653 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1654 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1656 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1657 ok( res != 0, "failed to create temp file\n" );
1658 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1659 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1661 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1662 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1663 fri->Flags = 0;
1664 fri->RootDirectory = NULL;
1665 fri->FileNameLength = name_str.Length;
1666 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1667 pRtlFreeUnicodeString( &name_str );
1669 io.Status = 0xdeadbeef;
1670 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1671 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
1672 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1673 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1674 ok( !fileDeleted, "file should exist\n" );
1675 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1676 ok( !fileDeleted, "file should exist\n" );
1678 CloseHandle( handle );
1679 CloseHandle( handle2 );
1680 HeapFree( GetProcessHeap(), 0, fri );
1681 delete_object( oldpath );
1682 delete_object( newpath );
1684 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1685 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1686 ok( res != 0, "failed to create temp file\n" );
1687 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1688 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1690 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1691 ok( res != 0, "failed to create temp file\n" );
1692 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1693 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1695 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1696 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1697 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
1698 fri->RootDirectory = NULL;
1699 fri->FileNameLength = name_str.Length;
1700 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1701 pRtlFreeUnicodeString( &name_str );
1703 io.Status = 0xdeadbeef;
1704 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1705 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
1706 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
1707 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1708 ok( !fileDeleted, "file should exist\n" );
1709 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1710 ok( !fileDeleted, "file should exist\n" );
1712 CloseHandle( handle );
1713 CloseHandle( handle2 );
1714 HeapFree( GetProcessHeap(), 0, fri );
1715 delete_object( oldpath );
1716 delete_object( newpath );
1718 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1719 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1720 ok( res != 0, "failed to create temp file\n" );
1721 DeleteFileW( oldpath );
1722 success = CreateDirectoryW( oldpath, NULL );
1723 ok( success != 0, "failed to create temp directory\n" );
1724 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1725 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1727 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1728 ok( res != 0, "failed to create temp file\n" );
1729 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1730 DeleteFileW( newpath );
1731 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1732 fri->Flags = 0;
1733 fri->RootDirectory = NULL;
1734 fri->FileNameLength = name_str.Length;
1735 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1736 pRtlFreeUnicodeString( &name_str );
1738 io.Status = 0xdeadbeef;
1739 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1740 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
1741 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1742 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1743 ok( fileDeleted, "file should not exist\n" );
1744 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1745 ok( !fileDeleted, "file should exist\n" );
1747 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1748 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1749 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1750 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1751 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1752 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1753 HeapFree( GetProcessHeap(), 0, fni );
1755 CloseHandle( handle );
1756 HeapFree( GetProcessHeap(), 0, fri );
1757 delete_object( oldpath );
1758 delete_object( newpath );
1760 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1761 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1762 ok( res != 0, "failed to create temp file\n" );
1763 DeleteFileW( oldpath );
1764 success = CreateDirectoryW( oldpath, NULL );
1765 ok( success != 0, "failed to create temp directory\n" );
1766 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1767 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1769 lstrcpyW( newpath, oldpath );
1770 lstrcatW( newpath, foo_txtW );
1771 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1772 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1774 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1775 ok( res != 0, "failed to create temp file\n" );
1776 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1777 DeleteFileW( newpath );
1778 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1779 fri->Flags = 0;
1780 fri->RootDirectory = NULL;
1781 fri->FileNameLength = name_str.Length;
1782 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1783 pRtlFreeUnicodeString( &name_str );
1785 io.Status = 0xdeadbeef;
1786 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1787 todo_wine ok( io.Status == 0xdeadbeef || io.Status == STATUS_ACCESS_DENIED, "io.Status got %lx\n", io.Status );
1788 todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
1789 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1790 todo_wine ok( !fileDeleted, "file should exist\n" );
1791 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1792 todo_wine ok( fileDeleted, "file should not exist\n" );
1794 CloseHandle( handle );
1795 CloseHandle( handle2 );
1796 HeapFree( GetProcessHeap(), 0, fri );
1797 delete_object( oldpath );
1798 if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1800 lstrcpyW( oldpath, newpath );
1801 lstrcatW( oldpath, foo_txtW );
1802 delete_object( oldpath );
1804 delete_object( newpath );
1806 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1807 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1808 ok( res != 0, "failed to create temp file\n" );
1809 DeleteFileW( oldpath );
1810 success = CreateDirectoryW( oldpath, NULL );
1811 ok( success != 0, "failed to create temp directory\n" );
1812 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1813 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1815 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1816 ok( res != 0, "failed to create temp file\n" );
1817 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1818 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1819 fri->Flags = 0;
1820 fri->RootDirectory = NULL;
1821 fri->FileNameLength = name_str.Length;
1822 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1823 pRtlFreeUnicodeString( &name_str );
1825 io.Status = 0xdeadbeef;
1826 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1827 ok( io.Status == 0xdeadbeef || io.Status == STATUS_OBJECT_NAME_COLLISION, "io.Status got %lx\n", io.Status );
1828 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1829 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1830 ok( !fileDeleted, "file should exist\n" );
1831 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1832 ok( !fileDeleted, "file should exist\n" );
1834 CloseHandle( handle );
1835 HeapFree( GetProcessHeap(), 0, fri );
1836 delete_object( oldpath );
1837 delete_object( newpath );
1839 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1840 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1841 ok( res != 0, "failed to create temp file\n" );
1842 DeleteFileW( oldpath );
1843 success = CreateDirectoryW( oldpath, NULL );
1844 ok( success != 0, "failed to create temp directory\n" );
1845 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1846 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1848 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1849 ok( res != 0, "failed to create temp file\n" );
1850 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1851 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1853 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1854 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1855 fri->Flags = 0;
1856 fri->RootDirectory = NULL;
1857 fri->FileNameLength = name_str.Length;
1858 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1859 pRtlFreeUnicodeString( &name_str );
1861 io.Status = 0xdeadbeef;
1862 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1863 ok( io.Status == 0xdeadbeef || io.Status == STATUS_OBJECT_NAME_COLLISION, "io.Status got %lx\n", io.Status );
1864 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1865 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1866 ok( !fileDeleted, "file should exist\n" );
1867 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1868 ok( !fileDeleted, "file should exist\n" );
1870 CloseHandle( handle );
1871 CloseHandle( handle2 );
1872 HeapFree( GetProcessHeap(), 0, fri );
1873 delete_object( oldpath );
1874 delete_object( newpath );
1876 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1877 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1878 ok( res != 0, "failed to create temp file\n" );
1879 DeleteFileW( oldpath );
1880 success = CreateDirectoryW( oldpath, NULL );
1881 ok( success != 0, "failed to create temp directory\n" );
1882 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1883 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1885 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1886 ok( res != 0, "failed to create temp file\n" );
1887 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1888 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1889 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
1890 fri->RootDirectory = NULL;
1891 fri->FileNameLength = name_str.Length;
1892 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1893 pRtlFreeUnicodeString( &name_str );
1895 io.Status = 0xdeadbeef;
1896 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1897 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
1898 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
1899 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1900 ok( fileDeleted, "file should not exist\n" );
1901 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1902 ok( !fileDeleted, "file should exist\n" );
1904 CloseHandle( handle );
1905 HeapFree( GetProcessHeap(), 0, fri );
1906 delete_object( oldpath );
1907 delete_object( newpath );
1909 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1910 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1911 ok( res != 0, "failed to create temp file\n" );
1912 DeleteFileW( oldpath );
1913 success = CreateDirectoryW( oldpath, NULL );
1914 ok( success != 0, "failed to create temp directory\n" );
1915 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1916 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1918 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1919 ok( res != 0, "failed to create temp file\n" );
1920 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1921 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1923 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1924 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1925 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
1926 fri->RootDirectory = NULL;
1927 fri->FileNameLength = name_str.Length;
1928 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1929 pRtlFreeUnicodeString( &name_str );
1931 io.Status = 0xdeadbeef;
1932 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1933 ok( io.Status == 0xdeadbeef || io.Status == STATUS_ACCESS_DENIED, "io.Status got %lx\n", io.Status );
1934 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
1935 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1936 ok( !fileDeleted, "file should exist\n" );
1937 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1938 ok( !fileDeleted, "file should exist\n" );
1940 CloseHandle( handle );
1941 CloseHandle( handle2 );
1942 HeapFree( GetProcessHeap(), 0, fri );
1943 delete_object( oldpath );
1944 delete_object( newpath );
1946 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1947 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1948 ok( res != 0, "failed to create temp file\n" );
1949 DeleteFileW( oldpath );
1950 success = CreateDirectoryW( oldpath, NULL );
1951 ok( success != 0, "failed to create temp directory\n" );
1952 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1953 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1955 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1956 ok( res != 0, "failed to create temp file\n" );
1957 DeleteFileW( newpath );
1958 success = CreateDirectoryW( newpath, NULL );
1959 ok( success != 0, "failed to create temp directory\n" );
1960 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1961 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1962 fri->Flags = 0;
1963 fri->RootDirectory = NULL;
1964 fri->FileNameLength = name_str.Length;
1965 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1966 pRtlFreeUnicodeString( &name_str );
1968 io.Status = 0xdeadbeef;
1969 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
1970 ok( io.Status == 0xdeadbeef || io.Status == STATUS_OBJECT_NAME_COLLISION, "io.Status got %lx\n", io.Status );
1971 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
1972 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1973 ok( !fileDeleted, "file should exist\n" );
1974 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1975 ok( !fileDeleted, "file should exist\n" );
1977 CloseHandle( handle );
1978 HeapFree( GetProcessHeap(), 0, fri );
1979 delete_object( oldpath );
1980 delete_object( newpath );
1982 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1983 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1984 ok( res != 0, "failed to create temp file\n" );
1985 DeleteFileW( oldpath );
1986 success = CreateDirectoryW( oldpath, NULL );
1987 ok( success != 0, "failed to create temp directory\n" );
1988 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1989 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1991 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1992 ok( res != 0, "failed to create temp file\n" );
1993 DeleteFileW( newpath );
1994 success = CreateDirectoryW( newpath, NULL );
1995 ok( success != 0, "failed to create temp directory\n" );
1996 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1997 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1998 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
1999 fri->RootDirectory = NULL;
2000 fri->FileNameLength = name_str.Length;
2001 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2002 pRtlFreeUnicodeString( &name_str );
2004 io.Status = 0xdeadbeef;
2005 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
2006 ok( io.Status == 0xdeadbeef || io.Status == STATUS_ACCESS_DENIED, "io.Status got %lx\n", io.Status );
2007 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2008 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2009 ok( !fileDeleted, "file should exist\n" );
2010 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2011 ok( !fileDeleted, "file should exist\n" );
2013 CloseHandle( handle );
2014 HeapFree( GetProcessHeap(), 0, fri );
2015 delete_object( oldpath );
2016 delete_object( newpath );
2018 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
2019 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2020 ok( res != 0, "failed to create temp file\n" );
2021 DeleteFileW( oldpath );
2022 success = CreateDirectoryW( oldpath, NULL );
2023 ok( success != 0, "failed to create temp directory\n" );
2024 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2025 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2027 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2028 ok( res != 0, "failed to create temp file\n" );
2029 DeleteFileW( newpath );
2030 success = CreateDirectoryW( newpath, NULL );
2031 ok( success != 0, "failed to create temp directory\n" );
2032 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2033 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2035 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2036 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2037 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
2038 fri->RootDirectory = NULL;
2039 fri->FileNameLength = name_str.Length;
2040 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2041 pRtlFreeUnicodeString( &name_str );
2043 io.Status = 0xdeadbeef;
2044 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
2045 ok( io.Status == 0xdeadbeef || io.Status == STATUS_ACCESS_DENIED, "io.Status got %lx\n", io.Status );
2046 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2047 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2048 ok( !fileDeleted, "file should exist\n" );
2049 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2050 ok( !fileDeleted, "file should exist\n" );
2052 CloseHandle( handle );
2053 CloseHandle( handle2 );
2054 HeapFree( GetProcessHeap(), 0, fri );
2055 delete_object( oldpath );
2056 delete_object( newpath );
2058 /* oldpath is a file, newpath is a directory, Replace = FALSE */
2059 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2060 ok( res != 0, "failed to create temp file\n" );
2061 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2062 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2064 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2065 ok( res != 0, "failed to create temp file\n" );
2066 DeleteFileW( newpath );
2067 success = CreateDirectoryW( newpath, NULL );
2068 ok( success != 0, "failed to create temp directory\n" );
2069 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2070 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2071 fri->Flags = 0;
2072 fri->RootDirectory = NULL;
2073 fri->FileNameLength = name_str.Length;
2074 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2075 pRtlFreeUnicodeString( &name_str );
2077 io.Status = 0xdeadbeef;
2078 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
2079 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2080 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
2081 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2082 ok( !fileDeleted, "file should exist\n" );
2083 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2084 ok( !fileDeleted, "file should exist\n" );
2086 CloseHandle( handle );
2087 HeapFree( GetProcessHeap(), 0, fri );
2088 delete_object( oldpath );
2089 delete_object( newpath );
2091 /* oldpath is a file, newpath is a directory, Replace = TRUE */
2092 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2093 ok( res != 0, "failed to create temp file\n" );
2094 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2095 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2097 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2098 ok( res != 0, "failed to create temp file\n" );
2099 DeleteFileW( newpath );
2100 success = CreateDirectoryW( newpath, NULL );
2101 ok( success != 0, "failed to create temp directory\n" );
2102 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2103 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2104 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
2105 fri->RootDirectory = NULL;
2106 fri->FileNameLength = name_str.Length;
2107 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2108 pRtlFreeUnicodeString( &name_str );
2110 io.Status = 0xdeadbeef;
2111 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
2112 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2113 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2114 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2115 ok( !fileDeleted, "file should exist\n" );
2116 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2117 ok( !fileDeleted, "file should exist\n" );
2119 CloseHandle( handle );
2120 HeapFree( GetProcessHeap(), 0, fri );
2121 delete_object( oldpath );
2122 delete_object( newpath );
2124 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
2125 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2126 ok( res != 0, "failed to create temp file\n" );
2127 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2128 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2130 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2131 ok( res != 0, "failed to create temp file\n" );
2132 DeleteFileW( newpath );
2133 for (filename = newpath, p = newpath; *p; p++)
2134 if (*p == '\\') filename = p + 1;
2135 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2136 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2138 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2139 fri->Flags = 0;
2140 fri->RootDirectory = handle2;
2141 fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2142 memcpy( fri->FileName, filename, fri->FileNameLength );
2144 io.Status = 0xdeadbeef;
2145 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
2146 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
2147 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2148 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2149 ok( fileDeleted, "file should not exist\n" );
2150 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2151 ok( !fileDeleted, "file should exist\n" );
2153 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2154 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2155 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2156 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2157 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
2158 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
2159 HeapFree( GetProcessHeap(), 0, fni );
2161 CloseHandle( handle );
2162 CloseHandle( handle2 );
2163 HeapFree( GetProcessHeap(), 0, fri );
2164 delete_object( oldpath );
2165 delete_object( newpath );
2167 /* oldpath == newpath */
2168 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2169 ok( res != 0, "failed to create temp file\n" );
2170 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2171 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2173 pRtlDosPathNameToNtPathName_U( oldpath, &name_str, NULL, NULL );
2174 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2175 fri->Flags = 0;
2176 fri->RootDirectory = NULL;
2177 fri->FileNameLength = name_str.Length;
2178 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2179 pRtlFreeUnicodeString( &name_str );
2181 io.Status = 0xdeadbeef;
2182 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, class );
2183 ok( io.Status == STATUS_SUCCESS, "got io status %#lx\n", io.Status );
2184 ok( res == STATUS_SUCCESS, "got status %lx\n", res );
2185 ok( GetFileAttributesW( oldpath ) != INVALID_FILE_ATTRIBUTES, "file should exist\n" );
2187 CloseHandle( handle );
2188 HeapFree( GetProcessHeap(), 0, fri );
2189 delete_object( oldpath );
2192 static void test_file_rename_information_ex(void)
2194 static const WCHAR fooW[] = {'f','o','o',0};
2195 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16];
2196 FILE_RENAME_INFORMATION *fri;
2197 BOOL fileDeleted;
2198 UNICODE_STRING name_str;
2199 HANDLE handle, handle2;
2200 IO_STATUS_BLOCK io;
2201 NTSTATUS res;
2203 GetTempPathW( MAX_PATH, tmp_path );
2205 /* oldpath is a file, newpath is a read-only file, with FILE_RENAME_REPLACE_IF_EXISTS */
2206 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2207 ok( res != 0, "failed to create temp file\n" );
2208 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2209 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2211 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2212 ok( res != 0, "failed to create temp file\n" );
2213 DeleteFileW( newpath );
2214 handle2 = CreateFileW( newpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0 );
2215 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2216 CloseHandle( handle2 );
2217 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2218 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2219 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS;
2220 fri->RootDirectory = NULL;
2221 fri->FileNameLength = name_str.Length;
2222 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2223 pRtlFreeUnicodeString( &name_str );
2225 io.Status = 0xdeadbeef;
2226 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformationEx );
2228 if (res == STATUS_NOT_IMPLEMENTED || res == STATUS_INVALID_INFO_CLASS)
2230 win_skip( "FileRenameInformationEx not supported\n" );
2231 CloseHandle( handle );
2232 HeapFree( GetProcessHeap(), 0, fri );
2233 delete_object( oldpath );
2234 return;
2237 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2238 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2239 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2240 ok( !fileDeleted, "file should exist\n" );
2241 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2242 ok( !fileDeleted, "file should exist\n" );
2244 CloseHandle( handle );
2245 HeapFree( GetProcessHeap(), 0, fri );
2246 delete_object( oldpath );
2247 delete_object( newpath );
2249 /* oldpath is a file, newpath is a read-only file, with FILE_RENAME_REPLACE_IF_EXISTS and FILE_RENAME_IGNORE_READONLY_ATTRIBUTE */
2250 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2251 ok( res != 0, "failed to create temp file\n" );
2252 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2253 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2255 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2256 ok( res != 0, "failed to create temp file\n" );
2257 DeleteFileW( newpath );
2258 handle2 = CreateFileW( newpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0 );
2259 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2260 CloseHandle( handle2 );
2261 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2262 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2263 fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS | FILE_RENAME_IGNORE_READONLY_ATTRIBUTE;
2264 fri->RootDirectory = NULL;
2265 fri->FileNameLength = name_str.Length;
2266 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2267 pRtlFreeUnicodeString( &name_str );
2269 io.Status = 0xdeadbeef;
2270 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformationEx );
2271 ok( io.Status == STATUS_SUCCESS || io.Status == 0xdeadbeef,
2272 "io.Status expected STATUS_SUCCESS or 0xdeadbeef, got %lx\n", io.Status );
2273 ok( res == STATUS_SUCCESS || res == STATUS_NOT_SUPPORTED,
2274 "res expected STATUS_SUCCESS or STATUS_NOT_SUPPORTED, got %lx\n", res );
2276 if (res == STATUS_SUCCESS)
2278 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2279 ok( fileDeleted, "file should not exist\n" );
2280 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2281 ok( !fileDeleted, "file should exist\n" );
2284 CloseHandle( handle );
2285 HeapFree( GetProcessHeap(), 0, fri );
2286 delete_object( oldpath );
2287 delete_object( newpath );
2290 static void test_file_link_information(FILE_INFORMATION_CLASS class)
2292 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
2293 static const WCHAR fooW[] = {'f','o','o',0};
2294 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
2295 FILE_LINK_INFORMATION *fli;
2296 FILE_NAME_INFORMATION *fni;
2297 WIN32_FIND_DATAW find_data;
2298 BOOL success, fileDeleted;
2299 UNICODE_STRING name_str;
2300 HANDLE handle, handle2;
2301 IO_STATUS_BLOCK io;
2302 NTSTATUS res;
2304 GetTempPathW( MAX_PATH, tmp_path );
2306 /* oldpath is a file, newpath doesn't exist */
2307 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2308 ok( res != 0, "failed to create temp file\n" );
2309 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2310 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2312 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2313 ok( res != 0, "failed to create temp file\n" );
2314 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2315 DeleteFileW( newpath );
2316 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2317 fli->Flags = 0;
2318 fli->RootDirectory = NULL;
2319 fli->FileNameLength = name_str.Length;
2320 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2321 pRtlFreeUnicodeString( &name_str );
2323 io.Status = 0xdeadbeef;
2324 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2326 if (class == FileLinkInformationEx && (res == STATUS_NOT_IMPLEMENTED || res == STATUS_INVALID_INFO_CLASS))
2328 win_skip( "FileLinkInformationEx not supported\n" );
2329 CloseHandle( handle );
2330 HeapFree( GetProcessHeap(), 0, fli );
2331 delete_object( oldpath );
2332 return;
2335 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
2336 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2337 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2338 ok( !fileDeleted, "file should exist\n" );
2339 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2340 ok( !fileDeleted, "file should exist\n" );
2342 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2343 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2344 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2345 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2346 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2347 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2348 HeapFree( GetProcessHeap(), 0, fni );
2350 CloseHandle( handle );
2351 HeapFree( GetProcessHeap(), 0, fli );
2352 delete_object( oldpath );
2353 delete_object( newpath );
2355 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2356 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2357 ok( res != 0, "failed to create temp file\n" );
2358 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2359 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2361 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2362 ok( res != 0, "failed to create temp file\n" );
2363 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2364 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2365 fli->Flags = 0;
2366 fli->RootDirectory = NULL;
2367 fli->FileNameLength = name_str.Length;
2368 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2369 pRtlFreeUnicodeString( &name_str );
2371 io.Status = 0xdeadbeef;
2372 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2373 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2374 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
2375 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2376 ok( !fileDeleted, "file should exist\n" );
2377 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2378 ok( !fileDeleted, "file should exist\n" );
2380 CloseHandle( handle );
2381 HeapFree( GetProcessHeap(), 0, fli );
2382 delete_object( oldpath );
2383 delete_object( newpath );
2385 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2386 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2387 ok( res != 0, "failed to create temp file\n" );
2388 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2389 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2391 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2392 ok( res != 0, "failed to create temp file\n" );
2393 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2394 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2395 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2396 fli->RootDirectory = NULL;
2397 fli->FileNameLength = name_str.Length;
2398 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2399 pRtlFreeUnicodeString( &name_str );
2401 io.Status = 0xdeadbeef;
2402 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2403 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
2404 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2405 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2406 ok( !fileDeleted, "file should exist\n" );
2407 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2408 ok( !fileDeleted, "file should exist\n" );
2410 CloseHandle( handle );
2411 HeapFree( GetProcessHeap(), 0, fli );
2412 delete_object( oldpath );
2413 delete_object( newpath );
2415 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, different casing on link */
2416 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2417 ok( res != 0, "failed to create temp file\n" );
2418 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2419 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2421 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2422 ok( res != 0, "failed to create temp file\n" );
2423 wcsrchr( newpath, '\\' )[1] = 'F';
2424 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2425 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2426 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2427 fli->RootDirectory = NULL;
2428 fli->FileNameLength = name_str.Length;
2429 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2430 pRtlFreeUnicodeString( &name_str );
2432 io.Status = 0xdeadbeef;
2433 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2434 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
2435 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2436 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2437 ok( !fileDeleted, "file should exist\n" );
2438 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2439 ok( !fileDeleted, "file should exist\n" );
2441 CloseHandle( handle );
2442 handle = FindFirstFileW( newpath, &find_data );
2443 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileW: failed, error %ld\n", GetLastError());
2444 if (handle != INVALID_HANDLE_VALUE)
2446 todo_wine ok(!lstrcmpW(wcsrchr(newpath, '\\') + 1, find_data.cFileName),
2447 "Link did not change casing on existing target file: got %s\n", wine_dbgstr_w(find_data.cFileName));
2450 FindClose( handle );
2451 HeapFree( GetProcessHeap(), 0, fli );
2452 delete_object( oldpath );
2453 delete_object( newpath );
2455 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2456 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2457 ok( res != 0, "failed to create temp file\n" );
2458 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2459 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2461 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2462 ok( res != 0, "failed to create temp file\n" );
2463 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2464 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2466 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2467 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2468 fli->Flags = 0;
2469 fli->RootDirectory = NULL;
2470 fli->FileNameLength = name_str.Length;
2471 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2472 pRtlFreeUnicodeString( &name_str );
2474 io.Status = 0xdeadbeef;
2475 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2476 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2477 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
2478 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2479 ok( !fileDeleted, "file should exist\n" );
2480 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2481 ok( !fileDeleted, "file should exist\n" );
2483 CloseHandle( handle );
2484 CloseHandle( handle2 );
2485 HeapFree( GetProcessHeap(), 0, fli );
2486 delete_object( oldpath );
2487 delete_object( newpath );
2489 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2490 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2491 ok( res != 0, "failed to create temp file\n" );
2492 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2493 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2495 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2496 ok( res != 0, "failed to create temp file\n" );
2497 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2498 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2500 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2501 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2502 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2503 fli->RootDirectory = NULL;
2504 fli->FileNameLength = name_str.Length;
2505 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2506 pRtlFreeUnicodeString( &name_str );
2508 io.Status = 0xdeadbeef;
2509 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2510 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2511 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2512 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2513 ok( !fileDeleted, "file should exist\n" );
2514 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2515 ok( !fileDeleted, "file should exist\n" );
2517 CloseHandle( handle );
2518 CloseHandle( handle2 );
2519 HeapFree( GetProcessHeap(), 0, fli );
2520 delete_object( oldpath );
2521 delete_object( newpath );
2523 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2524 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2525 ok( res != 0, "failed to create temp file\n" );
2526 DeleteFileW( oldpath );
2527 success = CreateDirectoryW( oldpath, NULL );
2528 ok( success != 0, "failed to create temp directory\n" );
2529 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2530 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2532 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2533 ok( res != 0, "failed to create temp file\n" );
2534 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2535 DeleteFileW( newpath );
2536 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2537 fli->Flags = 0;
2538 fli->RootDirectory = NULL;
2539 fli->FileNameLength = name_str.Length;
2540 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2541 pRtlFreeUnicodeString( &name_str );
2543 io.Status = 0xdeadbeef;
2544 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2545 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY ,
2546 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2547 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2548 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2549 ok( !fileDeleted, "file should exist\n" );
2550 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2551 ok( fileDeleted, "file should not exist\n" );
2553 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2554 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2555 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2556 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2557 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2558 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2559 HeapFree( GetProcessHeap(), 0, fni );
2561 CloseHandle( handle );
2562 HeapFree( GetProcessHeap(), 0, fli );
2563 delete_object( oldpath );
2564 delete_object( newpath );
2566 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2567 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2568 ok( res != 0, "failed to create temp file\n" );
2569 DeleteFileW( oldpath );
2570 success = CreateDirectoryW( oldpath, NULL );
2571 ok( success != 0, "failed to create temp directory\n" );
2572 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2573 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2575 lstrcpyW( newpath, oldpath );
2576 lstrcatW( newpath, foo_txtW );
2577 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2578 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2580 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2581 ok( res != 0, "failed to create temp file\n" );
2582 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2583 DeleteFileW( newpath );
2584 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2585 fli->Flags = 0;
2586 fli->RootDirectory = NULL;
2587 fli->FileNameLength = name_str.Length;
2588 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2589 pRtlFreeUnicodeString( &name_str );
2591 io.Status = 0xdeadbeef;
2592 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2593 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2594 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2595 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2596 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2597 ok( !fileDeleted, "file should exist\n" );
2598 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2599 ok( fileDeleted, "file should not exist\n" );
2601 CloseHandle( handle );
2602 CloseHandle( handle2 );
2603 HeapFree( GetProcessHeap(), 0, fli );
2604 delete_object( oldpath );
2605 delete_object( newpath );
2607 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2608 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2609 ok( res != 0, "failed to create temp file\n" );
2610 DeleteFileW( oldpath );
2611 success = CreateDirectoryW( oldpath, NULL );
2612 ok( success != 0, "failed to create temp directory\n" );
2613 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2614 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2616 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2617 ok( res != 0, "failed to create temp file\n" );
2618 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2619 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2620 fli->Flags = 0;
2621 fli->RootDirectory = NULL;
2622 fli->FileNameLength = name_str.Length;
2623 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2624 pRtlFreeUnicodeString( &name_str );
2626 io.Status = 0xdeadbeef;
2627 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2628 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2629 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2630 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2631 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2632 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2633 ok( !fileDeleted, "file should exist\n" );
2634 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2635 ok( !fileDeleted, "file should exist\n" );
2637 CloseHandle( handle );
2638 HeapFree( GetProcessHeap(), 0, fli );
2639 delete_object( oldpath );
2640 delete_object( newpath );
2642 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2643 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2644 ok( res != 0, "failed to create temp file\n" );
2645 DeleteFileW( oldpath );
2646 success = CreateDirectoryW( oldpath, NULL );
2647 ok( success != 0, "failed to create temp directory\n" );
2648 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2649 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2651 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2652 ok( res != 0, "failed to create temp file\n" );
2653 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2654 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2656 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2657 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2658 fli->Flags = 0;
2659 fli->RootDirectory = NULL;
2660 fli->FileNameLength = name_str.Length;
2661 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2662 pRtlFreeUnicodeString( &name_str );
2664 io.Status = 0xdeadbeef;
2665 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2666 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2667 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2668 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2669 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2670 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2671 ok( !fileDeleted, "file should exist\n" );
2672 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2673 ok( !fileDeleted, "file should exist\n" );
2675 CloseHandle( handle );
2676 CloseHandle( handle2 );
2677 HeapFree( GetProcessHeap(), 0, fli );
2678 delete_object( oldpath );
2679 delete_object( newpath );
2681 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2682 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2683 ok( res != 0, "failed to create temp file\n" );
2684 DeleteFileW( oldpath );
2685 success = CreateDirectoryW( oldpath, NULL );
2686 ok( success != 0, "failed to create temp directory\n" );
2687 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2688 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2690 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2691 ok( res != 0, "failed to create temp file\n" );
2692 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2693 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2694 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2695 fli->RootDirectory = NULL;
2696 fli->FileNameLength = name_str.Length;
2697 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2698 pRtlFreeUnicodeString( &name_str );
2700 io.Status = 0xdeadbeef;
2701 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2702 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2703 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2704 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2705 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2706 ok( !fileDeleted, "file should exist\n" );
2707 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2708 ok( !fileDeleted, "file should exist\n" );
2710 CloseHandle( handle );
2711 HeapFree( GetProcessHeap(), 0, fli );
2712 delete_object( oldpath );
2713 delete_object( newpath );
2715 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2716 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2717 ok( res != 0, "failed to create temp file\n" );
2718 DeleteFileW( oldpath );
2719 success = CreateDirectoryW( oldpath, NULL );
2720 ok( success != 0, "failed to create temp directory\n" );
2721 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2722 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2724 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2725 ok( res != 0, "failed to create temp file\n" );
2726 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2727 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2729 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2730 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2731 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2732 fli->RootDirectory = NULL;
2733 fli->FileNameLength = name_str.Length;
2734 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2735 pRtlFreeUnicodeString( &name_str );
2737 io.Status = 0xdeadbeef;
2738 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2739 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2740 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2741 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2742 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2743 ok( !fileDeleted, "file should exist\n" );
2744 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2745 ok( !fileDeleted, "file should exist\n" );
2747 CloseHandle( handle );
2748 CloseHandle( handle2 );
2749 HeapFree( GetProcessHeap(), 0, fli );
2750 delete_object( oldpath );
2751 delete_object( newpath );
2753 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2754 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2755 ok( res != 0, "failed to create temp file\n" );
2756 DeleteFileW( oldpath );
2757 success = CreateDirectoryW( oldpath, NULL );
2758 ok( success != 0, "failed to create temp directory\n" );
2759 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2760 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2762 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2763 ok( res != 0, "failed to create temp file\n" );
2764 DeleteFileW( newpath );
2765 success = CreateDirectoryW( newpath, NULL );
2766 ok( success != 0, "failed to create temp directory\n" );
2767 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2768 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2769 fli->Flags = 0;
2770 fli->RootDirectory = NULL;
2771 fli->FileNameLength = name_str.Length;
2772 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2773 pRtlFreeUnicodeString( &name_str );
2775 io.Status = 0xdeadbeef;
2776 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2777 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2778 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2779 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2780 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, 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 directory, newpath is a directory, ReplaceIfExists = TRUE */
2792 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2793 ok( res != 0, "failed to create temp file\n" );
2794 DeleteFileW( oldpath );
2795 success = CreateDirectoryW( oldpath, NULL );
2796 ok( success != 0, "failed to create temp directory\n" );
2797 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2798 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2800 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2801 ok( res != 0, "failed to create temp file\n" );
2802 DeleteFileW( newpath );
2803 success = CreateDirectoryW( newpath, NULL );
2804 ok( success != 0, "failed to create temp directory\n" );
2805 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2806 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2807 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2808 fli->RootDirectory = NULL;
2809 fli->FileNameLength = name_str.Length;
2810 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2811 pRtlFreeUnicodeString( &name_str );
2813 io.Status = 0xdeadbeef;
2814 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2815 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2816 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2817 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2818 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2819 ok( !fileDeleted, "file should exist\n" );
2820 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2821 ok( !fileDeleted, "file should exist\n" );
2823 CloseHandle( handle );
2824 HeapFree( GetProcessHeap(), 0, fli );
2825 delete_object( oldpath );
2826 delete_object( newpath );
2828 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2829 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2830 ok( res != 0, "failed to create temp file\n" );
2831 DeleteFileW( oldpath );
2832 success = CreateDirectoryW( oldpath, NULL );
2833 ok( success != 0, "failed to create temp directory\n" );
2834 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2835 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2837 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2838 ok( res != 0, "failed to create temp file\n" );
2839 DeleteFileW( newpath );
2840 success = CreateDirectoryW( newpath, NULL );
2841 ok( success != 0, "failed to create temp directory\n" );
2842 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2843 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2845 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2846 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2847 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2848 fli->RootDirectory = NULL;
2849 fli->FileNameLength = name_str.Length;
2850 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2851 pRtlFreeUnicodeString( &name_str );
2853 io.Status = 0xdeadbeef;
2854 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2855 ok( io.Status == 0xdeadbeef || io.Status == STATUS_FILE_IS_A_DIRECTORY,
2856 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io.Status );
2857 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res );
2858 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2859 ok( !fileDeleted, "file should exist\n" );
2860 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2861 ok( !fileDeleted, "file should exist\n" );
2863 CloseHandle( handle );
2864 CloseHandle( handle2 );
2865 HeapFree( GetProcessHeap(), 0, fli );
2866 delete_object( oldpath );
2867 delete_object( newpath );
2869 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2870 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2871 ok( res != 0, "failed to create temp file\n" );
2872 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2873 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2875 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2876 ok( res != 0, "failed to create temp file\n" );
2877 DeleteFileW( newpath );
2878 success = CreateDirectoryW( newpath, NULL );
2879 ok( success != 0, "failed to create temp directory\n" );
2880 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2881 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2882 fli->Flags = 0;
2883 fli->RootDirectory = NULL;
2884 fli->FileNameLength = name_str.Length;
2885 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2886 pRtlFreeUnicodeString( &name_str );
2888 io.Status = 0xdeadbeef;
2889 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2890 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2891 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res );
2892 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2893 ok( !fileDeleted, "file should exist\n" );
2894 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2895 ok( !fileDeleted, "file should exist\n" );
2897 CloseHandle( handle );
2898 HeapFree( GetProcessHeap(), 0, fli );
2899 delete_object( oldpath );
2900 delete_object( newpath );
2902 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2903 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2904 ok( res != 0, "failed to create temp file\n" );
2905 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2906 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2908 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2909 ok( res != 0, "failed to create temp file\n" );
2910 DeleteFileW( newpath );
2911 success = CreateDirectoryW( newpath, NULL );
2912 ok( success != 0, "failed to create temp directory\n" );
2913 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2914 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2915 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2916 fli->RootDirectory = NULL;
2917 fli->FileNameLength = name_str.Length;
2918 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2919 pRtlFreeUnicodeString( &name_str );
2921 io.Status = 0xdeadbeef;
2922 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2923 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
2924 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
2925 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2926 ok( !fileDeleted, "file should exist\n" );
2927 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2928 ok( !fileDeleted, "file should exist\n" );
2930 CloseHandle( handle );
2931 HeapFree( GetProcessHeap(), 0, fli );
2932 delete_object( oldpath );
2933 delete_object( newpath );
2935 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2936 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2937 ok( res != 0, "failed to create temp file\n" );
2938 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2939 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2941 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2942 ok( res != 0, "failed to create temp file\n" );
2943 DeleteFileW( newpath );
2944 for (filename = newpath, p = newpath; *p; p++)
2945 if (*p == '\\') filename = p + 1;
2946 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2947 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2949 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2950 fli->Flags = 0;
2951 fli->RootDirectory = handle2;
2952 fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2953 memcpy( fli->FileName, filename, fli->FileNameLength );
2955 io.Status = 0xdeadbeef;
2956 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2957 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
2958 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2959 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2960 ok( !fileDeleted, "file should exist\n" );
2961 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2962 ok( !fileDeleted, "file should exist\n" );
2964 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2965 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2966 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
2967 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2968 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2969 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2970 HeapFree( GetProcessHeap(), 0, fni );
2972 CloseHandle( handle );
2973 CloseHandle( handle2 );
2974 HeapFree( GetProcessHeap(), 0, fli );
2975 delete_object( oldpath );
2976 delete_object( newpath );
2978 /* oldpath == newpath */
2979 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2980 ok( res != 0, "failed to create temp file\n" );
2981 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2982 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2984 pRtlDosPathNameToNtPathName_U( oldpath, &name_str, NULL, NULL );
2985 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2986 fli->Flags = 0;
2987 fli->RootDirectory = NULL;
2988 fli->FileNameLength = name_str.Length;
2989 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2990 pRtlFreeUnicodeString( &name_str );
2992 io.Status = 0xdeadbeef;
2993 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
2994 todo_wine ok( io.Status == 0xdeadbeef, "got io status %#lx\n", io.Status );
2995 ok( res == STATUS_OBJECT_NAME_COLLISION, "got status %lx\n", res );
2997 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
2998 io.Status = 0xdeadbeef;
2999 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
3000 ok( io.Status == STATUS_SUCCESS, "got io status %#lx\n", io.Status );
3001 ok( res == STATUS_SUCCESS, "got status %lx\n", res );
3002 ok( GetFileAttributesW( oldpath ) != INVALID_FILE_ATTRIBUTES, "file should exist\n" );
3004 CloseHandle( handle );
3005 HeapFree( GetProcessHeap(), 0, fli );
3006 delete_object( oldpath );
3008 /* oldpath == newpath, different casing on link */
3009 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
3010 ok( res != 0, "failed to create temp file\n" );
3011 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3012 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
3014 wcsrchr( oldpath, '\\' )[1] = 'F';
3015 pRtlDosPathNameToNtPathName_U( oldpath, &name_str, NULL, NULL );
3016 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
3017 fli->Flags = 0;
3018 fli->RootDirectory = NULL;
3019 fli->FileNameLength = name_str.Length;
3020 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
3021 pRtlFreeUnicodeString( &name_str );
3023 io.Status = 0xdeadbeef;
3024 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
3025 todo_wine ok( io.Status == 0xdeadbeef, "got io status %#lx\n", io.Status );
3026 ok( res == STATUS_OBJECT_NAME_COLLISION, "got status %lx\n", res );
3028 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
3029 io.Status = 0xdeadbeef;
3030 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, class );
3031 ok( io.Status == STATUS_SUCCESS, "got io status %#lx\n", io.Status );
3032 ok( res == STATUS_SUCCESS, "got status %lx\n", res );
3033 ok( GetFileAttributesW( oldpath ) != INVALID_FILE_ATTRIBUTES, "file should exist\n" );
3035 CloseHandle( handle );
3036 handle = FindFirstFileW( oldpath, &find_data );
3037 ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileW: failed, error %ld\n", GetLastError());
3038 if (handle != INVALID_HANDLE_VALUE)
3040 todo_wine ok(!lstrcmpW(wcsrchr(oldpath, '\\') + 1, find_data.cFileName),
3041 "Link did not change casing on same file: got %s\n", wine_dbgstr_w(find_data.cFileName));
3044 FindClose( handle );
3045 HeapFree( GetProcessHeap(), 0, fli );
3046 delete_object( oldpath );
3049 static void test_file_link_information_ex(void)
3051 static const WCHAR fooW[] = {'f','o','o',0};
3052 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16];
3053 FILE_LINK_INFORMATION *fli;
3054 BOOL fileDeleted;
3055 UNICODE_STRING name_str;
3056 HANDLE handle, handle2;
3057 IO_STATUS_BLOCK io;
3058 NTSTATUS res;
3060 GetTempPathW( MAX_PATH, tmp_path );
3062 /* oldpath is a file, newpath is a read-only file, with FILE_LINK_REPLACE_IF_EXISTS */
3063 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
3064 ok( res != 0, "failed to create temp file\n" );
3065 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3066 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
3068 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
3069 ok( res != 0, "failed to create temp file\n" );
3070 DeleteFileW( newpath );
3071 handle2 = CreateFileW( newpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0 );
3072 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
3073 CloseHandle( handle2 );
3074 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
3075 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
3076 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS;
3077 fli->RootDirectory = NULL;
3078 fli->FileNameLength = name_str.Length;
3079 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
3080 pRtlFreeUnicodeString( &name_str );
3082 io.Status = 0xdeadbeef;
3083 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformationEx );
3085 if (res == STATUS_NOT_IMPLEMENTED || res == STATUS_INVALID_INFO_CLASS)
3087 win_skip( "FileLinkInformationEx not supported\n" );
3088 CloseHandle( handle );
3089 HeapFree( GetProcessHeap(), 0, fli );
3090 delete_object( oldpath );
3091 return;
3094 todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io.Status );
3095 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %lx\n", res );
3096 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3097 ok( !fileDeleted, "file should exist\n" );
3098 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3099 ok( !fileDeleted, "file should exist\n" );
3101 CloseHandle( handle );
3102 HeapFree( GetProcessHeap(), 0, fli );
3103 delete_object( oldpath );
3104 delete_object( newpath );
3106 /* oldpath is a file, newpath is a read-only file, with FILE_LINK_REPLACE_IF_EXISTS and FILE_LINK_IGNORE_READONLY_ATTRIBUTE */
3107 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
3108 ok( res != 0, "failed to create temp file\n" );
3109 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3110 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
3112 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
3113 ok( res != 0, "failed to create temp file\n" );
3114 DeleteFileW( newpath );
3115 handle2 = CreateFileW( newpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0 );
3116 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
3117 CloseHandle( handle2 );
3118 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
3119 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
3120 fli->Flags = FILE_LINK_REPLACE_IF_EXISTS | FILE_LINK_IGNORE_READONLY_ATTRIBUTE;
3121 fli->RootDirectory = NULL;
3122 fli->FileNameLength = name_str.Length;
3123 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
3124 pRtlFreeUnicodeString( &name_str );
3126 io.Status = 0xdeadbeef;
3127 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformationEx );
3128 ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %lx\n", io.Status );
3129 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %lx\n", res );
3130 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3131 ok( !fileDeleted, "file should exist\n" );
3132 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3133 ok( !fileDeleted, "file should exist\n" );
3135 CloseHandle( handle );
3136 HeapFree( GetProcessHeap(), 0, fli );
3137 delete_object( oldpath );
3138 delete_object( newpath );
3141 static void test_file_both_information(void)
3143 IO_STATUS_BLOCK io;
3144 FILE_BOTH_DIR_INFORMATION fbi;
3145 HANDLE h;
3146 int res;
3148 if (!(h = create_temp_file(0))) return;
3150 memset(&fbi, 0, sizeof(fbi));
3151 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
3152 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
3154 CloseHandle( h );
3157 static NTSTATUS nt_get_file_attrs(const char *name, DWORD *attrs)
3159 WCHAR nameW[MAX_PATH];
3160 FILE_BASIC_INFORMATION info;
3161 UNICODE_STRING nt_name;
3162 OBJECT_ATTRIBUTES attr;
3163 NTSTATUS status;
3165 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, MAX_PATH );
3167 *attrs = INVALID_FILE_ATTRIBUTES;
3169 if (!pRtlDosPathNameToNtPathName_U( nameW, &nt_name, NULL, NULL ))
3170 return STATUS_UNSUCCESSFUL;
3172 attr.Length = sizeof(attr);
3173 attr.RootDirectory = 0;
3174 attr.Attributes = OBJ_CASE_INSENSITIVE;
3175 attr.ObjectName = &nt_name;
3176 attr.SecurityDescriptor = NULL;
3177 attr.SecurityQualityOfService = NULL;
3179 status = pNtQueryAttributesFile( &attr, &info );
3180 pRtlFreeUnicodeString( &nt_name );
3182 if (status == STATUS_SUCCESS)
3183 *attrs = info.FileAttributes;
3185 return status;
3188 static void test_file_disposition_information(void)
3190 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
3191 DWORD dirpos;
3192 HANDLE handle, handle2, handle3, mapping;
3193 NTSTATUS res;
3194 IO_STATUS_BLOCK io;
3195 FILE_DISPOSITION_INFORMATION fdi;
3196 FILE_DISPOSITION_INFORMATION_EX fdie;
3197 FILE_STANDARD_INFORMATION fsi;
3198 BOOL fileDeleted;
3199 DWORD fdi2, size;
3200 void *view;
3202 GetTempPathA( MAX_PATH, tmp_path );
3204 /* tests for info struct size */
3205 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3206 handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3207 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3208 res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
3209 todo_wine
3210 ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %lx\n", res );
3211 fdi2 = 0x100;
3212 res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
3213 ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %lx\n", res );
3214 CloseHandle( handle );
3215 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3216 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3217 DeleteFileA( buffer );
3219 /* cannot set disposition on file not opened with delete access */
3220 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3221 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3222 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3223 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3224 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %lx)\n", res );
3225 fdi.DoDeleteFile = TRUE;
3226 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3227 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %lx)\n", res );
3228 CloseHandle( handle );
3229 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3230 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3231 DeleteFileA( buffer );
3233 /* can set disposition on file opened with proper access */
3234 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3235 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
3236 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3237 fdi.DoDeleteFile = TRUE;
3238 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3239 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3240 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3241 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3242 todo_wine
3243 ok(fsi.DeletePending, "Handle should be marked for deletion\n");
3244 CloseHandle( handle );
3245 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3246 ok( fileDeleted, "File should have been deleted\n" );
3248 /* file exists until all handles to it get closed */
3249 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3250 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3251 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3252 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3253 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
3254 fdi.DoDeleteFile = TRUE;
3255 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3256 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3257 res = nt_get_file_attrs( buffer, &fdi2 );
3258 todo_wine
3259 ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res );
3260 /* can't open the deleted file */
3261 handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3262 todo_wine
3263 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3264 if (handle3 != INVALID_HANDLE_VALUE)
3265 CloseHandle( handle3 );
3266 todo_wine
3267 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3268 /* can't open the deleted file (wrong sharing mode) */
3269 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, 0, 0);
3270 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3271 todo_wine
3272 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3273 CloseHandle( handle );
3274 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3275 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3276 CloseHandle( handle2 );
3277 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3278 ok( fileDeleted, "File should have been deleted\n" );
3280 /* file exists until all handles to it get closed */
3281 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3282 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
3283 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3284 /* can open the marked for delete file (proper sharing mode) */
3285 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3286 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
3287 res = nt_get_file_attrs( buffer, &fdi2 );
3288 ok( res == STATUS_SUCCESS, "got %#lx\n", res );
3289 /* can't open the marked for delete file (wrong sharing mode) */
3290 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, 0, 0);
3291 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3292 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3293 CloseHandle( handle );
3294 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3295 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3296 CloseHandle( handle2 );
3297 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3298 ok( fileDeleted, "File should have been deleted\n" );
3300 /* file is deleted after handle with FILE_DISPOSITION_POSIX_SEMANTICS is closed */
3301 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3302 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3303 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3304 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3305 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3306 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
3307 fdie.Flags = FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS;
3308 res = pNtSetInformationFile( handle, &io, &fdie, sizeof fdie, FileDispositionInformationEx );
3309 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_SUCCESS,
3310 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res );
3311 CloseHandle( handle );
3312 if ( res == STATUS_SUCCESS )
3314 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3315 ok( fileDeleted, "File should have been deleted\n" );
3317 CloseHandle( handle2 );
3319 /* file is deleted after handle with FILE_DISPOSITION_POSIX_SEMANTICS is closed */
3320 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3321 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3322 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3323 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3324 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3325 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
3326 fdie.Flags = FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS;
3327 res = pNtSetInformationFile( handle, &io, &fdie, sizeof fdie, FileDispositionInformationEx );
3328 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_SUCCESS,
3329 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res );
3330 CloseHandle( handle2 );
3331 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3332 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3333 CloseHandle( handle );
3334 if ( res == STATUS_SUCCESS )
3336 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3337 ok( fileDeleted, "File should have been deleted\n" );
3340 /* cannot set disposition on readonly file */
3341 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3342 DeleteFileA( buffer );
3343 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
3344 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3345 fdi.DoDeleteFile = TRUE;
3346 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3347 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %lx)\n", res );
3348 CloseHandle( handle );
3349 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3350 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3351 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
3352 DeleteFileA( buffer );
3354 /* cannot set disposition on readonly file */
3355 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3356 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
3357 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3358 fdi.DoDeleteFile = TRUE;
3359 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3360 todo_wine
3361 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %lx)\n", res );
3362 CloseHandle( handle );
3363 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3364 todo_wine
3365 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3366 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
3367 DeleteFileA( buffer );
3369 /* set disposition on readonly file ignoring readonly attribute */
3370 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3371 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3372 DeleteFileA( buffer );
3373 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
3374 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3375 fdie.Flags = FILE_DISPOSITION_DELETE | FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE;
3376 res = pNtSetInformationFile( handle, &io, &fdie, sizeof fdie, FileDispositionInformationEx );
3377 ok( res == STATUS_SUCCESS
3378 || broken(res == STATUS_INVALID_INFO_CLASS) /* win10 1507 & 32-bit 1607 */
3379 || broken(res == STATUS_NOT_SUPPORTED), /* win10 1709 & 64-bit 1607 */
3380 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res );
3381 CloseHandle( handle );
3382 if ( res == STATUS_SUCCESS )
3384 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3385 ok( fileDeleted, "File should have been deleted\n" );
3387 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
3388 DeleteFileA( buffer );
3390 /* can set disposition on file and then reset it */
3391 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3392 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
3393 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3394 fdi.DoDeleteFile = TRUE;
3395 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3396 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3397 fdi.DoDeleteFile = FALSE;
3398 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3399 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3400 CloseHandle( handle );
3401 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3402 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3403 DeleteFileA( buffer );
3405 /* can't reset disposition if delete-on-close flag is specified */
3406 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3407 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
3408 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3409 fdi.DoDeleteFile = FALSE;
3410 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3411 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3412 CloseHandle( handle );
3413 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3414 ok( fileDeleted, "File should have been deleted\n" );
3416 /* can't reset disposition on duplicated handle if delete-on-close flag is specified */
3417 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3418 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
3419 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3420 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
3421 CloseHandle( handle );
3422 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3423 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3424 fdi.DoDeleteFile = FALSE;
3425 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
3426 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3427 CloseHandle( handle2 );
3428 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3429 ok( fileDeleted, "File should have been deleted\n" );
3431 /* can reset delete-on-close flag through FileDispositionInformationEx */
3432 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3433 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3434 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
3435 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3436 fdie.Flags = FILE_DISPOSITION_ON_CLOSE;
3437 res = pNtSetInformationFile( handle, &io, &fdie, sizeof fdie, FileDispositionInformationEx );
3438 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_SUCCESS,
3439 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res );
3440 CloseHandle( handle );
3441 if ( res == STATUS_SUCCESS )
3443 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3444 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3445 DeleteFileA( buffer );
3448 /* DeleteFile fails for wrong sharing mode */
3449 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3450 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
3451 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3452 fileDeleted = DeleteFileA( buffer );
3453 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3454 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3455 CloseHandle( handle );
3456 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3457 ok( !fileDeleted, "File shouldn't have been deleted\n" );
3458 DeleteFileA( buffer );
3460 /* DeleteFile succeeds for proper sharing mode */
3461 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3462 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3463 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3464 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3465 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3466 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3467 fileDeleted = DeleteFileA( buffer );
3468 ok( fileDeleted, "File should have been deleted\n" );
3469 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3470 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3471 todo_wine
3472 ok(fsi.DeletePending, "Handle should be marked for deletion\n");
3473 res = nt_get_file_attrs( buffer, &fdi2 );
3474 todo_wine
3475 ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res );
3476 /* can't open the deleted file */
3477 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3478 todo_wine
3479 ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3480 todo_wine
3481 ok( GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError());
3482 if (handle2 != INVALID_HANDLE_VALUE)
3483 CloseHandle( handle2);
3484 CloseHandle( handle );
3485 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3486 ok( fileDeleted, "File should have been deleted\n" );
3488 /* can set disposition on a directory opened with proper access */
3489 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3490 DeleteFileA( buffer );
3491 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3492 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3493 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3494 fdi.DoDeleteFile = TRUE;
3495 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3496 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3497 CloseHandle( handle );
3498 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3499 ok( fileDeleted, "Directory should have been deleted\n" );
3501 /* RemoveDirectory fails for wrong sharing mode */
3502 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3503 DeleteFileA( buffer );
3504 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3505 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3506 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3507 fileDeleted = RemoveDirectoryA( buffer );
3508 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3509 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3510 CloseHandle( handle );
3511 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3512 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3513 RemoveDirectoryA( buffer );
3515 /* RemoveDirectory succeeds for proper sharing mode */
3516 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3517 DeleteFileA( buffer );
3518 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3519 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3520 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3521 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3522 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3523 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3524 fileDeleted = RemoveDirectoryA( buffer );
3525 ok( fileDeleted, "Directory should have been deleted\n" );
3526 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3527 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3528 todo_wine
3529 ok(fsi.DeletePending, "Handle should be marked for deletion\n");
3530 res = nt_get_file_attrs( buffer, &fdi2 );
3531 todo_wine
3532 ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res );
3533 /* can't open the deleted directory */
3534 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3535 todo_wine
3536 ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3537 todo_wine
3538 ok(GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError());
3539 if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2 );
3540 CloseHandle( handle );
3541 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3542 ok( fileDeleted, "Directory should have been deleted\n" );
3544 /* directory exists until all handles to it get closed */
3545 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3546 DeleteFileA( buffer );
3547 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3548 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3549 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3550 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3551 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3552 fdi.DoDeleteFile = TRUE;
3553 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
3554 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res );
3555 res = nt_get_file_attrs( buffer, &fdi2 );
3556 todo_wine
3557 ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res );
3558 /* can't open the deleted directory */
3559 handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3560 todo_wine
3561 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3562 if (handle3 != INVALID_HANDLE_VALUE)
3563 CloseHandle( handle3 );
3564 todo_wine
3565 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3566 /* can't open the deleted directory (wrong sharing mode) */
3567 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3568 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3569 todo_wine
3570 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError());
3571 CloseHandle( handle2 );
3572 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3573 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3574 CloseHandle( handle );
3575 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3576 ok( fileDeleted, "Directory should have been deleted\n" );
3578 /* directory exists until all handles to it get closed */
3579 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3580 DeleteFileA( buffer );
3581 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3582 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
3583 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3584 /* can open the marked for delete directory (proper sharing mode) */
3585 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3586 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3587 /* can't open the marked for delete file (wrong sharing mode) */
3588 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3589 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
3590 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %lu\n", GetLastError());
3591 CloseHandle( handle );
3592 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3593 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3594 CloseHandle( handle2 );
3595 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3596 ok( fileDeleted, "Directory should have been deleted\n" );
3598 /* can open a non-empty directory with FILE_FLAG_DELETE_ON_CLOSE */
3599 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3600 DeleteFileA( buffer );
3601 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3602 dirpos = lstrlenA( buffer );
3603 lstrcpyA( buffer + dirpos, "\\tst" );
3604 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3605 CloseHandle( handle2 );
3606 buffer[dirpos] = '\0';
3607 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
3608 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3609 SetLastError(0xdeadbeef);
3610 CloseHandle( handle );
3611 ok(GetLastError() == 0xdeadbeef, "got %lu\n", GetLastError());
3612 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3613 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3614 buffer[dirpos] = '\\';
3615 fileDeleted = DeleteFileA( buffer );
3616 ok( fileDeleted, "File should have been deleted\n" );
3617 buffer[dirpos] = '\0';
3618 fileDeleted = RemoveDirectoryA( buffer );
3619 ok( fileDeleted, "Directory should have been deleted\n" );
3621 /* cannot set disposition on a non-empty directory */
3622 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3623 DeleteFileA( buffer );
3624 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3625 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3626 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3627 dirpos = lstrlenA( buffer );
3628 lstrcpyA( buffer + dirpos, "\\tst" );
3629 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3630 CloseHandle( handle2 );
3631 fdi.DoDeleteFile = TRUE;
3632 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3633 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %lx)\n", res );
3634 fileDeleted = DeleteFileA( buffer );
3635 ok( fileDeleted, "File should have been deleted\n" );
3636 buffer[dirpos] = '\0';
3637 CloseHandle( handle );
3638 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3639 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3640 fileDeleted = RemoveDirectoryA( buffer );
3641 ok( fileDeleted, "Directory should have been deleted\n" );
3643 /* a file with an open mapping handle cannot be deleted */
3645 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3646 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3647 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3648 WriteFile(handle, "data", 4, &size, NULL);
3649 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3650 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3652 fdi.DoDeleteFile = FALSE;
3653 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3654 ok( !res, "got %#lx\n", res );
3656 fdi.DoDeleteFile = TRUE;
3657 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3658 ok( res == STATUS_CANNOT_DELETE, "got %#lx\n", res );
3659 res = GetFileAttributesA( buffer );
3660 ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
3662 CloseHandle( mapping );
3663 CloseHandle( handle );
3664 res = DeleteFileA( buffer );
3665 ok( res, "got error %lu\n", GetLastError() );
3667 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3668 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3669 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3670 WriteFile(handle, "data", 4, &size, NULL);
3671 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3672 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3673 CloseHandle( mapping );
3675 fdi.DoDeleteFile = TRUE;
3676 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3677 ok( !res, "got %#lx\n", res );
3679 CloseHandle( handle );
3680 res = DeleteFileA( buffer );
3681 ok( !res, "expected failure\n" );
3682 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError() );
3684 /* a file with an open view cannot be deleted */
3686 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3687 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3688 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3689 WriteFile(handle, "data", 4, &size, NULL);
3690 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3691 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3692 view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4 );
3693 ok( !!view, "failed to map view, error %lu\n", GetLastError() );
3694 CloseHandle( mapping );
3696 fdi.DoDeleteFile = FALSE;
3697 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3698 ok( !res, "got %#lx\n", res );
3700 fdi.DoDeleteFile = TRUE;
3701 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3702 ok( res == STATUS_CANNOT_DELETE, "got %#lx\n", res );
3703 res = GetFileAttributesA( buffer );
3704 ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
3706 UnmapViewOfFile( view );
3707 CloseHandle( handle );
3708 res = DeleteFileA( buffer );
3709 ok( res, "got error %lu\n", GetLastError() );
3711 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3712 handle = CreateFileA( buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
3713 ok( handle != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
3714 WriteFile(handle, "data", 4, &size, NULL);
3715 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY, 0, 4, NULL );
3716 ok( !!mapping, "failed to create mapping, error %lu\n", GetLastError() );
3717 view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4 );
3718 ok( !!view, "failed to map view, error %lu\n", GetLastError() );
3719 CloseHandle( mapping );
3720 UnmapViewOfFile( view );
3722 fdi.DoDeleteFile = TRUE;
3723 res = pNtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation );
3724 ok( !res, "got %#lx\n", res );
3726 CloseHandle( handle );
3727 res = DeleteFileA( buffer );
3728 ok( !res, "expected failure\n" );
3729 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError() );
3731 /* pending delete flag is shared across handles */
3732 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3733 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3734 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3735 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3736 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3737 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3738 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3739 ok( handle2 != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3740 res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation);
3741 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3742 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3743 fdi.DoDeleteFile = TRUE;
3744 res = NtSetInformationFile(handle, &io, &fdi, sizeof(fdi), FileDispositionInformation);
3745 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3746 res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation);
3747 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3748 todo_wine
3749 ok(fsi.DeletePending, "Handle should be marked for deletion\n");
3750 fdi.DoDeleteFile = FALSE;
3751 res = NtSetInformationFile(handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation);
3752 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3753 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3754 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3755 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3756 CloseHandle(handle);
3757 CloseHandle(handle2);
3758 res = GetFileAttributesA( buffer );
3759 todo_wine
3760 ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
3762 /* pending delete flag is shared across handles (even after closing) */
3763 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3764 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
3765 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3766 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3767 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3768 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3769 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
3770 ok( handle2 != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
3771 res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation);
3772 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3773 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3774 fdi.DoDeleteFile = TRUE;
3775 res = NtSetInformationFile(handle, &io, &fdi, sizeof(fdi), FileDispositionInformation);
3776 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3777 res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation);
3778 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3779 todo_wine
3780 ok(fsi.DeletePending, "Handle should be marked for deletion\n");
3781 fdi.DoDeleteFile = FALSE;
3782 res = NtSetInformationFile(handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation);
3783 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3784 CloseHandle(handle2);
3785 res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation);
3786 ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res);
3787 ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n");
3788 CloseHandle(handle);
3789 res = GetFileAttributesA( buffer );
3790 todo_wine
3791 ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
3794 static void test_file_name_information(void)
3796 WCHAR *file_name, *volume_prefix, *expected;
3797 FILE_NAME_INFORMATION *info;
3798 ULONG old_redir = 1, tmp;
3799 UINT file_name_size;
3800 IO_STATUS_BLOCK io;
3801 UINT info_size;
3802 HRESULT hr;
3803 HANDLE h;
3804 UINT len;
3806 /* GetVolumePathName is not present before w2k */
3807 if (!pGetVolumePathNameW) {
3808 win_skip("GetVolumePathNameW not found\n");
3809 return;
3812 file_name_size = GetSystemDirectoryW( NULL, 0 );
3813 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3814 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3815 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3817 len = GetSystemDirectoryW( file_name, file_name_size );
3818 ok(len == file_name_size - 1,
3819 "GetSystemDirectoryW returned %u, expected %u.\n",
3820 len, file_name_size - 1);
3822 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3823 ok(len, "GetVolumePathNameW failed.\n");
3825 len = lstrlenW( volume_prefix );
3826 if (len && volume_prefix[len - 1] == '\\') --len;
3827 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3828 expected[file_name_size - len - 1] = '\0';
3830 /* A bit more than we actually need, but it keeps the calculation simple. */
3831 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3832 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3834 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3835 h = CreateFileW( file_name, GENERIC_READ,
3836 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3837 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3838 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3839 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3841 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
3842 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#lx.\n", hr);
3844 memset( info, 0xcc, info_size );
3845 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
3846 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3847 hr, STATUS_BUFFER_OVERFLOW);
3848 ok(io.Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#lx, expected %#lx.\n",
3849 io.Status, STATUS_BUFFER_OVERFLOW);
3850 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %lu\n", info->FileNameLength);
3851 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
3852 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3853 "info->FileName[1] is %p, expected %p.\n",
3854 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3855 ok(io.Information == sizeof(*info), "io.Information is %Iu\n", io.Information);
3857 memset( info, 0xcc, info_size );
3858 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3859 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
3860 ok(io.Status == STATUS_SUCCESS, "io.Status is %#lx, expected %#lx.\n", io.Status, STATUS_SUCCESS);
3861 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %lu\n", info->FileNameLength);
3862 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
3863 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
3864 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3865 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3866 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3867 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
3868 "io.Information is %Iu, expected %lu.\n",
3869 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
3871 CloseHandle( h );
3872 HeapFree( GetProcessHeap(), 0, info );
3873 HeapFree( GetProcessHeap(), 0, expected );
3874 HeapFree( GetProcessHeap(), 0, volume_prefix );
3876 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3878 skip("Not running on WoW64, skipping test.\n");
3879 HeapFree( GetProcessHeap(), 0, file_name );
3880 return;
3883 h = CreateFileW( file_name, GENERIC_READ,
3884 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3885 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3886 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3887 HeapFree( GetProcessHeap(), 0, file_name );
3889 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3890 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3891 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3893 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3894 ok(len == file_name_size - 1,
3895 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3896 len, file_name_size - 1);
3898 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3899 ok(len, "GetVolumePathNameW failed.\n");
3901 len = lstrlenW( volume_prefix );
3902 if (len && volume_prefix[len - 1] == '\\') --len;
3903 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3904 expected[file_name_size - len - 1] = '\0';
3906 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3907 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3909 memset( info, 0xcc, info_size );
3910 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3911 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
3912 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3913 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3914 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3916 CloseHandle( h );
3917 HeapFree( GetProcessHeap(), 0, info );
3918 HeapFree( GetProcessHeap(), 0, expected );
3919 HeapFree( GetProcessHeap(), 0, volume_prefix );
3920 HeapFree( GetProcessHeap(), 0, file_name );
3923 static void test_file_all_name_information(void)
3925 WCHAR *file_name, *volume_prefix, *expected;
3926 FILE_ALL_INFORMATION *info;
3927 ULONG old_redir = 1, tmp;
3928 UINT file_name_size;
3929 IO_STATUS_BLOCK io;
3930 UINT info_size;
3931 HRESULT hr;
3932 HANDLE h;
3933 UINT len;
3935 /* GetVolumePathName is not present before w2k */
3936 if (!pGetVolumePathNameW) {
3937 win_skip("GetVolumePathNameW not found\n");
3938 return;
3941 file_name_size = GetSystemDirectoryW( NULL, 0 );
3942 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3943 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3944 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3946 len = GetSystemDirectoryW( file_name, file_name_size );
3947 ok(len == file_name_size - 1,
3948 "GetSystemDirectoryW returned %u, expected %u.\n",
3949 len, file_name_size - 1);
3951 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3952 ok(len, "GetVolumePathNameW failed.\n");
3954 len = lstrlenW( volume_prefix );
3955 if (len && volume_prefix[len - 1] == '\\') --len;
3956 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3957 expected[file_name_size - len - 1] = '\0';
3959 /* A bit more than we actually need, but it keeps the calculation simple. */
3960 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3961 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3963 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3964 h = CreateFileW( file_name, GENERIC_READ,
3965 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3966 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3967 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3968 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3970 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
3971 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3972 hr, STATUS_INFO_LENGTH_MISMATCH);
3974 memset( info, 0xcc, info_size );
3975 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
3976 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3977 hr, STATUS_BUFFER_OVERFLOW);
3978 ok(io.Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#lx, expected %#lx.\n",
3979 io.Status, STATUS_BUFFER_OVERFLOW);
3980 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3981 "info->NameInformation.FileNameLength is %lu\n", info->NameInformation.FileNameLength );
3982 ok(info->NameInformation.FileName[2] == 0xcccc,
3983 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
3984 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3985 "info->NameInformation.FileName[1] is %p, expected %p.\n",
3986 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3987 ok(io.Information == sizeof(*info), "io.Information is %Iu\n", io.Information);
3989 memset( info, 0xcc, info_size );
3990 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3991 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
3992 ok(io.Status == STATUS_SUCCESS, "io.Status is %#lx, expected %#lx.\n", io.Status, STATUS_SUCCESS);
3993 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3994 "info->NameInformation.FileNameLength is %lu\n", info->NameInformation.FileNameLength );
3995 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
3996 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3997 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
3998 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3999 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
4000 "info->NameInformation.FileName is %s, expected %s.\n",
4001 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
4002 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
4003 + info->NameInformation.FileNameLength,
4004 "io.Information is %Iu\n", io.Information );
4006 CloseHandle( h );
4007 HeapFree( GetProcessHeap(), 0, info );
4008 HeapFree( GetProcessHeap(), 0, expected );
4009 HeapFree( GetProcessHeap(), 0, volume_prefix );
4011 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
4013 skip("Not running on WoW64, skipping test.\n");
4014 HeapFree( GetProcessHeap(), 0, file_name );
4015 return;
4018 h = CreateFileW( file_name, GENERIC_READ,
4019 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4020 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
4021 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
4022 HeapFree( GetProcessHeap(), 0, file_name );
4024 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
4025 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
4026 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
4028 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
4029 ok(len == file_name_size - 1,
4030 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
4031 len, file_name_size - 1);
4033 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
4034 ok(len, "GetVolumePathNameW failed.\n");
4036 len = lstrlenW( volume_prefix );
4037 if (len && volume_prefix[len - 1] == '\\') --len;
4038 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
4039 expected[file_name_size - len - 1] = '\0';
4041 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
4042 info = HeapAlloc( GetProcessHeap(), 0, info_size );
4044 memset( info, 0xcc, info_size );
4045 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
4046 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr, STATUS_SUCCESS);
4047 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
4048 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
4049 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
4051 CloseHandle( h );
4052 HeapFree( GetProcessHeap(), 0, info );
4053 HeapFree( GetProcessHeap(), 0, expected );
4054 HeapFree( GetProcessHeap(), 0, volume_prefix );
4055 HeapFree( GetProcessHeap(), 0, file_name );
4058 #define test_completion_flags(a,b) _test_completion_flags(__LINE__,a,b)
4059 static void _test_completion_flags(unsigned line, HANDLE handle, DWORD expected_flags)
4061 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
4062 IO_STATUS_BLOCK io;
4063 NTSTATUS status;
4065 info.Flags = 0xdeadbeef;
4066 status = pNtQueryInformationFile(handle, &io, &info, sizeof(info),
4067 FileIoCompletionNotificationInformation);
4068 ok_(__FILE__,line)(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4069 ok_(__FILE__,line)(io.Status == STATUS_SUCCESS, "Status = %lx\n", io.Status);
4070 ok_(__FILE__,line)(io.Information == sizeof(info), "Information = %Iu\n", io.Information);
4071 /* FILE_SKIP_SET_USER_EVENT_ON_FAST_IO is not supported on win2k3 */
4072 ok_(__FILE__,line)((info.Flags & ~FILE_SKIP_SET_USER_EVENT_ON_FAST_IO) == expected_flags,
4073 "got %08lx\n", info.Flags);
4076 static void test_file_completion_information(void)
4078 DECLSPEC_ALIGN(TEST_OVERLAPPED_READ_SIZE) static unsigned char aligned_buf[TEST_OVERLAPPED_READ_SIZE];
4079 static const char buf[] = "testdata";
4080 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
4081 OVERLAPPED ov, *pov;
4082 IO_STATUS_BLOCK io;
4083 NTSTATUS status;
4084 DWORD num_bytes;
4085 HANDLE port, h;
4086 ULONG_PTR key;
4087 BOOL ret;
4088 int i;
4090 if (!(h = create_temp_file(0))) return;
4092 status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
4093 ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS /* XP */),
4094 "expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
4095 if (status != STATUS_INFO_LENGTH_MISMATCH)
4097 win_skip("FileIoCompletionNotificationInformation class not supported\n");
4098 CloseHandle(h);
4099 return;
4102 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
4103 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4104 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
4106 CloseHandle(h);
4107 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
4109 info.Flags = FILE_SKIP_SET_EVENT_ON_HANDLE;
4110 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4111 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4112 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
4114 info.Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO;
4115 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4116 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4117 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
4119 info.Flags = 0;
4120 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4121 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4122 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
4124 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
4125 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4126 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4127 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
4129 info.Flags = 0xdeadbeef;
4130 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4131 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4132 test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
4134 CloseHandle(h);
4135 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
4136 test_completion_flags(h, 0);
4138 memset(&ov, 0, sizeof(ov));
4139 ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
4140 port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
4141 ok(port != NULL, "CreateIoCompletionPort failed, error %lu\n", GetLastError());
4143 for (i = 0; i < 10; i++)
4145 SetLastError(0xdeadbeef);
4146 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
4147 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* Before Vista */,
4148 "Unexpected result %#x, GetLastError() %lu.\n", ret, GetLastError());
4149 if (ret || GetLastError() != ERROR_IO_PENDING) break;
4150 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
4151 ok(ret, "GetOverlappedResult failed, error %lu\n", GetLastError());
4152 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
4153 ok(ret, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
4154 ret = FALSE;
4156 if (ret)
4158 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %lu\n", num_bytes);
4160 key = 0;
4161 pov = NULL;
4162 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
4163 ok(ret, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
4164 ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %Ix\n", key);
4165 ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
4168 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
4169 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4170 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4171 test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
4173 for (i = 0; i < 10; i++)
4175 SetLastError(0xdeadbeef);
4176 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
4177 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* Before Vista */,
4178 "Unexpected result %#x, GetLastError() %lu.\n", ret, GetLastError());
4179 if (ret || GetLastError() != ERROR_IO_PENDING) break;
4180 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
4181 ok(ret, "GetOverlappedResult failed, error %lu\n", GetLastError());
4182 ret = FALSE;
4184 if (ret)
4186 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %lu\n", num_bytes);
4188 pov = (void *)0xdeadbeef;
4189 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
4190 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
4191 ok(pov == NULL, "expected NULL, got %p\n", pov);
4194 info.Flags = 0;
4195 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4196 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
4197 test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
4199 for (i = 0; i < 10; i++)
4201 SetLastError(0xdeadbeef);
4202 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
4203 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* Before Vista */,
4204 "Unexpected result %#x, GetLastError() %lu.\n", ret, GetLastError());
4205 if (ret || GetLastError() != ERROR_IO_PENDING) break;
4206 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
4207 ok(ret, "GetOverlappedResult failed, error %lu\n", GetLastError());
4208 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
4209 ok(ret, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
4210 ret = FALSE;
4212 if (ret)
4214 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %lu\n", num_bytes);
4216 pov = (void *)0xdeadbeef;
4217 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
4218 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
4219 ok(pov == NULL, "expected NULL, got %p\n", pov);
4222 CloseHandle(port);
4223 CloseHandle(h);
4225 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING)))
4226 return;
4228 port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
4229 ok(port != NULL, "CreateIoCompletionPort failed, error %lu.\n", GetLastError());
4231 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
4232 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
4233 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %#lx.\n", status);
4234 test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
4236 ret = WriteFile(h, aligned_buf, sizeof(aligned_buf), &num_bytes, &ov);
4237 if (!ret && GetLastError() == ERROR_IO_PENDING)
4239 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
4240 ok(ret, "GetOverlappedResult failed, error %lu.\n", GetLastError());
4241 ok(num_bytes == sizeof(aligned_buf), "expected sizeof(aligned_buf), got %lu.\n", num_bytes);
4242 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
4243 ok(ret, "GetQueuedCompletionStatus failed, error %lu.\n", GetLastError());
4245 ok(num_bytes == sizeof(aligned_buf), "expected sizeof(buf), got %lu.\n", num_bytes);
4247 SetLastError(0xdeadbeef);
4248 ret = ReadFile(h, aligned_buf, sizeof(aligned_buf), &num_bytes, &ov);
4249 ok(!ret && GetLastError() == ERROR_IO_PENDING, "Unexpected result, ret %#x, error %lu.\n",
4250 ret, GetLastError());
4251 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
4252 ok(ret, "GetOverlappedResult failed, error %lu.\n", GetLastError());
4253 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
4254 ok(ret, "GetQueuedCompletionStatus failed, error %lu.\n", GetLastError());
4256 CloseHandle(ov.hEvent);
4257 CloseHandle(port);
4258 CloseHandle(h);
4261 static void test_file_id_information(void)
4263 BY_HANDLE_FILE_INFORMATION info;
4264 FILE_ID_INFORMATION fid;
4265 IO_STATUS_BLOCK io;
4266 NTSTATUS status;
4267 DWORD *dwords;
4268 HANDLE h;
4269 BOOL ret;
4271 if (!(h = create_temp_file(0))) return;
4273 memset( &fid, 0x11, sizeof(fid) );
4274 status = pNtQueryInformationFile( h, &io, &fid, sizeof(fid), FileIdInformation );
4275 if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
4277 win_skip( "FileIdInformation not supported\n" );
4278 CloseHandle( h );
4279 return;
4282 memset( &info, 0x22, sizeof(info) );
4283 ret = GetFileInformationByHandle( h, &info );
4284 ok( ret, "GetFileInformationByHandle failed\n" );
4286 dwords = (DWORD *)&fid.VolumeSerialNumber;
4287 ok( dwords[0] == info.dwVolumeSerialNumber, "expected %08lx, got %08lx\n",
4288 info.dwVolumeSerialNumber, dwords[0] );
4289 ok( dwords[1] != 0x11111111, "expected != 0x11111111\n" );
4291 dwords = (DWORD *)&fid.FileId;
4292 ok( dwords[0] == info.nFileIndexLow, "expected %08lx, got %08lx\n", info.nFileIndexLow, dwords[0] );
4293 ok( dwords[1] == info.nFileIndexHigh, "expected %08lx, got %08lx\n", info.nFileIndexHigh, dwords[1] );
4294 ok( dwords[2] == 0, "expected 0, got %08lx\n", dwords[2] );
4295 ok( dwords[3] == 0, "expected 0, got %08lx\n", dwords[3] );
4297 CloseHandle( h );
4300 static void test_file_access_information(void)
4302 FILE_ACCESS_INFORMATION info;
4303 IO_STATUS_BLOCK io;
4304 NTSTATUS status;
4305 HANDLE h;
4307 if (!(h = create_temp_file(0))) return;
4309 status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation );
4310 ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
4312 status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation );
4313 ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status );
4315 memset(&info, 0x11, sizeof(info));
4316 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation );
4317 ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status );
4318 ok( info.AccessFlags == 0x13019f, "got %08lx\n", info.AccessFlags );
4320 CloseHandle( h );
4323 static void test_file_attribute_tag_information(void)
4325 FILE_ATTRIBUTE_TAG_INFORMATION info;
4326 FILE_BASIC_INFORMATION fbi = {};
4327 IO_STATUS_BLOCK io;
4328 NTSTATUS status;
4329 HANDLE h;
4331 if (!(h = create_temp_file(0))) return;
4333 status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAttributeTagInformation );
4334 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status );
4336 status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAttributeTagInformation );
4337 ok( status == STATUS_INVALID_HANDLE, "got %#lx\n", status );
4339 memset(&info, 0x11, sizeof(info));
4340 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAttributeTagInformation );
4341 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4342 info.FileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
4343 ok( info.FileAttributes == FILE_ATTRIBUTE_ARCHIVE, "got attributes %#lx\n", info.FileAttributes );
4344 ok( !info.ReparseTag, "got reparse tag %#lx\n", info.ReparseTag );
4346 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
4347 status = pNtSetInformationFile(h, &io, &fbi, sizeof(fbi), FileBasicInformation);
4348 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4350 memset(&info, 0x11, sizeof(info));
4351 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAttributeTagInformation );
4352 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4353 todo_wine ok( info.FileAttributes == FILE_ATTRIBUTE_SYSTEM, "got attributes %#lx\n", info.FileAttributes );
4354 ok( !info.ReparseTag, "got reparse tag %#lx\n", info.ReparseTag );
4356 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
4357 status = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
4358 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4360 memset(&info, 0x11, sizeof(info));
4361 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAttributeTagInformation );
4362 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4363 todo_wine ok( info.FileAttributes == FILE_ATTRIBUTE_HIDDEN, "got attributes %#lx\n", info.FileAttributes );
4364 ok( !info.ReparseTag, "got reparse tag %#lx\n", info.ReparseTag );
4366 CloseHandle( h );
4369 static void test_file_stat_information(void)
4371 BY_HANDLE_FILE_INFORMATION info;
4372 FILE_STAT_INFORMATION fsd;
4373 IO_STATUS_BLOCK io;
4374 NTSTATUS status;
4375 HANDLE h;
4376 BOOL ret;
4378 if (!(h = create_temp_file(0))) return;
4380 memset( &fsd, 0x11, sizeof(fsd) );
4381 status = pNtQueryInformationFile( h, &io, &fsd, sizeof(fsd), FileStatInformation );
4382 if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
4384 win_skip( "FileStatInformation not supported\n" );
4385 CloseHandle( h );
4386 return;
4388 ok( status == STATUS_SUCCESS, "query FileStatInformation returned %#lx\n", status );
4390 memset( &info, 0x22, sizeof(info) );
4391 ret = GetFileInformationByHandle( h, &info );
4392 ok( ret, "GetFileInformationByHandle failed\n" );
4394 ok( fsd.FileId.u.LowPart == info.nFileIndexLow, "expected %08lx, got %08lx\n", info.nFileIndexLow, fsd.FileId.u.LowPart );
4395 ok( fsd.FileId.u.HighPart == info.nFileIndexHigh, "expected %08lx, got %08lx\n", info.nFileIndexHigh, fsd.FileId.u.HighPart );
4396 ok( fsd.CreationTime.u.LowPart == info.ftCreationTime.dwLowDateTime, "expected %08lx, got %08lx\n",
4397 info.ftCreationTime.dwLowDateTime, fsd.CreationTime.u.LowPart );
4398 ok( fsd.CreationTime.u.HighPart == info.ftCreationTime.dwHighDateTime, "expected %08lx, got %08lx\n",
4399 info.ftCreationTime.dwHighDateTime, fsd.CreationTime.u.HighPart );
4400 ok( fsd.LastAccessTime.u.LowPart == info.ftLastAccessTime.dwLowDateTime, "expected %08lx, got %08lx\n",
4401 info.ftLastAccessTime.dwLowDateTime, fsd.LastAccessTime.u.LowPart );
4402 ok( fsd.LastAccessTime.u.HighPart == info.ftLastAccessTime.dwHighDateTime, "expected %08lx, got %08lx\n",
4403 info.ftLastAccessTime.dwHighDateTime, fsd.LastAccessTime.u.HighPart );
4404 ok( fsd.LastWriteTime.u.LowPart == info.ftLastWriteTime.dwLowDateTime, "expected %08lx, got %08lx\n",
4405 info.ftLastWriteTime.dwLowDateTime, fsd.LastWriteTime.u.LowPart );
4406 ok( fsd.LastWriteTime.u.HighPart == info.ftLastWriteTime.dwHighDateTime, "expected %08lx, got %08lx\n",
4407 info.ftLastWriteTime.dwHighDateTime, fsd.LastWriteTime.u.HighPart );
4408 /* TODO: ChangeTime */
4409 /* TODO: AllocationSize */
4410 ok( fsd.EndOfFile.u.LowPart == info.nFileSizeLow, "expected %08lx, got %08lx\n", info.nFileSizeLow, fsd.EndOfFile.u.LowPart );
4411 ok( fsd.EndOfFile.u.HighPart == info.nFileSizeHigh, "expected %08lx, got %08lx\n", info.nFileSizeHigh, fsd.EndOfFile.u.HighPart );
4412 ok( fsd.FileAttributes == info.dwFileAttributes, "expected %08lx, got %08lx\n", info.dwFileAttributes, fsd.FileAttributes );
4413 ok( !fsd.ReparseTag, "got reparse tag %#lx\n", fsd.ReparseTag );
4414 ok( fsd.NumberOfLinks == info.nNumberOfLinks, "expected %08lx, got %08lx\n", info.nNumberOfLinks, fsd.NumberOfLinks );
4415 ok( fsd.EffectiveAccess == FILE_ALL_ACCESS, "got %08lx\n", fsd.EffectiveAccess );
4417 CloseHandle( h );
4420 static void rename_file( HANDLE h, const WCHAR *filename )
4422 FILE_RENAME_INFORMATION *fri;
4423 UNICODE_STRING ntpath;
4424 IO_STATUS_BLOCK io;
4425 NTSTATUS status;
4426 BOOLEAN ret;
4427 ULONG size;
4429 ret = pRtlDosPathNameToNtPathName_U( filename, &ntpath, NULL, NULL );
4430 ok( ret, "RtlDosPathNameToNtPathName_U failed\n" );
4432 size = offsetof( FILE_RENAME_INFORMATION, FileName ) + ntpath.Length;
4433 fri = HeapAlloc( GetProcessHeap(), 0, size );
4434 ok( fri != NULL, "HeapAlloc failed\n" );
4435 fri->ReplaceIfExists = TRUE;
4436 fri->RootDirectory = NULL;
4437 fri->FileNameLength = ntpath.Length;
4438 memcpy( fri->FileName, ntpath.Buffer, ntpath.Length );
4439 pRtlFreeUnicodeString( &ntpath );
4441 status = pNtSetInformationFile( h, &io, fri, size, FileRenameInformation );
4442 HeapFree( GetProcessHeap(), 0, fri );
4443 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4446 static void test_dotfile_file_attributes(void)
4448 char temppath[MAX_PATH], filename[MAX_PATH];
4449 WCHAR temppathW[MAX_PATH], filenameW[MAX_PATH];
4450 FILE_BASIC_INFORMATION info = {};
4451 IO_STATUS_BLOCK io;
4452 NTSTATUS status;
4453 DWORD attrs;
4454 HANDLE h;
4456 GetTempPathA( MAX_PATH, temppath );
4457 GetTempFileNameA( temppath, ".foo", 0, filename );
4458 h = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
4459 ok( h != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
4461 status = nt_get_file_attrs(filename, &attrs);
4462 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4463 ok( !(attrs & FILE_ATTRIBUTE_HIDDEN), "got attributes %#lx\n", attrs );
4465 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileBasicInformation );
4466 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4467 ok( !(info.FileAttributes & FILE_ATTRIBUTE_HIDDEN), "got attributes %#lx\n", info.FileAttributes );
4469 info.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
4470 status = pNtSetInformationFile( h, &io, &info, sizeof(info), FileBasicInformation );
4471 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4473 status = nt_get_file_attrs(filename, &attrs);
4474 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4475 ok( attrs & FILE_ATTRIBUTE_SYSTEM, "got attributes %#lx\n", attrs );
4476 ok( !(attrs & FILE_ATTRIBUTE_HIDDEN), "got attributes %#lx\n", attrs );
4478 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileBasicInformation );
4479 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4480 ok( info.FileAttributes & FILE_ATTRIBUTE_SYSTEM, "got attributes %#lx\n", info.FileAttributes );
4481 ok( !(info.FileAttributes & FILE_ATTRIBUTE_HIDDEN), "got attributes %#lx\n", info.FileAttributes );
4483 CloseHandle( h );
4485 GetTempPathW( MAX_PATH, temppathW );
4486 GetTempFileNameW( temppathW, L"foo", 0, filenameW );
4487 h = CreateFileW( filenameW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
4488 ok( h != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
4490 GetTempFileNameW( temppathW, L".foo", 0, filenameW );
4491 winetest_push_context("foo -> .foo");
4492 rename_file( h, filenameW );
4493 winetest_pop_context();
4495 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileBasicInformation );
4496 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4497 ok( !(info.FileAttributes & FILE_ATTRIBUTE_HIDDEN), "got attributes %#lx\n", info.FileAttributes );
4499 GetTempFileNameW( temppathW, L"foo", 0, filenameW );
4500 winetest_push_context(".foo -> foo");
4501 rename_file( h, filenameW );
4502 winetest_pop_context();
4504 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileBasicInformation );
4505 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
4506 ok( !(info.FileAttributes & FILE_ATTRIBUTE_HIDDEN), "got attributes %#lx\n", info.FileAttributes );
4508 CloseHandle( h );
4511 static void test_file_mode(void)
4513 UNICODE_STRING file_name, pipe_dev_name, mountmgr_dev_name, mailslot_dev_name;
4514 WCHAR tmp_path[MAX_PATH], dos_file_name[MAX_PATH];
4515 FILE_MODE_INFORMATION mode;
4516 OBJECT_ATTRIBUTES attr;
4517 IO_STATUS_BLOCK io;
4518 HANDLE file;
4519 unsigned i;
4520 DWORD res, access;
4521 NTSTATUS status;
4523 const struct {
4524 UNICODE_STRING *file_name;
4525 ULONG options;
4526 ULONG mode;
4527 } option_tests[] = {
4528 { &file_name, 0, 0 },
4529 { &file_name, FILE_NON_DIRECTORY_FILE, 0 },
4530 { &file_name, FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY, FILE_SEQUENTIAL_ONLY },
4531 { &file_name, FILE_WRITE_THROUGH, FILE_WRITE_THROUGH },
4532 { &file_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT },
4533 { &file_name, FILE_NO_INTERMEDIATE_BUFFERING, FILE_NO_INTERMEDIATE_BUFFERING },
4534 { &file_name, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, FILE_SYNCHRONOUS_IO_NONALERT },
4535 { &file_name, FILE_DELETE_ON_CLOSE, 0 },
4536 { &file_name, FILE_RANDOM_ACCESS | FILE_NO_COMPRESSION, 0 },
4537 { &pipe_dev_name, 0, 0 },
4538 { &pipe_dev_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT },
4539 { &mailslot_dev_name, 0, 0 },
4540 { &mailslot_dev_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT },
4541 { &mountmgr_dev_name, 0, 0 },
4542 { &mountmgr_dev_name, FILE_SYNCHRONOUS_IO_ALERT, FILE_SYNCHRONOUS_IO_ALERT }
4545 static WCHAR pipe_devW[] = {'\\','?','?','\\','P','I','P','E','\\'};
4546 static WCHAR mailslot_devW[] = {'\\','?','?','\\','M','A','I','L','S','L','O','T','\\'};
4547 static WCHAR mountmgr_devW[] =
4548 {'\\','?','?','\\','M','o','u','n','t','P','o','i','n','t','M','a','n','a','g','e','r'};
4550 GetTempPathW(MAX_PATH, tmp_path);
4551 res = GetTempFileNameW(tmp_path, fooW, 0, dos_file_name);
4552 ok(res, "GetTempFileNameW failed: %lu\n", GetLastError());
4553 pRtlDosPathNameToNtPathName_U( dos_file_name, &file_name, NULL, NULL );
4555 pipe_dev_name.Buffer = pipe_devW;
4556 pipe_dev_name.Length = sizeof(pipe_devW);
4557 pipe_dev_name.MaximumLength = sizeof(pipe_devW);
4559 mailslot_dev_name.Buffer = mailslot_devW;
4560 mailslot_dev_name.Length = sizeof(mailslot_devW);
4561 mailslot_dev_name.MaximumLength = sizeof(mailslot_devW);
4563 mountmgr_dev_name.Buffer = mountmgr_devW;
4564 mountmgr_dev_name.Length = sizeof(mountmgr_devW);
4565 mountmgr_dev_name.MaximumLength = sizeof(mountmgr_devW);
4567 attr.Length = sizeof(attr);
4568 attr.RootDirectory = 0;
4569 attr.Attributes = OBJ_CASE_INSENSITIVE;
4570 attr.SecurityDescriptor = NULL;
4571 attr.SecurityQualityOfService = NULL;
4573 for (i = 0; i < ARRAY_SIZE(option_tests); i++)
4575 attr.ObjectName = option_tests[i].file_name;
4576 access = SYNCHRONIZE;
4578 if (option_tests[i].file_name == &file_name)
4580 file = CreateFileW(dos_file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
4581 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
4582 CloseHandle(file);
4583 access |= GENERIC_WRITE | DELETE;
4586 status = pNtOpenFile(&file, access, &attr, &io, 0, option_tests[i].options);
4587 ok(status == STATUS_SUCCESS, "[%u] NtOpenFile failed: %lx\n", i, status);
4589 memset(&mode, 0xcc, sizeof(mode));
4590 status = pNtQueryInformationFile(file, &io, &mode, sizeof(mode), FileModeInformation);
4591 ok(status == STATUS_SUCCESS, "[%u] can't get FileModeInformation: %lx\n", i, status);
4592 ok(mode.Mode == option_tests[i].mode, "[%u] Mode = %lx, expected %lx\n",
4593 i, mode.Mode, option_tests[i].mode);
4595 pNtClose(file);
4596 if (option_tests[i].file_name == &file_name)
4597 DeleteFileW(dos_file_name);
4600 pRtlFreeUnicodeString(&file_name);
4603 static void test_query_volume_information_file(void)
4605 NTSTATUS status;
4606 HANDLE dir;
4607 WCHAR path[MAX_PATH];
4608 OBJECT_ATTRIBUTES attr;
4609 IO_STATUS_BLOCK io;
4610 UNICODE_STRING nameW;
4611 FILE_FS_VOLUME_INFORMATION *ffvi;
4612 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
4614 GetWindowsDirectoryW( path, MAX_PATH );
4615 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
4616 attr.Length = sizeof(attr);
4617 attr.RootDirectory = 0;
4618 attr.ObjectName = &nameW;
4619 attr.Attributes = OBJ_CASE_INSENSITIVE;
4620 attr.SecurityDescriptor = NULL;
4621 attr.SecurityQualityOfService = NULL;
4623 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
4624 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
4625 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
4626 pRtlFreeUnicodeString( &nameW );
4628 ZeroMemory( buf, sizeof(buf) );
4629 io.Status = 0xdadadada;
4630 io.Information = 0xcacacaca;
4632 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
4634 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
4636 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", status);
4637 ok(io.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", io.Status);
4639 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
4640 "expected %ld, got %Iu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
4641 io.Information);
4643 todo_wine ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
4644 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
4645 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
4646 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %ld\n", ffvi->VolumeLabelLength);
4648 trace("VolumeSerialNumber: %lx VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
4650 CloseHandle( dir );
4653 static void test_query_attribute_information_file(void)
4655 NTSTATUS status;
4656 HANDLE dir;
4657 WCHAR path[MAX_PATH];
4658 OBJECT_ATTRIBUTES attr;
4659 IO_STATUS_BLOCK io;
4660 UNICODE_STRING nameW;
4661 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
4662 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
4664 GetWindowsDirectoryW( path, MAX_PATH );
4665 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
4666 attr.Length = sizeof(attr);
4667 attr.RootDirectory = 0;
4668 attr.ObjectName = &nameW;
4669 attr.Attributes = OBJ_CASE_INSENSITIVE;
4670 attr.SecurityDescriptor = NULL;
4671 attr.SecurityQualityOfService = NULL;
4673 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
4674 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
4675 ok( !status, "open %s failed %lx\n", wine_dbgstr_w(nameW.Buffer), status );
4676 pRtlFreeUnicodeString( &nameW );
4678 ZeroMemory( buf, sizeof(buf) );
4679 io.Status = 0xdadadada;
4680 io.Information = 0xcacacaca;
4682 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
4684 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
4686 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", status);
4687 ok(io.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %ld\n", io.Status);
4688 ok(ffai->FileSystemAttributes != 0, "Missing FileSystemAttributes\n");
4689 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
4690 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
4692 trace("FileSystemAttributes: %lx MaximumComponentNameLength: %lx FileSystemName: %s\n",
4693 ffai->FileSystemAttributes, ffai->MaximumComponentNameLength,
4694 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
4696 CloseHandle( dir );
4699 static void test_NtCreateFile(void)
4701 static const struct test_data
4703 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
4704 } td[] =
4706 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4707 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
4708 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4709 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
4710 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
4711 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4712 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
4713 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4714 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4715 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
4716 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
4717 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4718 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4719 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
4720 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4721 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
4722 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
4723 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
4724 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
4726 static const WCHAR fooW[] = {'f','o','o',0};
4727 NTSTATUS status;
4728 HANDLE handle;
4729 WCHAR path[MAX_PATH];
4730 OBJECT_ATTRIBUTES attr;
4731 IO_STATUS_BLOCK io;
4732 UNICODE_STRING nameW;
4733 DWORD ret, i;
4735 GetTempPathW(MAX_PATH, path);
4736 GetTempFileNameW(path, fooW, 0, path);
4737 DeleteFileW(path);
4738 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
4740 attr.Length = sizeof(attr);
4741 attr.RootDirectory = NULL;
4742 attr.ObjectName = &nameW;
4743 attr.Attributes = OBJ_CASE_INSENSITIVE;
4744 attr.SecurityDescriptor = NULL;
4745 attr.SecurityQualityOfService = NULL;
4747 for (i = 0; i < ARRAY_SIZE(td); i++)
4749 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
4750 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
4751 td[i].disposition, 0, NULL, 0);
4753 ok(status == td[i].status, "%ld: expected %#lx got %#lx\n", i, td[i].status, status);
4755 if (!status)
4757 ok(io.Information == td[i].result,"%ld: expected %#lx got %#Ix\n", i, td[i].result, io.Information);
4759 ret = GetFileAttributesW(path);
4760 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
4761 /* FIXME: leave only 'else' case below once Wine is fixed */
4762 if (ret != td[i].attrib_out)
4764 todo_wine
4765 ok(ret == td[i].attrib_out, "%ld: expected %#lx got %#lx\n", i, td[i].attrib_out, ret);
4766 SetFileAttributesW(path, td[i].attrib_out);
4768 else
4769 ok(ret == td[i].attrib_out, "%ld: expected %#lx got %#lx\n", i, td[i].attrib_out, ret);
4771 CloseHandle(handle);
4774 if (td[i].needs_cleanup)
4776 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
4777 DeleteFileW(path);
4781 pRtlFreeUnicodeString( &nameW );
4782 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
4783 DeleteFileW( path );
4785 wcscat( path, L"\\" );
4786 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
4788 status = pNtCreateFile( &handle, GENERIC_READ, &attr, &io, NULL,
4789 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_CREATE, 0, NULL, 0);
4790 ok( status == STATUS_OBJECT_NAME_INVALID, "failed %s %lx\n", debugstr_w(nameW.Buffer), status );
4791 status = pNtCreateFile( &handle, GENERIC_READ, &attr, &io, NULL,
4792 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_CREATE,
4793 FILE_DIRECTORY_FILE, NULL, 0);
4794 ok( !status, "failed %s %lx\n", debugstr_w(nameW.Buffer), status );
4795 RemoveDirectoryW( path );
4798 static void test_read_write(void)
4800 static const char contents[14] = "1234567890abcd";
4801 char buf[256];
4802 HANDLE hfile, event;
4803 OVERLAPPED ovl;
4804 IO_STATUS_BLOCK iob;
4805 DWORD ret, bytes, status, off;
4806 LARGE_INTEGER offset;
4807 LONG i;
4809 event = CreateEventA( NULL, TRUE, FALSE, NULL );
4811 iob.Status = -1;
4812 iob.Information = -1;
4813 offset.QuadPart = 0;
4814 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4815 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4816 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4817 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4819 iob.Status = -1;
4820 iob.Information = -1;
4821 offset.QuadPart = 0;
4822 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, NULL, sizeof(buf), &offset, NULL);
4823 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4824 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4825 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4827 iob.Status = -1;
4828 iob.Information = -1;
4829 offset.QuadPart = 0;
4830 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4831 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4832 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4833 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4835 iob.Status = -1;
4836 iob.Information = -1;
4837 offset.QuadPart = 0;
4838 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4839 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
4840 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4841 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4843 hfile = create_temp_file(0);
4844 if (!hfile) return;
4846 iob.Status = -1;
4847 iob.Information = -1;
4848 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4849 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#lx\n", status);
4850 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4851 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4853 iob.Status = -1;
4854 iob.Information = -1;
4855 SetEvent(event);
4856 status = pNtWriteFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4857 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#lx\n", status);
4858 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4859 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4860 ok(!is_signaled(event), "event is not signaled\n");
4862 iob.Status = -1;
4863 iob.Information = -1;
4864 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4865 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status);
4866 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4867 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4869 iob.Status = -1;
4870 iob.Information = -1;
4871 SetEvent(event);
4872 status = pNtReadFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
4873 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status);
4874 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4875 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4876 ok(is_signaled(event), "event is not signaled\n");
4878 iob.Status = -1;
4879 iob.Information = -1;
4880 SetEvent(event);
4881 status = pNtReadFile(hfile, event, NULL, NULL, &iob, (void*)0xdeadbeef, sizeof(contents), NULL, NULL);
4882 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status);
4883 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4884 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
4885 ok(is_signaled(event), "event is not signaled\n");
4887 iob.Status = -1;
4888 iob.Information = -1;
4889 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
4890 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
4891 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
4892 ok(iob.Information == 7, "expected 7, got %Iu\n", iob.Information);
4894 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4896 iob.Status = -1;
4897 iob.Information = -1;
4898 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4899 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
4900 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
4901 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
4902 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %Iu\n", iob.Information);
4904 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4905 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4907 bytes = 0xdeadbeef;
4908 SetLastError(0xdeadbeef);
4909 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
4910 ok(!ret, "ReadFile should fail\n");
4911 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
4912 ok(bytes == 0, "bytes %lu\n", bytes);
4914 bytes = 0xdeadbeef;
4915 SetLastError(0xdeadbeef);
4916 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
4917 ok(ret, "ReadFile error %ld\n", GetLastError());
4918 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4919 ok(bytes == 0, "bytes %lu\n", bytes);
4921 bytes = 0xdeadbeef;
4922 SetLastError(0xdeadbeef);
4923 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4924 ok(ret, "ReadFile error %ld\n", GetLastError());
4925 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4926 ok(bytes == 0, "bytes %lu\n", bytes);
4928 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4930 bytes = 0;
4931 SetLastError(0xdeadbeef);
4932 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4933 ok(ret, "ReadFile error %ld\n", GetLastError());
4934 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4935 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4937 for (i = -20; i < -1; i++)
4939 if (i == -2) continue;
4941 iob.Status = -1;
4942 iob.Information = -1;
4943 offset.QuadPart = (LONGLONG)i;
4944 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4945 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
4946 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
4947 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
4950 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4952 iob.Status = -1;
4953 iob.Information = -1;
4954 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
4955 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4956 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
4957 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
4958 ok(iob.Information == 4, "expected 4, got %Iu\n", iob.Information);
4960 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4961 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4963 iob.Status = -1;
4964 iob.Information = -1;
4965 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
4966 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
4967 ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", iob.Status);
4968 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
4970 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4972 bytes = 0;
4973 SetLastError(0xdeadbeef);
4974 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4975 ok(ret, "ReadFile error %ld\n", GetLastError());
4976 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4977 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4978 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4980 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4981 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4983 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4985 bytes = 0;
4986 SetLastError(0xdeadbeef);
4987 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
4988 ok(ret, "WriteFile error %ld\n", GetLastError());
4989 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
4991 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4992 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
4994 /* test reading beyond EOF */
4995 bytes = -1;
4996 SetLastError(0xdeadbeef);
4997 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4998 ok(ret, "ReadFile error %ld\n", GetLastError());
4999 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5000 ok(bytes == 0, "bytes %lu\n", bytes);
5002 bytes = -1;
5003 SetLastError(0xdeadbeef);
5004 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
5005 ok(ret, "ReadFile error %ld\n", GetLastError());
5006 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5007 ok(bytes == 0, "bytes %lu\n", bytes);
5009 bytes = -1;
5010 SetLastError(0xdeadbeef);
5011 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
5012 ok(ret, "ReadFile error %ld\n", GetLastError());
5013 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5014 ok(bytes == 0, "bytes %lu\n", bytes);
5016 ovl.Offset = sizeof(contents);
5017 ovl.OffsetHigh = 0;
5018 ovl.Internal = -1;
5019 ovl.InternalHigh = -1;
5020 ovl.hEvent = 0;
5021 bytes = -1;
5022 SetLastError(0xdeadbeef);
5023 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
5024 ok(!ret, "ReadFile should fail\n");
5025 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %ld\n", GetLastError());
5026 ok(bytes == 0, "bytes %lu\n", bytes);
5027 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#Ix\n", ovl.Internal);
5028 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
5030 ovl.Offset = sizeof(contents);
5031 ovl.OffsetHigh = 0;
5032 ovl.Internal = -1;
5033 ovl.InternalHigh = -1;
5034 ovl.hEvent = 0;
5035 bytes = -1;
5036 SetLastError(0xdeadbeef);
5037 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
5038 ok(ret, "ReadFile error %ld\n", GetLastError());
5039 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5040 ok(bytes == 0, "bytes %lu\n", bytes);
5041 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5042 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
5044 iob.Status = -1;
5045 iob.Information = -1;
5046 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
5047 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
5048 ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", iob.Status);
5049 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5051 iob.Status = -1;
5052 iob.Information = -1;
5053 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
5054 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
5055 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5056 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5058 iob.Status = -1;
5059 iob.Information = -1;
5060 offset.QuadPart = sizeof(contents);
5061 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5062 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
5063 ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", iob.Status);
5064 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5066 iob.Status = -1;
5067 iob.Information = -1;
5068 offset.QuadPart = sizeof(contents);
5069 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
5070 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
5071 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5072 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5074 iob.Status = -1;
5075 iob.Information = -1;
5076 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
5077 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5078 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
5079 ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", iob.Status);
5080 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5082 iob.Status = -1;
5083 iob.Information = -1;
5084 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
5085 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
5086 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
5087 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5088 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5090 for (i = -20; i < 0; i++)
5092 if (i == -2) continue;
5094 iob.Status = -1;
5095 iob.Information = -1;
5096 offset.QuadPart = (LONGLONG)i;
5097 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5098 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
5099 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
5100 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
5103 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
5105 bytes = 0;
5106 SetLastError(0xdeadbeef);
5107 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
5108 ok(ret, "ReadFile error %ld\n", GetLastError());
5109 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
5110 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
5112 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5113 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
5115 iob.Status = -1;
5116 iob.Information = -1;
5117 offset.QuadPart = 0;
5118 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5119 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
5120 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5121 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
5122 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
5124 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5125 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
5127 iob.Status = -1;
5128 iob.Information = -1;
5129 offset.QuadPart = sizeof(contents) - 4;
5130 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
5131 ok(status == STATUS_SUCCESS, "NtWriteFile error %#lx\n", status);
5132 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5133 ok(iob.Information == 4, "expected 4, got %Iu\n", iob.Information);
5135 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5136 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
5138 iob.Status = -1;
5139 iob.Information = -1;
5140 offset.QuadPart = 0;
5141 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5142 ok(status == STATUS_SUCCESS, "NtReadFile error %#lx\n", status);
5143 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5144 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
5145 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
5146 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
5148 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5149 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
5151 ovl.Offset = sizeof(contents) - 4;
5152 ovl.OffsetHigh = 0;
5153 ovl.hEvent = 0;
5154 bytes = 0;
5155 SetLastError(0xdeadbeef);
5156 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
5157 ok(ret, "WriteFile error %ld\n", GetLastError());
5158 ok(bytes == 4, "bytes %lu\n", bytes);
5160 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5161 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
5163 ovl.Offset = 0;
5164 ovl.OffsetHigh = 0;
5165 ovl.Internal = -1;
5166 ovl.InternalHigh = -1;
5167 ovl.hEvent = 0;
5168 bytes = 0;
5169 SetLastError(0xdeadbeef);
5170 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
5171 ok(ret, "ReadFile error %ld\n", GetLastError());
5172 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
5173 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5174 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
5175 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
5176 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
5178 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5179 ok(off == sizeof(contents), "expected sizeof(contents), got %lu\n", off);
5181 CloseHandle(hfile);
5183 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
5184 if (!hfile) return;
5186 bytes = 0xdeadbeef;
5187 SetLastError(0xdeadbeef);
5188 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
5189 ok(!ret, "ReadFile should fail\n");
5190 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
5191 ok(bytes == 0, "bytes %lu\n", bytes);
5193 ovl.Offset = 0;
5194 ovl.OffsetHigh = 0;
5195 ovl.Internal = -1;
5196 ovl.InternalHigh = -1;
5197 ovl.hEvent = 0;
5198 bytes = 0xdeadbeef;
5199 SetLastError(0xdeadbeef);
5200 /* ReadFile return value depends on Windows version and testing it is not practical */
5201 ReadFile(hfile, buf, 0, &bytes, &ovl);
5202 ok(bytes == 0, "bytes %lu\n", bytes);
5203 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5204 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
5206 bytes = 0xdeadbeef;
5207 SetLastError(0xdeadbeef);
5208 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
5209 ok(!ret, "WriteFile should fail\n");
5210 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
5211 ok(bytes == 0, "bytes %lu\n", bytes);
5213 iob.Status = -1;
5214 iob.Information = -1;
5215 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
5216 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#lx\n", status);
5217 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
5218 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
5220 for (i = -20; i < -1; i++)
5222 iob.Status = -1;
5223 iob.Information = -1;
5224 offset.QuadPart = (LONGLONG)i;
5225 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
5226 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
5227 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
5228 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
5231 iob.Status = -1;
5232 iob.Information = -1;
5233 offset.QuadPart = 0;
5234 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
5235 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
5236 "expected STATUS_PENDING, got %#lx.\n", status);
5237 if (status == STATUS_PENDING)
5239 ret = WaitForSingleObject(hfile, 3000);
5240 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
5242 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5243 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
5245 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5246 ok(off == 0, "expected 0, got %lu\n", off);
5248 bytes = 0xdeadbeef;
5249 SetLastError(0xdeadbeef);
5250 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
5251 ok(!ret, "ReadFile should fail\n");
5252 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
5253 ok(bytes == 0, "bytes %lu\n", bytes);
5255 iob.Status = -1;
5256 iob.Information = -1;
5257 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
5258 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#lx\n", status);
5259 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
5260 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
5262 for (i = -20; i < 0; i++)
5264 iob.Status = -1;
5265 iob.Information = -1;
5266 offset.QuadPart = (LONGLONG)i;
5267 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5268 ok(status == STATUS_INVALID_PARAMETER, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i, status);
5269 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
5270 ok(iob.Information == -1, "expected -1, got %Id\n", iob.Information);
5273 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5274 ok(off == 0, "expected 0, got %lu\n", off);
5276 /* test reading beyond EOF */
5277 offset.QuadPart = sizeof(contents);
5278 ovl.Offset = offset.u.LowPart;
5279 ovl.OffsetHigh = offset.u.HighPart;
5280 ovl.Internal = -1;
5281 ovl.InternalHigh = -1;
5282 ovl.hEvent = 0;
5283 bytes = 0xdeadbeef;
5284 SetLastError(0xdeadbeef);
5285 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
5286 ok(!ret, "ReadFile should fail\n");
5287 ret = GetLastError();
5288 ok(ret == ERROR_IO_PENDING || broken(ret == ERROR_HANDLE_EOF) /* before Vista */,
5289 "expected ERROR_IO_PENDING, got %ld\n", ret);
5290 ok(bytes == 0, "bytes %lu\n", bytes);
5292 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5293 ok(off == 0, "expected 0, got %lu\n", off);
5295 if (ret == ERROR_IO_PENDING)
5297 bytes = 0xdeadbeef;
5298 SetLastError(0xdeadbeef);
5299 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
5300 ok(!ret, "GetOverlappedResult should report FALSE\n");
5301 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %ld\n", GetLastError());
5302 ok(bytes == 0, "expected 0, read %lu\n", bytes);
5303 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#Ix\n", ovl.Internal);
5304 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
5307 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5308 ok(off == 0, "expected 0, got %lu\n", off);
5310 offset.QuadPart = sizeof(contents);
5311 ovl.Offset = offset.u.LowPart;
5312 ovl.OffsetHigh = offset.u.HighPart;
5313 ovl.Internal = -1;
5314 ovl.InternalHigh = -1;
5315 ovl.hEvent = 0;
5316 bytes = 0xdeadbeef;
5317 SetLastError(0xdeadbeef);
5318 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
5319 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
5320 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret, GetLastError());
5321 ret = GetLastError();
5322 ok(bytes == 0, "bytes %lu\n", bytes);
5324 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5325 ok(off == 0, "expected 0, got %lu\n", off);
5327 if (ret == ERROR_IO_PENDING)
5329 bytes = 0xdeadbeef;
5330 SetLastError(0xdeadbeef);
5331 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
5332 ok(ret, "GetOverlappedResult returned FALSE with %lu (expected TRUE)\n", GetLastError());
5333 ok(bytes == 0, "expected 0, read %lu\n", bytes);
5334 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5335 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
5338 offset.QuadPart = sizeof(contents);
5339 ovl.Offset = offset.u.LowPart;
5340 ovl.OffsetHigh = offset.u.HighPart;
5341 ovl.Internal = -1;
5342 ovl.InternalHigh = -1;
5343 ovl.hEvent = 0;
5344 bytes = 0xdeadbeef;
5345 SetLastError(0xdeadbeef);
5346 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
5347 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
5348 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret, GetLastError());
5349 ret = GetLastError();
5350 ok(bytes == 0, "bytes %lu\n", bytes);
5352 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5353 ok(off == 0, "expected 0, got %lu\n", off);
5355 if (ret == ERROR_IO_PENDING)
5357 bytes = 0xdeadbeef;
5358 SetLastError(0xdeadbeef);
5359 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
5360 ok(ret, "GetOverlappedResult returned FALSE with %lu (expected TRUE)\n", GetLastError());
5361 ok(bytes == 0, "expected 0, read %lu\n", bytes);
5362 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5363 ok(ovl.InternalHigh == 0, "expected 0, got %Iu\n", ovl.InternalHigh);
5366 iob.Status = -1;
5367 iob.Information = -1;
5368 offset.QuadPart = sizeof(contents);
5369 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5370 if (status == STATUS_PENDING)
5372 ret = WaitForSingleObject(hfile, 3000);
5373 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
5374 ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", iob.Status);
5375 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5377 else
5379 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", status);
5380 ok(iob.Status == -1, "expected -1, got %#lx\n", iob.Status);
5381 ok(iob.Information == -1, "expected -1, got %Iu\n", iob.Information);
5384 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5385 ok(off == 0, "expected 0, got %lu\n", off);
5387 iob.Status = -1;
5388 iob.Information = -1;
5389 offset.QuadPart = sizeof(contents);
5390 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
5391 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
5392 "expected STATUS_PENDING, got %#lx.\n", status);
5393 if (status == STATUS_PENDING)
5395 ret = WaitForSingleObject(hfile, 3000);
5396 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
5397 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5398 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5400 else
5402 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5403 ok(iob.Information == 0, "expected 0, got %Iu\n", iob.Information);
5406 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5407 ok(off == 0, "expected 0, got %lu\n", off);
5409 ovl.Offset = 0;
5410 ovl.OffsetHigh = 0;
5411 ovl.Internal = -1;
5412 ovl.InternalHigh = -1;
5413 ovl.hEvent = 0;
5414 bytes = 0;
5415 SetLastError(0xdeadbeef);
5416 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
5417 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
5418 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret, GetLastError());
5419 if (!ret)
5420 ok(bytes == 0, "bytes %lu\n", bytes);
5421 else
5422 ok(bytes == 14, "bytes %lu\n", bytes);
5423 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5424 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
5426 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5427 ok(off == 0, "expected 0, got %lu\n", off);
5429 bytes = 0xdeadbeef;
5430 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
5431 ok(ret, "GetOverlappedResult error %ld\n", GetLastError());
5432 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
5433 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5434 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
5435 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
5437 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5438 ok(off == 0, "expected 0, got %lu\n", off);
5440 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
5441 SetEndOfFile(hfile);
5442 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
5444 iob.Status = -1;
5445 iob.Information = -1;
5446 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
5447 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
5448 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
5449 "expected STATUS_PENDING, got %#lx.\n", status);
5450 if (status == STATUS_PENDING)
5452 ret = WaitForSingleObject(hfile, 3000);
5453 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
5455 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5456 ok(iob.Information == 4, "expected 4, got %Iu\n", iob.Information);
5458 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5459 ok(off == 0, "expected 0, got %lu\n", off);
5461 iob.Status = -1;
5462 iob.Information = -1;
5463 offset.QuadPart = 0;
5464 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
5465 ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */,
5466 "expected STATUS_PENDING, got %#lx.\n", status);
5467 if (status == STATUS_PENDING)
5469 ret = WaitForSingleObject(hfile, 3000);
5470 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
5472 ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", iob.Status);
5473 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %Iu\n", iob.Information);
5475 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5476 ok(off == 0, "expected 0, got %lu\n", off);
5478 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
5479 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
5481 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5482 ok(off == 0, "expected 0, got %lu\n", off);
5484 ovl.Offset = sizeof(contents) - 4;
5485 ovl.OffsetHigh = 0;
5486 ovl.Internal = -1;
5487 ovl.InternalHigh = -1;
5488 ovl.hEvent = 0;
5489 bytes = 0;
5490 SetLastError(0xdeadbeef);
5491 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
5492 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
5493 "Unexpected result %#lx, GetLastError() %lu.\n", ret, GetLastError());
5494 if (!ret)
5496 ok(bytes == 0, "bytes %lu\n", bytes);
5497 ret = WaitForSingleObject(hfile, 3000);
5498 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
5500 else ok(bytes == 4, "bytes %lu\n", bytes);
5501 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5502 ok(ovl.InternalHigh == 4, "expected 4, got %Iu\n", ovl.InternalHigh);
5504 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5505 ok(off == 0, "expected 0, got %lu\n", off);
5507 bytes = 0xdeadbeef;
5508 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
5509 ok(ret, "GetOverlappedResult error %ld\n", GetLastError());
5510 ok(bytes == 4, "bytes %lu\n", bytes);
5511 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5512 ok(ovl.InternalHigh == 4, "expected 4, got %Iu\n", ovl.InternalHigh);
5514 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5515 ok(off == 0, "expected 0, got %lu\n", off);
5517 ovl.Offset = 0;
5518 ovl.OffsetHigh = 0;
5519 ovl.Internal = -1;
5520 ovl.InternalHigh = -1;
5521 ovl.hEvent = 0;
5522 bytes = 0;
5523 SetLastError(0xdeadbeef);
5524 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
5525 ok((!ret && GetLastError() == ERROR_IO_PENDING) || broken(ret) /* before Vista */,
5526 "Unexpected result %#lx, GetLastError() %lu.\n", ret, GetLastError());
5527 if (!ret)
5529 ok(bytes == 0, "bytes %lu\n", bytes);
5530 ret = WaitForSingleObject(hfile, 3000);
5531 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %ld\n", ret);
5533 else ok(bytes == 14, "bytes %lu\n", bytes);
5534 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5535 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
5537 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5538 ok(off == 0, "expected 0, got %lu\n", off);
5540 bytes = 0xdeadbeef;
5541 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
5542 ok(ret, "GetOverlappedResult error %ld\n", GetLastError());
5543 ok(bytes == sizeof(contents), "bytes %lu\n", bytes);
5544 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", ovl.Internal);
5545 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %Iu\n", ovl.InternalHigh);
5546 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
5547 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
5549 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
5550 ok(off == 0, "expected 0, got %lu\n", off);
5552 CloseHandle(event);
5553 CloseHandle(hfile);
5556 static void test_ioctl(void)
5558 HANDLE event = CreateEventA(NULL, TRUE, FALSE, NULL);
5559 FILE_PIPE_PEEK_BUFFER peek_buf;
5560 IO_STATUS_BLOCK iosb;
5561 HANDLE file;
5562 NTSTATUS status;
5564 file = create_temp_file(FILE_FLAG_OVERLAPPED);
5565 ok(file != INVALID_HANDLE_VALUE, "could not create temp file\n");
5567 SetEvent(event);
5568 status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
5569 todo_wine
5570 ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile returned %lx\n", status);
5571 ok(!is_signaled(event), "event is signaled\n");
5573 status = pNtFsControlFile(file, (HANDLE)0xdeadbeef, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
5574 ok(status == STATUS_INVALID_HANDLE, "NtFsControlFile returned %lx\n", status);
5576 memset(&iosb, 0x55, sizeof(iosb));
5577 status = pNtFsControlFile(file, NULL, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0,
5578 &peek_buf, sizeof(peek_buf));
5579 todo_wine
5580 ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile failed: %lx\n", status);
5581 ok(iosb.Status == 0x55555555, "iosb.Status = %lx\n", iosb.Status);
5583 CloseHandle(event);
5584 CloseHandle(file);
5587 static void test_flush_buffers_file(void)
5589 char path[MAX_PATH], buffer[MAX_PATH];
5590 HANDLE hfile, hfileread;
5591 NTSTATUS status;
5592 IO_STATUS_BLOCK io_status_block;
5594 GetTempPathA(MAX_PATH, path);
5595 GetTempFileNameA(path, "foo", 0, buffer);
5596 hfile = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
5597 FILE_ATTRIBUTE_NORMAL, 0);
5598 ok(hfile != INVALID_HANDLE_VALUE, "failed to create temp file.\n" );
5600 hfileread = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
5601 OPEN_EXISTING, 0, NULL);
5602 ok(hfileread != INVALID_HANDLE_VALUE, "could not open temp file, error %ld.\n", GetLastError());
5604 status = pNtFlushBuffersFile(hfile, NULL);
5605 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER, "got %#lx.\n", status);
5607 status = pNtFlushBuffersFile(hfile, (IO_STATUS_BLOCK *)0xdeadbeaf);
5608 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#lx.\n", status);
5610 io_status_block.Information = 0xdeadbeef;
5611 io_status_block.Status = 0xdeadbeef;
5612 status = pNtFlushBuffersFile(hfile, &io_status_block);
5613 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5614 ok(io_status_block.Status == STATUS_SUCCESS, "Got unexpected io_status_block.Status %#lx.\n",
5615 io_status_block.Status);
5616 ok(!io_status_block.Information, "Got unexpected io_status_block.Information %#Ix.\n",
5617 io_status_block.Information);
5619 status = pNtFlushBuffersFile(hfileread, &io_status_block);
5620 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status);
5622 io_status_block.Information = 0xdeadbeef;
5623 io_status_block.Status = 0xdeadbeef;
5624 status = pNtFlushBuffersFile(NULL, &io_status_block);
5625 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#lx.\n", status);
5626 ok(io_status_block.Status == 0xdeadbeef, "Got unexpected io_status_block.Status %#lx.\n",
5627 io_status_block.Status);
5628 ok(io_status_block.Information == 0xdeadbeef, "Got unexpected io_status_block.Information %#Ix.\n",
5629 io_status_block.Information);
5631 CloseHandle(hfileread);
5632 CloseHandle(hfile);
5633 hfile = CreateFileA(buffer, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
5634 OPEN_EXISTING, 0, NULL);
5635 ok(hfile != INVALID_HANDLE_VALUE, "could not open temp file, error %ld.\n", GetLastError());
5637 status = pNtFlushBuffersFile(hfile, &io_status_block);
5638 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5640 io_status_block.Information = 0xdeadbeef;
5641 io_status_block.Status = 0xdeadbeef;
5642 status = pNtFlushBuffersFile((HANDLE)0xdeadbeef, &io_status_block);
5643 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#lx.\n", status);
5644 ok(io_status_block.Status == 0xdeadbeef, "Got unexpected io_status_block.Status %#lx.\n",
5645 io_status_block.Status);
5646 ok(io_status_block.Information == 0xdeadbeef, "Got unexpected io_status_block.Information %#Ix.\n",
5647 io_status_block.Information);
5649 CloseHandle(hfile);
5650 DeleteFileA(buffer);
5653 static void test_query_ea(void)
5655 #define EA_BUFFER_SIZE 4097
5656 unsigned char data[EA_BUFFER_SIZE + 8];
5657 unsigned char *buffer = (void *)(((DWORD_PTR)data + 7) & ~7);
5658 DWORD buffer_len, i;
5659 IO_STATUS_BLOCK io;
5660 NTSTATUS status;
5661 HANDLE handle;
5663 if (!(handle = create_temp_file(0))) return;
5665 /* test with INVALID_HANDLE_VALUE */
5666 io.Status = 0xdeadbeef;
5667 io.Information = 0xdeadbeef;
5668 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5669 buffer_len = EA_BUFFER_SIZE - 1;
5670 status = pNtQueryEaFile(INVALID_HANDLE_VALUE, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5671 ok(status == STATUS_OBJECT_TYPE_MISMATCH, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status);
5672 ok(io.Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io.Status);
5673 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5674 ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
5676 /* test with 0xdeadbeef */
5677 io.Status = 0xdeadbeef;
5678 io.Information = 0xdeadbeef;
5679 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5680 buffer_len = EA_BUFFER_SIZE - 1;
5681 status = pNtQueryEaFile((void *)0xdeadbeef, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5682 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#lx\n", status);
5683 ok(io.Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io.Status);
5684 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5685 ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
5687 /* test without buffer */
5688 io.Status = 0xdeadbeef;
5689 io.Information = 0xdeadbeef;
5690 status = pNtQueryEaFile(handle, &io, NULL, 0, TRUE, NULL, 0, NULL, FALSE);
5691 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5692 ok(io.Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io.Status);
5693 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5695 /* test with zero buffer */
5696 io.Status = 0xdeadbeef;
5697 io.Information = 0xdeadbeef;
5698 status = pNtQueryEaFile(handle, &io, buffer, 0, TRUE, NULL, 0, NULL, FALSE);
5699 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5700 ok(io.Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io.Status);
5701 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5703 /* test with very small buffer */
5704 io.Status = 0xdeadbeef;
5705 io.Information = 0xdeadbeef;
5706 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5707 buffer_len = 4;
5708 status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5709 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5710 ok(io.Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io.Status);
5711 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5712 for (i = 0; i < buffer_len && !buffer[i]; i++);
5713 ok(i == buffer_len, "expected %lu bytes filled with 0x00, got %lu bytes\n", buffer_len, i);
5714 ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
5716 /* test with very big buffer */
5717 io.Status = 0xdeadbeef;
5718 io.Information = 0xdeadbeef;
5719 memset(buffer, 0xcc, EA_BUFFER_SIZE);
5720 buffer_len = EA_BUFFER_SIZE - 1;
5721 status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
5722 ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status);
5723 ok(io.Status == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io.Status);
5724 ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io.Information);
5725 for (i = 0; i < buffer_len && !buffer[i]; i++);
5726 ok(i == buffer_len, "expected %lu bytes filled with 0x00, got %lu bytes\n", buffer_len, i);
5727 ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
5729 CloseHandle(handle);
5730 #undef EA_BUFFER_SIZE
5733 static void test_file_readonly_access(void)
5735 static const DWORD default_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
5736 static const WCHAR fooW[] = {'f', 'o', 'o', 0};
5737 WCHAR path[MAX_PATH];
5738 OBJECT_ATTRIBUTES attr;
5739 UNICODE_STRING nameW;
5740 IO_STATUS_BLOCK io;
5741 HANDLE handle;
5742 NTSTATUS status;
5743 DWORD ret;
5745 /* Set up */
5746 GetTempPathW(MAX_PATH, path);
5747 GetTempFileNameW(path, fooW, 0, path);
5748 DeleteFileW(path);
5749 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
5751 attr.Length = sizeof(attr);
5752 attr.RootDirectory = NULL;
5753 attr.ObjectName = &nameW;
5754 attr.Attributes = OBJ_CASE_INSENSITIVE;
5755 attr.SecurityDescriptor = NULL;
5756 attr.SecurityQualityOfService = NULL;
5758 status = pNtCreateFile(&handle, FILE_GENERIC_WRITE, &attr, &io, NULL, FILE_ATTRIBUTE_READONLY, default_sharing,
5759 FILE_CREATE, 0, NULL, 0);
5760 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5761 CloseHandle(handle);
5763 /* NtCreateFile FILE_GENERIC_WRITE */
5764 status = pNtCreateFile(&handle, FILE_GENERIC_WRITE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, default_sharing,
5765 FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
5766 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status);
5768 /* NtCreateFile DELETE without FILE_DELETE_ON_CLOSE */
5769 status = pNtCreateFile(&handle, DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, default_sharing, FILE_OPEN,
5770 FILE_NON_DIRECTORY_FILE, NULL, 0);
5771 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5772 CloseHandle(handle);
5774 /* NtCreateFile DELETE with FILE_DELETE_ON_CLOSE */
5775 status = pNtCreateFile(&handle, SYNCHRONIZE | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, default_sharing,
5776 FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0);
5777 ok(status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %#lx.\n", status);
5779 /* NtOpenFile GENERIC_WRITE */
5780 status = pNtOpenFile(&handle, GENERIC_WRITE, &attr, &io, default_sharing, FILE_NON_DIRECTORY_FILE);
5781 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status);
5783 /* NtOpenFile DELETE without FILE_DELETE_ON_CLOSE */
5784 status = pNtOpenFile(&handle, DELETE, &attr, &io, default_sharing, FILE_NON_DIRECTORY_FILE);
5785 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx.\n", status);
5786 CloseHandle(handle);
5788 /* NtOpenFile DELETE with FILE_DELETE_ON_CLOSE */
5789 status = pNtOpenFile(&handle, DELETE, &attr, &io, default_sharing, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE);
5790 ok(status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %#lx.\n", status);
5792 ret = GetFileAttributesW(path);
5793 ok(ret & FILE_ATTRIBUTE_READONLY, "got wrong attribute: %#lx.\n", ret);
5795 /* Clean up */
5796 pRtlFreeUnicodeString(&nameW);
5797 SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL);
5798 DeleteFileW(path);
5801 static void test_mailslot_name(void)
5803 char buffer[1024] = {0};
5804 const FILE_NAME_INFORMATION *name = (const FILE_NAME_INFORMATION *)buffer;
5805 HANDLE server, client, device;
5806 IO_STATUS_BLOCK io;
5807 NTSTATUS ret;
5809 server = CreateMailslotA( "\\\\.\\mailslot\\winetest", 100, 1000, NULL );
5810 ok(server != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
5812 ret = NtQueryInformationFile( server, &io, buffer, 0, FileNameInformation );
5813 ok(ret == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", ret);
5815 memset(buffer, 0xcc, sizeof(buffer));
5816 ret = NtQueryInformationFile( server, &io, buffer,
5817 offsetof(FILE_NAME_INFORMATION, FileName[5]), FileNameInformation );
5818 todo_wine ok(ret == STATUS_BUFFER_OVERFLOW, "got %#lx\n", ret);
5819 if (ret == STATUS_BUFFER_OVERFLOW)
5821 ok(name->FileNameLength == 18, "got length %lu\n", name->FileNameLength);
5822 ok(!memcmp(name->FileName, L"\\wine", 10), "got %s\n",
5823 debugstr_wn(name->FileName, name->FileNameLength / sizeof(WCHAR)));
5826 memset(buffer, 0xcc, sizeof(buffer));
5827 ret = NtQueryInformationFile( server, &io, buffer, sizeof(buffer), FileNameInformation );
5828 todo_wine ok(!ret, "got %#lx\n", ret);
5829 if (!ret)
5831 ok(name->FileNameLength == 18, "got length %lu\n", name->FileNameLength);
5832 ok(!memcmp(name->FileName, L"\\winetest", 18), "got %s\n",
5833 debugstr_wn(name->FileName, name->FileNameLength / sizeof(WCHAR)));
5836 client = CreateFileA( "\\\\.\\mailslot\\winetest", 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
5837 ok(client != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
5839 ret = NtQueryInformationFile( client, &io, buffer, 0, FileNameInformation );
5840 ok(ret == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", ret);
5842 ret = NtQueryInformationFile( client, &io, buffer, sizeof(buffer), FileNameInformation );
5843 todo_wine ok(ret == STATUS_INVALID_PARAMETER || !ret /* win8+ */, "got %#lx\n", ret);
5844 if (!ret)
5846 ok(name->FileNameLength == 18, "got length %lu\n", name->FileNameLength);
5847 ok(!memcmp(name->FileName, L"\\winetest", 18), "got %s\n",
5848 debugstr_wn(name->FileName, name->FileNameLength / sizeof(WCHAR)));
5851 CloseHandle( server );
5852 CloseHandle( client );
5854 device = CreateFileA("\\\\.\\mailslot", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
5855 ok(device != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
5857 ret = NtQueryInformationFile( device, &io, buffer, 0, FileNameInformation );
5858 ok(ret == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", ret);
5860 ret = NtQueryInformationFile( device, &io, buffer, sizeof(buffer), FileNameInformation );
5861 todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret);
5863 CloseHandle( device );
5866 static void test_reparse_points(void)
5868 OBJECT_ATTRIBUTES attr;
5869 HANDLE handle;
5870 IO_STATUS_BLOCK io;
5871 NTSTATUS status;
5872 UNICODE_STRING nameW;
5873 unsigned char reparse_data[1];
5875 pRtlInitUnicodeString( &nameW, L"\\??\\C:\\" );
5876 InitializeObjectAttributes( &attr, &nameW, 0, NULL, NULL );
5878 status = pNtOpenFile( &handle, READ_CONTROL, &attr, &io, 0, 0 );
5879 ok( !status, "open %s failed %#lx\n", wine_dbgstr_w(nameW.Buffer), status );
5881 status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, NULL, 0 );
5882 ok( status == STATUS_INVALID_USER_BUFFER, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER, status );
5884 status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_data, 0 );
5885 ok( status == STATUS_INVALID_USER_BUFFER, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER, status );
5887 /* a volume cannot be a reparse point by definition */
5888 status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_data, 1 );
5889 ok( status == STATUS_NOT_A_REPARSE_POINT, "expected %#lx, got %#lx\n", STATUS_NOT_A_REPARSE_POINT, status );
5891 CloseHandle( handle );
5894 START_TEST(file)
5896 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
5897 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
5898 if (!hntdll)
5900 skip("not running on NT, skipping test\n");
5901 return;
5904 pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
5905 pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
5907 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
5908 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
5909 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
5910 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
5911 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
5912 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
5913 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
5914 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
5915 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
5916 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
5917 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
5918 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
5919 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
5920 pNtFsControlFile = (void *)GetProcAddress(hntdll, "NtFsControlFile");
5921 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
5922 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
5923 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
5924 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
5925 pNtRemoveIoCompletionEx = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletionEx");
5926 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
5927 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
5928 pNtQueryAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryAttributesFile");
5929 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
5930 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
5931 pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
5932 pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
5933 pNtFlushBuffersFile = (void *)GetProcAddress(hntdll, "NtFlushBuffersFile");
5934 pNtQueryEaFile = (void *)GetProcAddress(hntdll, "NtQueryEaFile");
5936 test_read_write();
5937 test_NtCreateFile();
5938 create_file_test();
5939 open_file_test();
5940 delete_file_test();
5941 read_file_test();
5942 append_file_test();
5943 nt_mailslot_test();
5944 test_set_io_completion();
5945 test_file_io_completion();
5946 test_file_basic_information();
5947 test_file_all_information();
5948 test_file_both_information();
5949 test_file_name_information();
5950 test_file_full_size_information();
5951 test_file_all_name_information();
5952 test_file_rename_information(FileRenameInformation);
5953 test_file_rename_information(FileRenameInformationEx);
5954 test_file_rename_information_ex();
5955 test_file_link_information(FileLinkInformation);
5956 test_file_link_information(FileLinkInformationEx);
5957 test_file_link_information_ex();
5958 test_file_disposition_information();
5959 test_file_completion_information();
5960 test_file_id_information();
5961 test_file_access_information();
5962 test_file_attribute_tag_information();
5963 test_file_stat_information();
5964 test_dotfile_file_attributes();
5965 test_file_mode();
5966 test_file_readonly_access();
5967 test_query_volume_information_file();
5968 test_query_attribute_information_file();
5969 test_ioctl();
5970 test_query_ea();
5971 test_flush_buffers_file();
5972 test_mailslot_name();
5973 test_reparse_points();