d2d1: Add a helper to set error state.
[wine.git] / dlls / ntdll / tests / file.c
blob0f4281d93bd669dd56f78e344dc03d0c136060f8
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*);
88 static inline BOOL is_signaled( HANDLE obj )
90 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
93 #define TEST_BUF_LEN 3
95 static HANDLE create_temp_file( ULONG flags )
97 char path[MAX_PATH], buffer[MAX_PATH];
98 HANDLE handle;
100 GetTempPathA( MAX_PATH, path );
101 GetTempFileNameA( path, "foo", 0, buffer );
102 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
103 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
104 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
105 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
108 #define CVALUE_FIRST 0xfffabbcc
109 #define CKEY_FIRST 0x1030341
110 #define CKEY_SECOND 0x132E46
112 static ULONG get_pending_msgs(HANDLE h)
114 NTSTATUS res;
115 ULONG a, req;
117 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
118 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
119 if (res != STATUS_SUCCESS) return -1;
120 ok( req == sizeof(a), "Unexpected response size: %x\n", req );
121 return a;
124 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
126 int *count = arg;
128 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
129 iosb, U(*iosb).Status, iosb->Information );
130 (*count)++;
131 ok( !reserved, "reserved is not 0: %x\n", reserved );
134 static void create_file_test(void)
136 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
137 '\\','f','a','i','l','i','n','g',0};
138 static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
139 static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
140 static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
141 static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
142 static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
143 static const char testdata[] = "Hello World";
144 FILE_NETWORK_OPEN_INFORMATION info;
145 NTSTATUS status;
146 HANDLE dir, file;
147 WCHAR path[MAX_PATH];
148 OBJECT_ATTRIBUTES attr;
149 IO_STATUS_BLOCK io;
150 UNICODE_STRING nameW;
151 LARGE_INTEGER offset;
152 char buf[32];
153 DWORD ret;
155 GetCurrentDirectoryW( MAX_PATH, path );
156 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
157 attr.Length = sizeof(attr);
158 attr.RootDirectory = 0;
159 attr.ObjectName = &nameW;
160 attr.Attributes = OBJ_CASE_INSENSITIVE;
161 attr.SecurityDescriptor = NULL;
162 attr.SecurityQualityOfService = NULL;
164 /* try various open modes and options on directories */
165 status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0,
166 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
167 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
169 U(io).Status = 0xdeadbeef;
170 offset.QuadPart = 0;
171 status = pNtReadFile( dir, NULL, NULL, NULL, &io, buf, sizeof(buf), &offset, NULL );
172 todo_wine
173 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtReadFile error %08x\n", status );
174 if (status == STATUS_PENDING)
176 ret = WaitForSingleObject( dir, 1000 );
177 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
178 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
179 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
182 U(io).Status = 0xdeadbeef;
183 offset.QuadPart = 0;
184 status = pNtWriteFile( dir, NULL, NULL, NULL, &io, testdata, sizeof(testdata), &offset, NULL);
185 todo_wine
186 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtWriteFile error %08x\n", status );
187 if (status == STATUS_PENDING)
189 ret = WaitForSingleObject( dir, 1000 );
190 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
191 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
192 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
195 CloseHandle( dir );
197 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
198 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
199 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
200 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
202 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
203 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
204 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
205 CloseHandle( dir );
207 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
208 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
209 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
211 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
212 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
213 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
215 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
216 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
217 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
219 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
220 FILE_OPEN, 0, NULL, 0 );
221 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
222 CloseHandle( dir );
224 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
225 FILE_CREATE, 0, NULL, 0 );
226 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
227 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
229 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
230 FILE_OPEN_IF, 0, NULL, 0 );
231 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
232 CloseHandle( dir );
234 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
235 FILE_SUPERSEDE, 0, NULL, 0 );
236 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
237 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
239 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
240 FILE_OVERWRITE, 0, NULL, 0 );
241 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
242 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
244 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
245 FILE_OVERWRITE_IF, 0, NULL, 0 );
246 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
247 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
249 pRtlFreeUnicodeString( &nameW );
251 pRtlInitUnicodeString( &nameW, systemrootW );
252 attr.Length = sizeof(attr);
253 attr.RootDirectory = NULL;
254 attr.ObjectName = &nameW;
255 attr.Attributes = OBJ_CASE_INSENSITIVE;
256 attr.SecurityDescriptor = NULL;
257 attr.SecurityQualityOfService = NULL;
258 dir = NULL;
259 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
260 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
261 todo_wine
262 ok( status == STATUS_INVALID_PARAMETER,
263 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
265 /* Invalid chars in file/dirnames */
266 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
267 attr.ObjectName = &nameW;
268 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
269 FILE_SHARE_READ, FILE_CREATE,
270 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
271 ok(status == STATUS_OBJECT_NAME_INVALID,
272 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
274 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
275 0, FILE_CREATE,
276 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
277 ok(status == STATUS_OBJECT_NAME_INVALID,
278 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
279 pRtlFreeUnicodeString(&nameW);
281 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
282 attr.ObjectName = &nameW;
283 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
284 FILE_SHARE_READ, FILE_CREATE,
285 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
286 ok(status == STATUS_OBJECT_NAME_INVALID,
287 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
289 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
290 0, FILE_CREATE,
291 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
292 ok(status == STATUS_OBJECT_NAME_INVALID,
293 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
294 pRtlFreeUnicodeString(&nameW);
296 pRtlInitUnicodeString( &nameW, pathInvalidNtW );
297 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
298 FILE_SHARE_READ, FILE_CREATE,
299 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
300 ok( status == STATUS_OBJECT_NAME_INVALID,
301 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
303 status = pNtQueryFullAttributesFile( &attr, &info );
304 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
305 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
307 pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
308 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
309 FILE_SHARE_READ, FILE_CREATE,
310 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
311 ok( status == STATUS_OBJECT_NAME_INVALID,
312 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
314 status = pNtQueryFullAttributesFile( &attr, &info );
315 ok( status == STATUS_OBJECT_NAME_INVALID,
316 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
318 pRtlInitUnicodeString( &nameW, pathInvalidDosW );
319 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
320 FILE_SHARE_READ, FILE_CREATE,
321 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
322 ok( status == STATUS_OBJECT_NAME_INVALID,
323 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
325 status = pNtQueryFullAttributesFile( &attr, &info );
326 ok( status == STATUS_OBJECT_NAME_INVALID,
327 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
330 static void open_file_test(void)
332 static const WCHAR testdirW[] = {'o','p','e','n','f','i','l','e','t','e','s','t',0};
333 static const char testdata[] = "Hello World";
334 static WCHAR fooW[] = {'f','o','o',0};
335 NTSTATUS status;
336 HANDLE dir, root, handle, file;
337 WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
338 BYTE data[1024];
339 OBJECT_ATTRIBUTES attr;
340 IO_STATUS_BLOCK io;
341 UNICODE_STRING nameW;
342 UINT i, len;
343 BOOL ret, restart = TRUE;
344 DWORD numbytes;
346 len = GetWindowsDirectoryW( path, MAX_PATH );
347 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
348 attr.Length = sizeof(attr);
349 attr.RootDirectory = 0;
350 attr.ObjectName = &nameW;
351 attr.Attributes = OBJ_CASE_INSENSITIVE;
352 attr.SecurityDescriptor = NULL;
353 attr.SecurityQualityOfService = NULL;
354 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
355 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
356 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
357 pRtlFreeUnicodeString( &nameW );
359 path[3] = 0; /* root of the drive */
360 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
361 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
362 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
363 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
364 pRtlFreeUnicodeString( &nameW );
366 /* test opening system dir with RootDirectory set to windows dir */
367 GetSystemDirectoryW( path, MAX_PATH );
368 while (path[len] == '\\') len++;
369 nameW.Buffer = path + len;
370 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
371 attr.RootDirectory = dir;
372 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
373 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
374 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
375 CloseHandle( handle );
377 /* try uppercase name */
378 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
379 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
380 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
381 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
382 CloseHandle( handle );
384 /* try with leading backslash */
385 nameW.Buffer--;
386 nameW.Length += sizeof(WCHAR);
387 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
388 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
389 ok( status == STATUS_INVALID_PARAMETER ||
390 status == STATUS_OBJECT_NAME_INVALID ||
391 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
392 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
393 if (!status) CloseHandle( handle );
395 /* try with empty name */
396 nameW.Length = 0;
397 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
398 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
399 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
400 CloseHandle( handle );
401 CloseHandle( dir );
403 GetTempPathW( MAX_PATH, path );
404 lstrcatW( path, testdirW );
405 CreateDirectoryW( path, NULL );
407 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
408 attr.RootDirectory = NULL;
409 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
410 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
411 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
412 pRtlFreeUnicodeString( &nameW );
414 GetTempFileNameW( path, fooW, 0, tmpfile );
415 file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
416 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
417 numbytes = 0xdeadbeef;
418 ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
419 ok( ret, "WriteFile failed with error %u\n", GetLastError() );
420 ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
421 CloseHandle( file );
423 /* try open by file id */
425 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
426 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
428 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
430 restart = FALSE;
432 if (!info->FileId.QuadPart) continue;
434 nameW.Buffer = (WCHAR *)&info->FileId;
435 nameW.Length = sizeof(info->FileId);
436 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
437 attr.RootDirectory = dir;
438 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
439 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
440 FILE_SHARE_READ,
441 FILE_OPEN_BY_FILE_ID |
442 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
443 ok( status == STATUS_SUCCESS, "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
444 if (!status)
446 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
448 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
450 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
452 /* check that it's the same file/directory */
454 /* don't check the size for directories */
455 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
456 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
457 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
459 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
460 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
462 CloseHandle( handle );
464 /* try same thing from drive root */
465 attr.RootDirectory = root;
466 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
467 FILE_SHARE_READ|FILE_SHARE_WRITE,
468 FILE_OPEN_BY_FILE_ID |
469 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
470 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
471 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
472 if (!status) CloseHandle( handle );
476 CloseHandle( dir );
477 CloseHandle( root );
479 pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
480 attr.Length = sizeof(attr);
481 attr.RootDirectory = 0;
482 attr.ObjectName = &nameW;
483 attr.Attributes = OBJ_CASE_INSENSITIVE;
484 attr.SecurityDescriptor = NULL;
485 attr.SecurityQualityOfService = NULL;
486 status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
487 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
488 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
489 pRtlFreeUnicodeString( &nameW );
491 numbytes = 0xdeadbeef;
492 memset( data, 0, sizeof(data) );
493 ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
494 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
495 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
496 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
498 nameW.Length = sizeof(fooW) - sizeof(WCHAR);
499 nameW.Buffer = fooW;
500 attr.RootDirectory = file;
501 attr.ObjectName = &nameW;
502 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
503 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
504 ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
505 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
507 nameW.Length = 0;
508 nameW.Buffer = NULL;
509 attr.RootDirectory = file;
510 attr.ObjectName = &nameW;
511 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
512 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
513 ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
515 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
516 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
517 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
518 ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
520 numbytes = 0xdeadbeef;
521 memset( data, 0, sizeof(data) );
522 ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
523 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
524 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
525 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
527 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
528 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
529 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
530 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
532 CloseHandle( file );
533 CloseHandle( root );
534 DeleteFileW( tmpfile );
535 RemoveDirectoryW( path );
538 static void delete_file_test(void)
540 NTSTATUS ret;
541 OBJECT_ATTRIBUTES attr;
542 UNICODE_STRING nameW;
543 WCHAR pathW[MAX_PATH];
544 WCHAR pathsubW[MAX_PATH];
545 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
546 static const WCHAR subdirW[] = {'\\','s','u','b',0};
548 ret = GetTempPathW(MAX_PATH, pathW);
549 if (!ret)
551 ok(0, "couldn't get temp dir\n");
552 return;
554 if (ret + ARRAY_SIZE(testdirW)-1 + ARRAY_SIZE(subdirW)-1 >= MAX_PATH)
556 ok(0, "MAX_PATH exceeded in constructing paths\n");
557 return;
560 lstrcatW(pathW, testdirW);
561 lstrcpyW(pathsubW, pathW);
562 lstrcatW(pathsubW, subdirW);
564 ret = CreateDirectoryW(pathW, NULL);
565 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
566 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
568 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
569 return;
572 attr.Length = sizeof(attr);
573 attr.RootDirectory = 0;
574 attr.Attributes = OBJ_CASE_INSENSITIVE;
575 attr.ObjectName = &nameW;
576 attr.SecurityDescriptor = NULL;
577 attr.SecurityQualityOfService = NULL;
579 /* test NtDeleteFile on an empty directory */
580 ret = pNtDeleteFile(&attr);
581 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
582 ret = RemoveDirectoryW(pathW);
583 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
585 /* test NtDeleteFile on a non-empty directory */
586 ret = CreateDirectoryW(pathW, NULL);
587 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
588 ret = CreateDirectoryW(pathsubW, NULL);
589 ok(ret == TRUE, "couldn't create directory subdir\n");
590 ret = pNtDeleteFile(&attr);
591 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
592 ret = RemoveDirectoryW(pathsubW);
593 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
594 ret = RemoveDirectoryW(pathW);
595 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
597 pRtlFreeUnicodeString( &nameW );
600 static void read_file_test(void)
602 const char text[] = "foobar";
603 HANDLE handle;
604 IO_STATUS_BLOCK iosb;
605 NTSTATUS status;
606 int apc_count = 0;
607 char buffer[128];
608 LARGE_INTEGER offset;
609 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
611 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
612 apc_count = 0;
613 U(iosb).Status = 0xdeadbabe;
614 iosb.Information = 0xdeadbeef;
615 offset.QuadPart = 0;
616 ResetEvent( event );
617 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
618 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
619 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
620 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
621 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
622 ok( is_signaled( event ), "event is not signaled\n" );
623 ok( !apc_count, "apc was called\n" );
624 SleepEx( 1, TRUE ); /* alertable sleep */
625 ok( apc_count == 1, "apc was not called\n" );
627 apc_count = 0;
628 U(iosb).Status = 0xdeadbabe;
629 iosb.Information = 0xdeadbeef;
630 offset.QuadPart = 0;
631 ResetEvent( event );
632 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
633 ok( status == STATUS_SUCCESS ||
634 status == STATUS_PENDING, /* vista */
635 "wrong status %x\n", status );
636 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
637 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
638 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
639 ok( is_signaled( event ), "event is not signaled\n" );
640 ok( !apc_count, "apc was called\n" );
641 SleepEx( 1, TRUE ); /* alertable sleep */
642 ok( apc_count == 1, "apc was not called\n" );
644 /* read beyond eof */
645 apc_count = 0;
646 U(iosb).Status = 0xdeadbabe;
647 iosb.Information = 0xdeadbeef;
648 offset.QuadPart = strlen(text) + 2;
649 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
650 ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
651 if (status == STATUS_PENDING) /* vista */
653 WaitForSingleObject( event, 1000 );
654 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
655 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
656 ok( is_signaled( event ), "event is not signaled\n" );
657 ok( !apc_count, "apc was called\n" );
658 SleepEx( 1, TRUE ); /* alertable sleep */
659 ok( apc_count == 1, "apc was not called\n" );
661 CloseHandle( handle );
663 /* now a non-overlapped file */
664 if (!(handle = create_temp_file(0))) return;
665 apc_count = 0;
666 U(iosb).Status = 0xdeadbabe;
667 iosb.Information = 0xdeadbeef;
668 offset.QuadPart = 0;
669 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
670 ok( status == STATUS_END_OF_FILE ||
671 status == STATUS_SUCCESS ||
672 status == STATUS_PENDING, /* vista */
673 "wrong status %x\n", status );
674 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
675 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
676 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
677 ok( is_signaled( event ), "event is not signaled\n" );
678 ok( !apc_count, "apc was called\n" );
679 SleepEx( 1, TRUE ); /* alertable sleep */
680 ok( apc_count == 1, "apc was not called\n" );
682 apc_count = 0;
683 U(iosb).Status = 0xdeadbabe;
684 iosb.Information = 0xdeadbeef;
685 offset.QuadPart = 0;
686 ResetEvent( event );
687 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
688 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
689 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
690 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
691 ok( is_signaled( event ), "event is not signaled\n" );
692 ok( !apc_count, "apc was called\n" );
693 SleepEx( 1, TRUE ); /* alertable sleep */
694 todo_wine ok( !apc_count, "apc was called\n" );
696 /* read beyond eof */
697 apc_count = 0;
698 U(iosb).Status = 0xdeadbabe;
699 iosb.Information = 0xdeadbeef;
700 offset.QuadPart = strlen(text) + 2;
701 ResetEvent( event );
702 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
703 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
704 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
705 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
706 ok( is_signaled( event ), "event is not signaled\n" );
707 ok( !apc_count, "apc was called\n" );
708 SleepEx( 1, TRUE ); /* alertable sleep */
709 ok( !apc_count, "apc was called\n" );
711 CloseHandle( handle );
713 CloseHandle( event );
716 static void append_file_test(void)
718 static const char text[6] = "foobar";
719 HANDLE handle;
720 NTSTATUS status;
721 IO_STATUS_BLOCK iosb;
722 LARGE_INTEGER offset;
723 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
724 DWORD ret;
726 GetTempPathA( MAX_PATH, path );
727 GetTempFileNameA( path, "foo", 0, buffer );
729 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
730 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
732 U(iosb).Status = -1;
733 iosb.Information = -1;
734 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
735 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
736 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
737 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
739 CloseHandle(handle);
741 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
742 It matches the O_WRONLY|O_APPEND open() posix behavior */
743 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
744 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
746 U(iosb).Status = -1;
747 iosb.Information = -1;
748 offset.QuadPart = 1;
749 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
750 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
751 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
752 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
754 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
755 ok(ret == 4, "expected 4, got %u\n", ret);
757 U(iosb).Status = -1;
758 iosb.Information = -1;
759 offset.QuadPart = 3;
760 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
761 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
762 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
763 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
765 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
766 ok(ret == 6, "expected 6, got %u\n", ret);
768 CloseHandle(handle);
770 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
771 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
773 memset(buf, 0, sizeof(buf));
774 U(iosb).Status = -1;
775 iosb.Information = -1;
776 offset.QuadPart = 0;
777 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
778 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
779 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
780 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
781 buf[6] = 0;
782 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
784 U(iosb).Status = -1;
785 iosb.Information = -1;
786 offset.QuadPart = 0;
787 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
788 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
789 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
790 ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
792 memset(buf, 0, sizeof(buf));
793 U(iosb).Status = -1;
794 iosb.Information = -1;
795 offset.QuadPart = 0;
796 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
797 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
798 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
799 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
800 buf[6] = 0;
801 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
803 CloseHandle(handle);
804 DeleteFileA(buffer);
807 static void nt_mailslot_test(void)
809 HANDLE hslot;
810 ACCESS_MASK DesiredAccess;
811 OBJECT_ATTRIBUTES attr;
813 ULONG CreateOptions;
814 ULONG MailslotQuota;
815 ULONG MaxMessageSize;
816 LARGE_INTEGER TimeOut;
817 IO_STATUS_BLOCK IoStatusBlock;
818 NTSTATUS rc;
819 UNICODE_STRING str;
820 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
821 'R',':','\\','F','R','E','D','\0' };
823 TimeOut.QuadPart = -1;
825 pRtlInitUnicodeString(&str, buffer1);
826 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
827 CreateOptions = MailslotQuota = MaxMessageSize = 0;
828 DesiredAccess = GENERIC_READ;
831 * Check for NULL pointer handling
833 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
834 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
835 &TimeOut);
836 ok( rc == STATUS_ACCESS_VIOLATION ||
837 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
838 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
841 * Test to see if the Timeout can be NULL
843 hslot = (HANDLE)0xdeadbeef;
844 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
845 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
846 NULL);
847 ok( rc == STATUS_SUCCESS ||
848 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
849 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
850 ok( hslot != 0, "Handle is invalid\n");
852 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
855 * Test a valid call
857 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
858 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
859 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
860 &TimeOut);
861 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
862 ok( hslot != 0, "Handle is invalid\n");
864 rc = pNtClose(hslot);
865 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
868 static void WINAPI user_apc_proc(ULONG_PTR arg)
870 unsigned int *apc_count = (unsigned int *)arg;
871 ++*apc_count;
874 static void test_set_io_completion(void)
876 FILE_IO_COMPLETION_INFORMATION info[2] = {{0}};
877 LARGE_INTEGER timeout = {{0}};
878 unsigned int apc_count;
879 IO_STATUS_BLOCK iosb;
880 ULONG_PTR key, value;
881 NTSTATUS res;
882 ULONG count;
883 SIZE_T size = 3;
884 HANDLE h;
886 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
888 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
889 ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#x\n", res );
890 ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h );
892 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
893 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletion failed: %#x\n", res );
895 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
896 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
898 count = get_pending_msgs(h);
899 ok( count == 1, "Unexpected msg count: %d\n", count );
901 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
902 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res );
903 ok( key == CKEY_FIRST, "Invalid completion key: %#lx\n", key );
904 ok( iosb.Information == size, "Invalid iosb.Information: %lu\n", iosb.Information );
905 ok( U(iosb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid iosb.Status: %#x\n", U(iosb).Status );
906 ok( value == CVALUE_FIRST, "Invalid completion value: %#lx\n", value );
908 count = get_pending_msgs(h);
909 ok( !count, "Unexpected msg count: %d\n", count );
911 if (!pNtRemoveIoCompletionEx)
913 skip("NtRemoveIoCompletionEx() not present\n");
914 pNtClose( h );
915 return;
918 count = 0xdeadbeef;
919 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
920 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#x\n", res );
921 ok( count == 1, "wrong count %u\n", count );
923 res = pNtSetIoCompletion( h, 123, 456, 789, size );
924 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res );
926 count = 0xdeadbeef;
927 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
928 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#x\n", res );
929 ok( count == 1, "wrong count %u\n", count );
930 ok( info[0].CompletionKey == 123, "wrong key %#lx\n", info[0].CompletionKey );
931 ok( info[0].CompletionValue == 456, "wrong value %#lx\n", info[0].CompletionValue );
932 ok( info[0].IoStatusBlock.Information == size, "wrong information %#lx\n",
933 info[0].IoStatusBlock.Information );
934 ok( U(info[0].IoStatusBlock).Status == 789, "wrong status %#x\n", U(info[0].IoStatusBlock).Status);
936 res = pNtSetIoCompletion( h, 123, 456, 789, size );
937 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res );
939 res = pNtSetIoCompletion( h, 12, 34, 56, size );
940 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res );
942 count = 0xdeadbeef;
943 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
944 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#x\n", res );
945 ok( count == 2, "wrong count %u\n", count );
946 ok( info[0].CompletionKey == 123, "wrong key %#lx\n", info[0].CompletionKey );
947 ok( info[0].CompletionValue == 456, "wrong value %#lx\n", info[0].CompletionValue );
948 ok( info[0].IoStatusBlock.Information == size, "wrong information %#lx\n",
949 info[0].IoStatusBlock.Information );
950 ok( U(info[0].IoStatusBlock).Status == 789, "wrong status %#x\n", U(info[0].IoStatusBlock).Status);
951 ok( info[1].CompletionKey == 12, "wrong key %#lx\n", info[1].CompletionKey );
952 ok( info[1].CompletionValue == 34, "wrong value %#lx\n", info[1].CompletionValue );
953 ok( info[1].IoStatusBlock.Information == size, "wrong information %#lx\n",
954 info[1].IoStatusBlock.Information );
955 ok( U(info[1].IoStatusBlock).Status == 56, "wrong status %#x\n", U(info[1].IoStatusBlock).Status);
957 apc_count = 0;
958 QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count );
960 count = 0xdeadbeef;
961 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
962 ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#x\n", res );
963 ok( count == 1, "wrong count %u\n", count );
964 ok( !apc_count, "wrong apc count %d\n", apc_count );
966 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE );
967 ok( res == STATUS_USER_APC, "NtRemoveIoCompletionEx failed: %#x\n", res );
968 ok( count == 1, "wrong count %u\n", count );
969 ok( apc_count == 1, "wrong apc count %u\n", apc_count );
971 apc_count = 0;
972 QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count );
974 res = pNtSetIoCompletion( h, 123, 456, 789, size );
975 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res );
977 res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE );
978 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#x\n", res );
979 ok( count == 1, "wrong count %u\n", count );
980 ok( !apc_count, "wrong apc count %u\n", apc_count );
982 SleepEx( 1, TRUE );
984 pNtClose( h );
987 static void test_file_io_completion(void)
989 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
991 IO_STATUS_BLOCK iosb;
992 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
993 FILE_COMPLETION_INFORMATION fci;
994 LARGE_INTEGER timeout = {{0}};
995 HANDLE server, client;
996 ULONG_PTR key, value;
997 OVERLAPPED o = {0};
998 int apc_count = 0;
999 NTSTATUS res;
1000 DWORD read;
1001 long count;
1002 HANDLE h;
1004 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
1005 ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#x\n", res );
1006 ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h );
1007 fci.CompletionPort = h;
1008 fci.CompletionKey = CKEY_SECOND;
1010 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND,
1011 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1012 4, 1024, 1024, 1000, NULL );
1013 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() );
1014 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1015 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1016 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
1018 U(iosb).Status = 0xdeadbeef;
1019 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1020 ok( res == STATUS_INVALID_PARAMETER, "NtSetInformationFile failed: %#x\n", res );
1021 todo_wine
1022 ok( U(iosb).Status == 0xdeadbeef, "wrong status %#x\n", U(iosb).Status );
1023 CloseHandle( client );
1024 CloseHandle( server );
1026 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1027 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1028 4, 1024, 1024, 1000, NULL );
1029 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() );
1030 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1031 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1032 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
1034 U(iosb).Status = 0xdeadbeef;
1035 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1036 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %#x\n", res );
1037 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %#x\n", U(iosb).Status );
1039 memset( send_buf, 0, TEST_BUF_LEN );
1040 memset( recv_buf, 0xde, TEST_BUF_LEN );
1041 count = get_pending_msgs(h);
1042 ok( !count, "Unexpected msg count: %ld\n", count );
1043 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1044 count = get_pending_msgs(h);
1045 ok( !count, "Unexpected msg count: %ld\n", count );
1046 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1048 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1049 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res );
1050 ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key );
1051 ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information );
1052 ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status );
1053 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value );
1054 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ),
1055 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1056 recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1057 count = get_pending_msgs(h);
1058 ok( !count, "Unexpected msg count: %ld\n", count );
1060 memset( send_buf, 0, TEST_BUF_LEN );
1061 memset( recv_buf, 0xde, TEST_BUF_LEN );
1062 WriteFile( client, send_buf, 2, &read, NULL );
1063 count = get_pending_msgs(h);
1064 ok( !count, "Unexpected msg count: %ld\n", count );
1065 ReadFile( server, recv_buf, 2, &read, &o);
1066 count = get_pending_msgs(h);
1067 ok( count == 1, "Unexpected msg count: %ld\n", count );
1069 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1070 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res );
1071 ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key );
1072 ok( iosb.Information == 2, "Invalid iosb.Information: %ld\n", iosb.Information );
1073 ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status );
1074 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value );
1075 ok( !memcmp( send_buf, recv_buf, 2 ),
1076 "Receive buffer (%02x %02x) did not match send buffer (%02x %02x)\n",
1077 recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
1079 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1080 CloseHandle( server );
1081 count = get_pending_msgs(h);
1082 ok( count == 1, "Unexpected msg count: %ld\n", count );
1084 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1085 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res );
1086 ok( key == CKEY_SECOND, "Invalid completion key: %lx\n", key );
1087 ok( iosb.Information == 0, "Invalid iosb.Information: %ld\n", iosb.Information );
1088 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "Invalid iosb.Status: %x\n", U(iosb).Status );
1089 ok( value == (ULONG_PTR)&o, "Invalid completion value: %lx\n", value );
1091 CloseHandle( client );
1093 /* test associating a completion port with a handle after an async is queued */
1094 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1095 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1096 4, 1024, 1024, 1000, NULL );
1097 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() );
1098 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1099 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1100 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
1102 memset( send_buf, 0, TEST_BUF_LEN );
1103 memset( recv_buf, 0xde, TEST_BUF_LEN );
1104 count = get_pending_msgs(h);
1105 ok( !count, "Unexpected msg count: %ld\n", count );
1106 ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
1108 U(iosb).Status = 0xdeadbeef;
1109 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1110 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1111 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1112 count = get_pending_msgs(h);
1113 ok( !count, "Unexpected msg count: %ld\n", count );
1115 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1117 res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
1118 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res );
1119 ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key );
1120 ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information );
1121 ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status );
1122 ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value );
1123 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ),
1124 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1125 recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1127 count = get_pending_msgs(h);
1128 ok( !count, "Unexpected msg count: %ld\n", count );
1130 /* using APCs on handle with associated completion port is not allowed */
1131 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1132 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1134 CloseHandle( server );
1135 CloseHandle( client );
1137 /* test associating a completion port with a handle after an async using APC is queued */
1138 server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
1139 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1140 4, 1024, 1024, 1000, NULL );
1141 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() );
1142 client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
1143 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1144 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
1146 apc_count = 0;
1147 memset( send_buf, 0, TEST_BUF_LEN );
1148 memset( recv_buf, 0xde, TEST_BUF_LEN );
1149 count = get_pending_msgs(h);
1150 ok( !count, "Unexpected msg count: %ld\n", count );
1152 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1153 ok(res == STATUS_PENDING, "NtReadFile returned %x\n", res);
1155 U(iosb).Status = 0xdeadbeef;
1156 res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1157 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1158 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1159 count = get_pending_msgs(h);
1160 ok( !count, "Unexpected msg count: %ld\n", count );
1162 WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
1164 ok(!apc_count, "apc_count = %u\n", apc_count);
1165 count = get_pending_msgs(h);
1166 ok( !count, "Unexpected msg count: %ld\n", count );
1168 SleepEx(1, TRUE); /* alertable sleep */
1169 ok(apc_count == 1, "apc was not called\n");
1170 count = get_pending_msgs(h);
1171 ok( !count, "Unexpected msg count: %ld\n", count );
1173 /* using APCs on handle with associated completion port is not allowed */
1174 res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1175 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1177 CloseHandle( server );
1178 CloseHandle( client );
1179 pNtClose( h );
1182 static void test_file_full_size_information(void)
1184 IO_STATUS_BLOCK io;
1185 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1186 FILE_FS_SIZE_INFORMATION fsi;
1187 HANDLE h;
1188 NTSTATUS res;
1190 if(!(h = create_temp_file(0))) return ;
1192 memset(&ffsi,0,sizeof(ffsi));
1193 memset(&fsi,0,sizeof(fsi));
1195 /* Assume No Quota Settings configured on Wine Testbot */
1196 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1197 todo_wine ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1198 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1199 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1201 /* Test for FileFsSizeInformation */
1202 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1203 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1204 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1205 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1206 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1207 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1209 /* Assume file system is NTFS */
1210 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1211 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1213 todo_wine
1215 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1216 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1217 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1218 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1219 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1220 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1221 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1222 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1223 wine_dbgstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1224 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1225 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1226 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1227 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1228 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1229 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1230 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1231 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1234 /* Assume file system is NTFS */
1235 todo_wine
1237 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1238 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1241 CloseHandle( h );
1244 static void test_file_basic_information(void)
1246 IO_STATUS_BLOCK io;
1247 FILE_BASIC_INFORMATION fbi;
1248 HANDLE h;
1249 int res;
1250 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1252 if (!(h = create_temp_file(0))) return;
1254 /* Check default first */
1255 memset(&fbi, 0, sizeof(fbi));
1256 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1257 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1258 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1259 "attribute %x not expected\n", fbi.FileAttributes );
1261 /* Then SYSTEM */
1262 /* Clear fbi to avoid setting times */
1263 memset(&fbi, 0, sizeof(fbi));
1264 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1265 U(io).Status = 0xdeadbeef;
1266 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1267 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1268 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1270 memset(&fbi, 0, sizeof(fbi));
1271 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1272 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1273 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1275 /* Then HIDDEN */
1276 memset(&fbi, 0, sizeof(fbi));
1277 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1278 U(io).Status = 0xdeadbeef;
1279 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1280 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1281 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1283 memset(&fbi, 0, sizeof(fbi));
1284 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1285 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1286 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1288 /* Check NORMAL last of all (to make sure we can clear attributes) */
1289 memset(&fbi, 0, sizeof(fbi));
1290 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1291 U(io).Status = 0xdeadbeef;
1292 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1293 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1294 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1296 memset(&fbi, 0, sizeof(fbi));
1297 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1298 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1299 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1301 CloseHandle( h );
1304 static void test_file_all_information(void)
1306 IO_STATUS_BLOCK io;
1307 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1308 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1309 * don't leave enough room there.
1311 struct {
1312 FILE_ALL_INFORMATION fai;
1313 WCHAR buf[256];
1314 } fai_buf;
1315 HANDLE h;
1316 int res;
1317 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1319 if (!(h = create_temp_file(0))) return;
1321 /* Check default first */
1322 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1323 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1324 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1325 "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1327 /* Then SYSTEM */
1328 /* Clear fbi to avoid setting times */
1329 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1330 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1331 U(io).Status = 0xdeadbeef;
1332 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1333 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1334 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1335 U(io).Status = 0xdeadbeef;
1336 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1337 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1338 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1340 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1341 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1342 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1343 todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fai_buf.fai.BasicInformation.FileAttributes );
1345 /* Then HIDDEN */
1346 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1347 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1348 U(io).Status = 0xdeadbeef;
1349 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1350 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1351 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1353 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1354 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1355 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1356 todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fai_buf.fai.BasicInformation.FileAttributes );
1358 /* Check NORMAL last of all (to make sure we can clear attributes) */
1359 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1360 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1361 U(io).Status = 0xdeadbeef;
1362 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1363 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1364 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1366 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1367 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1368 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1369 todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not FILE_ATTRIBUTE_NORMAL\n", fai_buf.fai.BasicInformation.FileAttributes );
1371 CloseHandle( h );
1374 static void delete_object( WCHAR *path )
1376 BOOL ret = DeleteFileW( path );
1377 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1378 "DeleteFileW failed with %u\n", GetLastError() );
1379 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1381 ret = RemoveDirectoryW( path );
1382 ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
1386 static void test_file_rename_information(void)
1388 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1389 static const WCHAR fooW[] = {'f','o','o',0};
1390 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1391 FILE_RENAME_INFORMATION *fri;
1392 FILE_NAME_INFORMATION *fni;
1393 BOOL success, fileDeleted;
1394 UNICODE_STRING name_str;
1395 HANDLE handle, handle2;
1396 IO_STATUS_BLOCK io;
1397 NTSTATUS res;
1399 GetTempPathW( MAX_PATH, tmp_path );
1401 /* oldpath is a file, newpath doesn't exist */
1402 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1403 ok( res != 0, "failed to create temp file\n" );
1404 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1405 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1407 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1408 ok( res != 0, "failed to create temp file\n" );
1409 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1410 DeleteFileW( newpath );
1411 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1412 fri->Replace = FALSE;
1413 fri->RootDir = NULL;
1414 fri->FileNameLength = name_str.Length;
1415 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1416 pRtlFreeUnicodeString( &name_str );
1418 U(io).Status = 0xdeadbeef;
1419 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1420 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1421 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1422 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1423 ok( fileDeleted, "file should not exist\n" );
1424 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1425 ok( !fileDeleted, "file should exist\n" );
1427 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1428 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1429 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1430 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1431 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1432 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1433 HeapFree( GetProcessHeap(), 0, fni );
1435 CloseHandle( handle );
1436 HeapFree( GetProcessHeap(), 0, fri );
1437 delete_object( oldpath );
1438 delete_object( newpath );
1440 /* oldpath is a file, newpath is a file, Replace = FALSE */
1441 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1442 ok( res != 0, "failed to create temp file\n" );
1443 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1444 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1446 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1447 ok( res != 0, "failed to create temp file\n" );
1448 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1449 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1450 fri->Replace = FALSE;
1451 fri->RootDir = NULL;
1452 fri->FileNameLength = name_str.Length;
1453 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1454 pRtlFreeUnicodeString( &name_str );
1456 U(io).Status = 0xdeadbeef;
1457 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1458 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1459 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1460 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1461 ok( !fileDeleted, "file should exist\n" );
1462 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1463 ok( !fileDeleted, "file should exist\n" );
1465 CloseHandle( handle );
1466 HeapFree( GetProcessHeap(), 0, fri );
1467 delete_object( oldpath );
1468 delete_object( newpath );
1470 /* oldpath is a file, newpath is a file, Replace = TRUE */
1471 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1472 ok( res != 0, "failed to create temp file\n" );
1473 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1474 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1476 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1477 ok( res != 0, "failed to create temp file\n" );
1478 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1479 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1480 fri->Replace = TRUE;
1481 fri->RootDir = NULL;
1482 fri->FileNameLength = name_str.Length;
1483 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1484 pRtlFreeUnicodeString( &name_str );
1486 U(io).Status = 0xdeadbeef;
1487 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1488 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1489 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1490 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1491 ok( fileDeleted, "file should not exist\n" );
1492 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1493 ok( !fileDeleted, "file should exist\n" );
1495 CloseHandle( handle );
1496 HeapFree( GetProcessHeap(), 0, fri );
1497 delete_object( oldpath );
1498 delete_object( newpath );
1500 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1501 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1502 ok( res != 0, "failed to create temp file\n" );
1503 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1504 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1506 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1507 ok( res != 0, "failed to create temp file\n" );
1508 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1509 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1511 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1512 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1513 fri->Replace = FALSE;
1514 fri->RootDir = NULL;
1515 fri->FileNameLength = name_str.Length;
1516 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1517 pRtlFreeUnicodeString( &name_str );
1519 U(io).Status = 0xdeadbeef;
1520 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1521 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1522 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1523 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1524 ok( !fileDeleted, "file should exist\n" );
1525 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1526 ok( !fileDeleted, "file should exist\n" );
1528 CloseHandle( handle );
1529 CloseHandle( handle2 );
1530 HeapFree( GetProcessHeap(), 0, fri );
1531 delete_object( oldpath );
1532 delete_object( newpath );
1534 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1535 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1536 ok( res != 0, "failed to create temp file\n" );
1537 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1538 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1540 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1541 ok( res != 0, "failed to create temp file\n" );
1542 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1543 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1545 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1546 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1547 fri->Replace = TRUE;
1548 fri->RootDir = NULL;
1549 fri->FileNameLength = name_str.Length;
1550 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1551 pRtlFreeUnicodeString( &name_str );
1553 U(io).Status = 0xdeadbeef;
1554 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1555 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1556 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1557 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1558 ok( !fileDeleted, "file should exist\n" );
1559 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1560 ok( !fileDeleted, "file should exist\n" );
1562 CloseHandle( handle );
1563 CloseHandle( handle2 );
1564 HeapFree( GetProcessHeap(), 0, fri );
1565 delete_object( oldpath );
1566 delete_object( newpath );
1568 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1569 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1570 ok( res != 0, "failed to create temp file\n" );
1571 DeleteFileW( oldpath );
1572 success = CreateDirectoryW( oldpath, NULL );
1573 ok( success != 0, "failed to create temp directory\n" );
1574 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1575 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1577 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1578 ok( res != 0, "failed to create temp file\n" );
1579 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1580 DeleteFileW( newpath );
1581 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1582 fri->Replace = FALSE;
1583 fri->RootDir = NULL;
1584 fri->FileNameLength = name_str.Length;
1585 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1586 pRtlFreeUnicodeString( &name_str );
1588 U(io).Status = 0xdeadbeef;
1589 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1590 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1591 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1592 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1593 ok( fileDeleted, "file should not exist\n" );
1594 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1595 ok( !fileDeleted, "file should exist\n" );
1597 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1598 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1599 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1600 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1601 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1602 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1603 HeapFree( GetProcessHeap(), 0, fni );
1605 CloseHandle( handle );
1606 HeapFree( GetProcessHeap(), 0, fri );
1607 delete_object( oldpath );
1608 delete_object( newpath );
1610 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1611 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1612 ok( res != 0, "failed to create temp file\n" );
1613 DeleteFileW( oldpath );
1614 success = CreateDirectoryW( oldpath, NULL );
1615 ok( success != 0, "failed to create temp directory\n" );
1616 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1617 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1619 lstrcpyW( newpath, oldpath );
1620 lstrcatW( newpath, foo_txtW );
1621 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1622 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1624 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1625 ok( res != 0, "failed to create temp file\n" );
1626 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1627 DeleteFileW( newpath );
1628 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1629 fri->Replace = FALSE;
1630 fri->RootDir = NULL;
1631 fri->FileNameLength = name_str.Length;
1632 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1633 pRtlFreeUnicodeString( &name_str );
1635 U(io).Status = 0xdeadbeef;
1636 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1637 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1638 todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1639 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1640 todo_wine ok( !fileDeleted, "file should exist\n" );
1641 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1642 todo_wine ok( fileDeleted, "file should not exist\n" );
1644 CloseHandle( handle );
1645 CloseHandle( handle2 );
1646 HeapFree( GetProcessHeap(), 0, fri );
1647 delete_object( oldpath );
1648 if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1650 lstrcpyW( oldpath, newpath );
1651 lstrcatW( oldpath, foo_txtW );
1652 delete_object( oldpath );
1654 delete_object( newpath );
1656 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1657 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1658 ok( res != 0, "failed to create temp file\n" );
1659 DeleteFileW( oldpath );
1660 success = CreateDirectoryW( oldpath, NULL );
1661 ok( success != 0, "failed to create temp directory\n" );
1662 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1663 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1665 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1666 ok( res != 0, "failed to create temp file\n" );
1667 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1668 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1669 fri->Replace = FALSE;
1670 fri->RootDir = NULL;
1671 fri->FileNameLength = name_str.Length;
1672 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1673 pRtlFreeUnicodeString( &name_str );
1675 U(io).Status = 0xdeadbeef;
1676 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1677 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1678 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1679 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1680 ok( !fileDeleted, "file should exist\n" );
1681 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1682 ok( !fileDeleted, "file should exist\n" );
1684 CloseHandle( handle );
1685 HeapFree( GetProcessHeap(), 0, fri );
1686 delete_object( oldpath );
1687 delete_object( newpath );
1689 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1690 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1691 ok( res != 0, "failed to create temp file\n" );
1692 DeleteFileW( oldpath );
1693 success = CreateDirectoryW( oldpath, NULL );
1694 ok( success != 0, "failed to create temp directory\n" );
1695 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1696 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1698 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1699 ok( res != 0, "failed to create temp file\n" );
1700 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1701 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1703 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1704 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1705 fri->Replace = FALSE;
1706 fri->RootDir = NULL;
1707 fri->FileNameLength = name_str.Length;
1708 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1709 pRtlFreeUnicodeString( &name_str );
1711 U(io).Status = 0xdeadbeef;
1712 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1713 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1714 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1715 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1716 ok( !fileDeleted, "file should exist\n" );
1717 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1718 ok( !fileDeleted, "file should exist\n" );
1720 CloseHandle( handle );
1721 CloseHandle( handle2 );
1722 HeapFree( GetProcessHeap(), 0, fri );
1723 delete_object( oldpath );
1724 delete_object( newpath );
1726 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1727 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1728 ok( res != 0, "failed to create temp file\n" );
1729 DeleteFileW( oldpath );
1730 success = CreateDirectoryW( oldpath, NULL );
1731 ok( success != 0, "failed to create temp directory\n" );
1732 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1733 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1735 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1736 ok( res != 0, "failed to create temp file\n" );
1737 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1738 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1739 fri->Replace = TRUE;
1740 fri->RootDir = NULL;
1741 fri->FileNameLength = name_str.Length;
1742 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1743 pRtlFreeUnicodeString( &name_str );
1745 U(io).Status = 0xdeadbeef;
1746 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1747 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1748 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1749 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1750 ok( fileDeleted, "file should not exist\n" );
1751 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1752 ok( !fileDeleted, "file should exist\n" );
1754 CloseHandle( handle );
1755 HeapFree( GetProcessHeap(), 0, fri );
1756 delete_object( oldpath );
1757 delete_object( newpath );
1759 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1760 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1761 ok( res != 0, "failed to create temp file\n" );
1762 DeleteFileW( oldpath );
1763 success = CreateDirectoryW( oldpath, NULL );
1764 ok( success != 0, "failed to create temp directory\n" );
1765 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1766 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1768 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1769 ok( res != 0, "failed to create temp file\n" );
1770 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1771 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1773 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1774 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1775 fri->Replace = TRUE;
1776 fri->RootDir = NULL;
1777 fri->FileNameLength = name_str.Length;
1778 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1779 pRtlFreeUnicodeString( &name_str );
1781 U(io).Status = 0xdeadbeef;
1782 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1783 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1784 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1785 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1786 ok( !fileDeleted, "file should exist\n" );
1787 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1788 ok( !fileDeleted, "file should exist\n" );
1790 CloseHandle( handle );
1791 CloseHandle( handle2 );
1792 HeapFree( GetProcessHeap(), 0, fri );
1793 delete_object( oldpath );
1794 delete_object( newpath );
1796 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1797 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1798 ok( res != 0, "failed to create temp file\n" );
1799 DeleteFileW( oldpath );
1800 success = CreateDirectoryW( oldpath, NULL );
1801 ok( success != 0, "failed to create temp directory\n" );
1802 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1803 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1805 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1806 ok( res != 0, "failed to create temp file\n" );
1807 DeleteFileW( newpath );
1808 success = CreateDirectoryW( newpath, NULL );
1809 ok( success != 0, "failed to create temp directory\n" );
1810 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1811 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1812 fri->Replace = FALSE;
1813 fri->RootDir = NULL;
1814 fri->FileNameLength = name_str.Length;
1815 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1816 pRtlFreeUnicodeString( &name_str );
1818 U(io).Status = 0xdeadbeef;
1819 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1820 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1821 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1822 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1823 ok( !fileDeleted, "file should exist\n" );
1824 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1825 ok( !fileDeleted, "file should exist\n" );
1827 CloseHandle( handle );
1828 HeapFree( GetProcessHeap(), 0, fri );
1829 delete_object( oldpath );
1830 delete_object( newpath );
1832 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1833 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1834 ok( res != 0, "failed to create temp file\n" );
1835 DeleteFileW( oldpath );
1836 success = CreateDirectoryW( oldpath, NULL );
1837 ok( success != 0, "failed to create temp directory\n" );
1838 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1839 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1841 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1842 ok( res != 0, "failed to create temp file\n" );
1843 DeleteFileW( newpath );
1844 success = CreateDirectoryW( newpath, NULL );
1845 ok( success != 0, "failed to create temp directory\n" );
1846 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1847 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1848 fri->Replace = TRUE;
1849 fri->RootDir = NULL;
1850 fri->FileNameLength = name_str.Length;
1851 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1852 pRtlFreeUnicodeString( &name_str );
1854 U(io).Status = 0xdeadbeef;
1855 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1856 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1857 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1858 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1859 ok( !fileDeleted, "file should exist\n" );
1860 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1861 ok( !fileDeleted, "file should exist\n" );
1863 CloseHandle( handle );
1864 HeapFree( GetProcessHeap(), 0, fri );
1865 delete_object( oldpath );
1866 delete_object( newpath );
1868 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
1869 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1870 ok( res != 0, "failed to create temp file\n" );
1871 DeleteFileW( oldpath );
1872 success = CreateDirectoryW( oldpath, NULL );
1873 ok( success != 0, "failed to create temp directory\n" );
1874 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1875 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1877 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1878 ok( res != 0, "failed to create temp file\n" );
1879 DeleteFileW( newpath );
1880 success = CreateDirectoryW( newpath, NULL );
1881 ok( success != 0, "failed to create temp directory\n" );
1882 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1883 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1885 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1886 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1887 fri->Replace = TRUE;
1888 fri->RootDir = NULL;
1889 fri->FileNameLength = name_str.Length;
1890 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1891 pRtlFreeUnicodeString( &name_str );
1893 U(io).Status = 0xdeadbeef;
1894 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1895 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1896 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1897 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1898 ok( !fileDeleted, "file should exist\n" );
1899 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1900 ok( !fileDeleted, "file should exist\n" );
1902 CloseHandle( handle );
1903 CloseHandle( handle2 );
1904 HeapFree( GetProcessHeap(), 0, fri );
1905 delete_object( oldpath );
1906 delete_object( newpath );
1908 /* oldpath is a file, newpath is a directory, Replace = FALSE */
1909 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1910 ok( res != 0, "failed to create temp file\n" );
1911 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1912 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1914 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1915 ok( res != 0, "failed to create temp file\n" );
1916 DeleteFileW( newpath );
1917 success = CreateDirectoryW( newpath, NULL );
1918 ok( success != 0, "failed to create temp directory\n" );
1919 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1920 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1921 fri->Replace = FALSE;
1922 fri->RootDir = NULL;
1923 fri->FileNameLength = name_str.Length;
1924 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1925 pRtlFreeUnicodeString( &name_str );
1927 U(io).Status = 0xdeadbeef;
1928 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1929 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1930 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1931 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1932 ok( !fileDeleted, "file should exist\n" );
1933 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1934 ok( !fileDeleted, "file should exist\n" );
1936 CloseHandle( handle );
1937 HeapFree( GetProcessHeap(), 0, fri );
1938 delete_object( oldpath );
1939 delete_object( newpath );
1941 /* oldpath is a file, newpath is a directory, Replace = TRUE */
1942 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1943 ok( res != 0, "failed to create temp file\n" );
1944 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1945 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1947 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1948 ok( res != 0, "failed to create temp file\n" );
1949 DeleteFileW( newpath );
1950 success = CreateDirectoryW( newpath, NULL );
1951 ok( success != 0, "failed to create temp directory\n" );
1952 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1953 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1954 fri->Replace = TRUE;
1955 fri->RootDir = NULL;
1956 fri->FileNameLength = name_str.Length;
1957 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1958 pRtlFreeUnicodeString( &name_str );
1960 U(io).Status = 0xdeadbeef;
1961 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1962 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1963 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1964 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1965 ok( !fileDeleted, "file should exist\n" );
1966 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1967 ok( !fileDeleted, "file should exist\n" );
1969 CloseHandle( handle );
1970 HeapFree( GetProcessHeap(), 0, fri );
1971 delete_object( oldpath );
1972 delete_object( newpath );
1974 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
1975 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1976 ok( res != 0, "failed to create temp file\n" );
1977 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1978 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1980 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1981 ok( res != 0, "failed to create temp file\n" );
1982 DeleteFileW( newpath );
1983 for (filename = newpath, p = newpath; *p; p++)
1984 if (*p == '\\') filename = p + 1;
1985 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1986 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1988 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
1989 fri->Replace = FALSE;
1990 fri->RootDir = handle2;
1991 fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
1992 memcpy( fri->FileName, filename, fri->FileNameLength );
1994 U(io).Status = 0xdeadbeef;
1995 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1996 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1997 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1998 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1999 ok( fileDeleted, "file should not exist\n" );
2000 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2001 ok( !fileDeleted, "file should exist\n" );
2003 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2004 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2005 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2006 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2007 todo_wine ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
2008 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
2009 HeapFree( GetProcessHeap(), 0, fni );
2011 CloseHandle( handle );
2012 CloseHandle( handle2 );
2013 HeapFree( GetProcessHeap(), 0, fri );
2014 delete_object( oldpath );
2015 delete_object( newpath );
2018 static void test_file_link_information(void)
2020 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
2021 static const WCHAR fooW[] = {'f','o','o',0};
2022 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
2023 FILE_LINK_INFORMATION *fli;
2024 FILE_NAME_INFORMATION *fni;
2025 BOOL success, fileDeleted;
2026 UNICODE_STRING name_str;
2027 HANDLE handle, handle2;
2028 IO_STATUS_BLOCK io;
2029 NTSTATUS res;
2031 GetTempPathW( MAX_PATH, tmp_path );
2033 /* oldpath is a file, newpath doesn't exist */
2034 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2035 ok( res != 0, "failed to create temp file\n" );
2036 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2037 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2039 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2040 ok( res != 0, "failed to create temp file\n" );
2041 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2042 DeleteFileW( newpath );
2043 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2044 fli->ReplaceIfExists = FALSE;
2045 fli->RootDirectory = NULL;
2046 fli->FileNameLength = name_str.Length;
2047 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2048 pRtlFreeUnicodeString( &name_str );
2050 U(io).Status = 0xdeadbeef;
2051 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2052 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2053 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2054 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2055 ok( !fileDeleted, "file should exist\n" );
2056 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2057 ok( !fileDeleted, "file should exist\n" );
2059 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2060 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2061 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2062 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2063 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2064 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2065 HeapFree( GetProcessHeap(), 0, fni );
2067 CloseHandle( handle );
2068 HeapFree( GetProcessHeap(), 0, fli );
2069 delete_object( oldpath );
2070 delete_object( newpath );
2072 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2073 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2074 ok( res != 0, "failed to create temp file\n" );
2075 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2076 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2078 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2079 ok( res != 0, "failed to create temp file\n" );
2080 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2081 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2082 fli->ReplaceIfExists = FALSE;
2083 fli->RootDirectory = NULL;
2084 fli->FileNameLength = name_str.Length;
2085 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2086 pRtlFreeUnicodeString( &name_str );
2088 U(io).Status = 0xdeadbeef;
2089 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2090 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2091 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2092 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2093 ok( !fileDeleted, "file should exist\n" );
2094 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2095 ok( !fileDeleted, "file should exist\n" );
2097 CloseHandle( handle );
2098 HeapFree( GetProcessHeap(), 0, fli );
2099 delete_object( oldpath );
2100 delete_object( newpath );
2102 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2103 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2104 ok( res != 0, "failed to create temp file\n" );
2105 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2106 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2108 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2109 ok( res != 0, "failed to create temp file\n" );
2110 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2111 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2112 fli->ReplaceIfExists = TRUE;
2113 fli->RootDirectory = NULL;
2114 fli->FileNameLength = name_str.Length;
2115 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2116 pRtlFreeUnicodeString( &name_str );
2118 U(io).Status = 0xdeadbeef;
2119 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2120 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2121 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2122 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2123 ok( !fileDeleted, "file should exist\n" );
2124 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2125 ok( !fileDeleted, "file should exist\n" );
2127 CloseHandle( handle );
2128 HeapFree( GetProcessHeap(), 0, fli );
2129 delete_object( oldpath );
2130 delete_object( newpath );
2132 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2133 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2134 ok( res != 0, "failed to create temp file\n" );
2135 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2136 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2138 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2139 ok( res != 0, "failed to create temp file\n" );
2140 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2141 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2143 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2144 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2145 fli->ReplaceIfExists = FALSE;
2146 fli->RootDirectory = NULL;
2147 fli->FileNameLength = name_str.Length;
2148 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2149 pRtlFreeUnicodeString( &name_str );
2151 U(io).Status = 0xdeadbeef;
2152 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2153 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2154 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2155 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2156 ok( !fileDeleted, "file should exist\n" );
2157 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2158 ok( !fileDeleted, "file should exist\n" );
2160 CloseHandle( handle );
2161 CloseHandle( handle2 );
2162 HeapFree( GetProcessHeap(), 0, fli );
2163 delete_object( oldpath );
2164 delete_object( newpath );
2166 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2167 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2168 ok( res != 0, "failed to create temp file\n" );
2169 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2170 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2172 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2173 ok( res != 0, "failed to create temp file\n" );
2174 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2175 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2177 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2178 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2179 fli->ReplaceIfExists = TRUE;
2180 fli->RootDirectory = NULL;
2181 fli->FileNameLength = name_str.Length;
2182 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2183 pRtlFreeUnicodeString( &name_str );
2185 U(io).Status = 0xdeadbeef;
2186 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2187 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2188 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2189 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2190 ok( !fileDeleted, "file should exist\n" );
2191 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2192 ok( !fileDeleted, "file should exist\n" );
2194 CloseHandle( handle );
2195 CloseHandle( handle2 );
2196 HeapFree( GetProcessHeap(), 0, fli );
2197 delete_object( oldpath );
2198 delete_object( newpath );
2200 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2201 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2202 ok( res != 0, "failed to create temp file\n" );
2203 DeleteFileW( oldpath );
2204 success = CreateDirectoryW( oldpath, NULL );
2205 ok( success != 0, "failed to create temp directory\n" );
2206 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2207 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2209 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2210 ok( res != 0, "failed to create temp file\n" );
2211 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2212 DeleteFileW( newpath );
2213 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2214 fli->ReplaceIfExists = FALSE;
2215 fli->RootDirectory = NULL;
2216 fli->FileNameLength = name_str.Length;
2217 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2218 pRtlFreeUnicodeString( &name_str );
2220 U(io).Status = 0xdeadbeef;
2221 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2222 todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2223 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2224 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2225 ok( !fileDeleted, "file should exist\n" );
2226 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2227 ok( fileDeleted, "file should not exist\n" );
2229 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2230 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2231 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2232 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2233 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2234 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2235 HeapFree( GetProcessHeap(), 0, fni );
2237 CloseHandle( handle );
2238 HeapFree( GetProcessHeap(), 0, fli );
2239 delete_object( oldpath );
2240 delete_object( newpath );
2242 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2243 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2244 ok( res != 0, "failed to create temp file\n" );
2245 DeleteFileW( oldpath );
2246 success = CreateDirectoryW( oldpath, NULL );
2247 ok( success != 0, "failed to create temp directory\n" );
2248 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2249 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2251 lstrcpyW( newpath, oldpath );
2252 lstrcatW( newpath, foo_txtW );
2253 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2254 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2256 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2257 ok( res != 0, "failed to create temp file\n" );
2258 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2259 DeleteFileW( newpath );
2260 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2261 fli->ReplaceIfExists = FALSE;
2262 fli->RootDirectory = NULL;
2263 fli->FileNameLength = name_str.Length;
2264 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2265 pRtlFreeUnicodeString( &name_str );
2267 U(io).Status = 0xdeadbeef;
2268 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2269 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2270 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2271 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2272 ok( !fileDeleted, "file should exist\n" );
2273 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2274 ok( fileDeleted, "file should not exist\n" );
2276 CloseHandle( handle );
2277 CloseHandle( handle2 );
2278 HeapFree( GetProcessHeap(), 0, fli );
2279 delete_object( oldpath );
2280 delete_object( newpath );
2282 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2283 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2284 ok( res != 0, "failed to create temp file\n" );
2285 DeleteFileW( oldpath );
2286 success = CreateDirectoryW( oldpath, NULL );
2287 ok( success != 0, "failed to create temp directory\n" );
2288 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2289 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2291 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2292 ok( res != 0, "failed to create temp file\n" );
2293 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2294 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2295 fli->ReplaceIfExists = FALSE;
2296 fli->RootDirectory = NULL;
2297 fli->FileNameLength = name_str.Length;
2298 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2299 pRtlFreeUnicodeString( &name_str );
2301 U(io).Status = 0xdeadbeef;
2302 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2303 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2304 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2305 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2306 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2307 ok( !fileDeleted, "file should exist\n" );
2308 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2309 ok( !fileDeleted, "file should exist\n" );
2311 CloseHandle( handle );
2312 HeapFree( GetProcessHeap(), 0, fli );
2313 delete_object( oldpath );
2314 delete_object( newpath );
2316 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2317 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2318 ok( res != 0, "failed to create temp file\n" );
2319 DeleteFileW( oldpath );
2320 success = CreateDirectoryW( oldpath, NULL );
2321 ok( success != 0, "failed to create temp directory\n" );
2322 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2323 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2325 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2326 ok( res != 0, "failed to create temp file\n" );
2327 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2328 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2330 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2331 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2332 fli->ReplaceIfExists = FALSE;
2333 fli->RootDirectory = NULL;
2334 fli->FileNameLength = name_str.Length;
2335 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2336 pRtlFreeUnicodeString( &name_str );
2338 U(io).Status = 0xdeadbeef;
2339 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2340 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2341 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2342 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2343 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2344 ok( !fileDeleted, "file should exist\n" );
2345 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2346 ok( !fileDeleted, "file should exist\n" );
2348 CloseHandle( handle );
2349 CloseHandle( handle2 );
2350 HeapFree( GetProcessHeap(), 0, fli );
2351 delete_object( oldpath );
2352 delete_object( newpath );
2354 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2355 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2356 ok( res != 0, "failed to create temp file\n" );
2357 DeleteFileW( oldpath );
2358 success = CreateDirectoryW( oldpath, NULL );
2359 ok( success != 0, "failed to create temp directory\n" );
2360 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2361 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2363 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2364 ok( res != 0, "failed to create temp file\n" );
2365 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2366 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2367 fli->ReplaceIfExists = TRUE;
2368 fli->RootDirectory = NULL;
2369 fli->FileNameLength = name_str.Length;
2370 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2371 pRtlFreeUnicodeString( &name_str );
2373 U(io).Status = 0xdeadbeef;
2374 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2375 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2376 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2377 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2378 ok( !fileDeleted, "file should exist\n" );
2379 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2380 ok( !fileDeleted, "file should exist\n" );
2382 CloseHandle( handle );
2383 HeapFree( GetProcessHeap(), 0, fli );
2384 delete_object( oldpath );
2385 delete_object( newpath );
2387 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2388 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2389 ok( res != 0, "failed to create temp file\n" );
2390 DeleteFileW( oldpath );
2391 success = CreateDirectoryW( oldpath, NULL );
2392 ok( success != 0, "failed to create temp directory\n" );
2393 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2394 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2396 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2397 ok( res != 0, "failed to create temp file\n" );
2398 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2399 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2401 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2402 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2403 fli->ReplaceIfExists = TRUE;
2404 fli->RootDirectory = NULL;
2405 fli->FileNameLength = name_str.Length;
2406 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2407 pRtlFreeUnicodeString( &name_str );
2409 U(io).Status = 0xdeadbeef;
2410 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2411 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2412 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2413 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2414 ok( !fileDeleted, "file should exist\n" );
2415 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2416 ok( !fileDeleted, "file should exist\n" );
2418 CloseHandle( handle );
2419 CloseHandle( handle2 );
2420 HeapFree( GetProcessHeap(), 0, fli );
2421 delete_object( oldpath );
2422 delete_object( newpath );
2424 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2425 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2426 ok( res != 0, "failed to create temp file\n" );
2427 DeleteFileW( oldpath );
2428 success = CreateDirectoryW( oldpath, NULL );
2429 ok( success != 0, "failed to create temp directory\n" );
2430 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2431 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2433 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2434 ok( res != 0, "failed to create temp file\n" );
2435 DeleteFileW( newpath );
2436 success = CreateDirectoryW( newpath, NULL );
2437 ok( success != 0, "failed to create temp directory\n" );
2438 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2439 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2440 fli->ReplaceIfExists = FALSE;
2441 fli->RootDirectory = NULL;
2442 fli->FileNameLength = name_str.Length;
2443 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2444 pRtlFreeUnicodeString( &name_str );
2446 U(io).Status = 0xdeadbeef;
2447 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2448 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2449 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2450 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2451 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2452 ok( !fileDeleted, "file should exist\n" );
2453 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2454 ok( !fileDeleted, "file should exist\n" );
2456 CloseHandle( handle );
2457 HeapFree( GetProcessHeap(), 0, fli );
2458 delete_object( oldpath );
2459 delete_object( newpath );
2461 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2462 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2463 ok( res != 0, "failed to create temp file\n" );
2464 DeleteFileW( oldpath );
2465 success = CreateDirectoryW( oldpath, NULL );
2466 ok( success != 0, "failed to create temp directory\n" );
2467 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2468 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2470 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2471 ok( res != 0, "failed to create temp file\n" );
2472 DeleteFileW( newpath );
2473 success = CreateDirectoryW( newpath, NULL );
2474 ok( success != 0, "failed to create temp directory\n" );
2475 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2476 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2477 fli->ReplaceIfExists = TRUE;
2478 fli->RootDirectory = NULL;
2479 fli->FileNameLength = name_str.Length;
2480 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2481 pRtlFreeUnicodeString( &name_str );
2483 U(io).Status = 0xdeadbeef;
2484 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2485 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2486 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2487 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2488 ok( !fileDeleted, "file should exist\n" );
2489 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2490 ok( !fileDeleted, "file should exist\n" );
2492 CloseHandle( handle );
2493 HeapFree( GetProcessHeap(), 0, fli );
2494 delete_object( oldpath );
2495 delete_object( newpath );
2497 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2498 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2499 ok( res != 0, "failed to create temp file\n" );
2500 DeleteFileW( oldpath );
2501 success = CreateDirectoryW( oldpath, NULL );
2502 ok( success != 0, "failed to create temp directory\n" );
2503 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2504 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2506 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2507 ok( res != 0, "failed to create temp file\n" );
2508 DeleteFileW( newpath );
2509 success = CreateDirectoryW( newpath, NULL );
2510 ok( success != 0, "failed to create temp directory\n" );
2511 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2512 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2514 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2515 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2516 fli->ReplaceIfExists = TRUE;
2517 fli->RootDirectory = NULL;
2518 fli->FileNameLength = name_str.Length;
2519 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2520 pRtlFreeUnicodeString( &name_str );
2522 U(io).Status = 0xdeadbeef;
2523 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2524 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2525 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2526 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2527 ok( !fileDeleted, "file should exist\n" );
2528 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2529 ok( !fileDeleted, "file should exist\n" );
2531 CloseHandle( handle );
2532 CloseHandle( handle2 );
2533 HeapFree( GetProcessHeap(), 0, fli );
2534 delete_object( oldpath );
2535 delete_object( newpath );
2537 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2538 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2539 ok( res != 0, "failed to create temp file\n" );
2540 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2541 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2543 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2544 ok( res != 0, "failed to create temp file\n" );
2545 DeleteFileW( newpath );
2546 success = CreateDirectoryW( newpath, NULL );
2547 ok( success != 0, "failed to create temp directory\n" );
2548 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2549 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2550 fli->ReplaceIfExists = FALSE;
2551 fli->RootDirectory = NULL;
2552 fli->FileNameLength = name_str.Length;
2553 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2554 pRtlFreeUnicodeString( &name_str );
2556 U(io).Status = 0xdeadbeef;
2557 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2558 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2559 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2560 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2561 ok( !fileDeleted, "file should exist\n" );
2562 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2563 ok( !fileDeleted, "file should exist\n" );
2565 CloseHandle( handle );
2566 HeapFree( GetProcessHeap(), 0, fli );
2567 delete_object( oldpath );
2568 delete_object( newpath );
2570 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2571 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2572 ok( res != 0, "failed to create temp file\n" );
2573 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2574 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2576 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2577 ok( res != 0, "failed to create temp file\n" );
2578 DeleteFileW( newpath );
2579 success = CreateDirectoryW( newpath, NULL );
2580 ok( success != 0, "failed to create temp directory\n" );
2581 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2582 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2583 fli->ReplaceIfExists = TRUE;
2584 fli->RootDirectory = NULL;
2585 fli->FileNameLength = name_str.Length;
2586 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2587 pRtlFreeUnicodeString( &name_str );
2589 U(io).Status = 0xdeadbeef;
2590 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2591 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2592 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2593 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2594 ok( !fileDeleted, "file should exist\n" );
2595 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2596 ok( !fileDeleted, "file should exist\n" );
2598 CloseHandle( handle );
2599 HeapFree( GetProcessHeap(), 0, fli );
2600 delete_object( oldpath );
2601 delete_object( newpath );
2603 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2604 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2605 ok( res != 0, "failed to create temp file\n" );
2606 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2607 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2609 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2610 ok( res != 0, "failed to create temp file\n" );
2611 DeleteFileW( newpath );
2612 for (filename = newpath, p = newpath; *p; p++)
2613 if (*p == '\\') filename = p + 1;
2614 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2615 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2617 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2618 fli->ReplaceIfExists = FALSE;
2619 fli->RootDirectory = handle2;
2620 fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2621 memcpy( fli->FileName, filename, fli->FileNameLength );
2623 U(io).Status = 0xdeadbeef;
2624 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2625 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2626 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2627 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2628 ok( !fileDeleted, "file should exist\n" );
2629 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2630 ok( !fileDeleted, "file should exist\n" );
2632 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2633 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2634 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2635 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2636 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2637 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2638 HeapFree( GetProcessHeap(), 0, fni );
2640 CloseHandle( handle );
2641 CloseHandle( handle2 );
2642 HeapFree( GetProcessHeap(), 0, fli );
2643 delete_object( oldpath );
2644 delete_object( newpath );
2647 static void test_file_both_information(void)
2649 IO_STATUS_BLOCK io;
2650 FILE_BOTH_DIR_INFORMATION fbi;
2651 HANDLE h;
2652 int res;
2654 if (!(h = create_temp_file(0))) return;
2656 memset(&fbi, 0, sizeof(fbi));
2657 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
2658 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
2660 CloseHandle( h );
2663 static NTSTATUS nt_get_file_attrs(const char *name, DWORD *attrs)
2665 WCHAR nameW[MAX_PATH];
2666 FILE_BASIC_INFORMATION info;
2667 UNICODE_STRING nt_name;
2668 OBJECT_ATTRIBUTES attr;
2669 NTSTATUS status;
2671 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, MAX_PATH );
2673 *attrs = INVALID_FILE_ATTRIBUTES;
2675 if (!pRtlDosPathNameToNtPathName_U( nameW, &nt_name, NULL, NULL ))
2676 return STATUS_UNSUCCESSFUL;
2678 attr.Length = sizeof(attr);
2679 attr.RootDirectory = 0;
2680 attr.Attributes = OBJ_CASE_INSENSITIVE;
2681 attr.ObjectName = &nt_name;
2682 attr.SecurityDescriptor = NULL;
2683 attr.SecurityQualityOfService = NULL;
2685 status = pNtQueryAttributesFile( &attr, &info );
2686 pRtlFreeUnicodeString( &nt_name );
2688 if (status == STATUS_SUCCESS)
2689 *attrs = info.FileAttributes;
2691 return status;
2694 static void test_file_disposition_information(void)
2696 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
2697 DWORD dirpos;
2698 HANDLE handle, handle2, handle3;
2699 NTSTATUS res;
2700 IO_STATUS_BLOCK io;
2701 FILE_DISPOSITION_INFORMATION fdi;
2702 BOOL fileDeleted;
2703 DWORD fdi2;
2705 GetTempPathA( MAX_PATH, tmp_path );
2707 /* tests for info struct size */
2708 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2709 handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2710 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2711 res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
2712 todo_wine
2713 ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %x\n", res );
2714 fdi2 = 0x100;
2715 res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
2716 ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x\n", res );
2717 CloseHandle( handle );
2718 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2719 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2720 DeleteFileA( buffer );
2722 /* cannot set disposition on file not opened with delete access */
2723 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2724 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2725 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2726 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2727 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
2728 fdi.DoDeleteFile = TRUE;
2729 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2730 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
2731 CloseHandle( handle );
2732 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2733 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2734 DeleteFileA( buffer );
2736 /* can set disposition on file opened with proper access */
2737 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2738 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2739 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2740 fdi.DoDeleteFile = TRUE;
2741 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2742 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2743 CloseHandle( handle );
2744 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2745 ok( fileDeleted, "File should have been deleted\n" );
2747 /* file exists until all handles to it get closed */
2748 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2749 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
2750 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2751 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
2752 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
2753 fdi.DoDeleteFile = TRUE;
2754 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2755 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2756 res = nt_get_file_attrs( buffer, &fdi2 );
2757 todo_wine
2758 ok( res == STATUS_DELETE_PENDING, "got %#x\n", res );
2759 /* can't open the deleted file */
2760 handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
2761 todo_wine
2762 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2763 if (handle3 != INVALID_HANDLE_VALUE)
2764 CloseHandle( handle3 );
2765 todo_wine
2766 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %u\n", GetLastError());
2767 /* can't open the deleted file (wrong sharing mode) */
2768 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, 0, 0);
2769 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2770 todo_wine
2771 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %u\n", GetLastError());
2772 CloseHandle( handle );
2773 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2774 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2775 CloseHandle( handle2 );
2776 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2777 ok( fileDeleted, "File should have been deleted\n" );
2779 /* file exists until all handles to it get closed */
2780 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2781 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2782 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2783 /* can open the marked for delete file (proper sharing mode) */
2784 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
2785 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open temp file\n" );
2786 res = nt_get_file_attrs( buffer, &fdi2 );
2787 ok( res == STATUS_SUCCESS, "got %#x\n", res );
2788 /* can't open the marked for delete file (wrong sharing mode) */
2789 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, 0, 0);
2790 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2791 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %u\n", GetLastError());
2792 CloseHandle( handle );
2793 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2794 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2795 CloseHandle( handle2 );
2796 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2797 ok( fileDeleted, "File should have been deleted\n" );
2799 /* cannot set disposition on readonly file */
2800 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2801 DeleteFileA( buffer );
2802 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2803 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2804 fdi.DoDeleteFile = TRUE;
2805 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2806 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2807 CloseHandle( handle );
2808 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2809 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2810 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2811 DeleteFileA( buffer );
2813 /* cannot set disposition on readonly file */
2814 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2815 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2816 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2817 fdi.DoDeleteFile = TRUE;
2818 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2819 todo_wine
2820 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2821 CloseHandle( handle );
2822 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2823 todo_wine
2824 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2825 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2826 DeleteFileA( buffer );
2828 /* can set disposition on file and then reset it */
2829 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2830 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2831 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2832 fdi.DoDeleteFile = TRUE;
2833 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2834 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2835 fdi.DoDeleteFile = FALSE;
2836 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2837 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2838 CloseHandle( handle );
2839 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2840 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2841 DeleteFileA( buffer );
2843 /* can't reset disposition if delete-on-close flag is specified */
2844 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2845 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2846 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2847 fdi.DoDeleteFile = FALSE;
2848 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2849 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2850 CloseHandle( handle );
2851 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2852 ok( fileDeleted, "File should have been deleted\n" );
2854 /* can't reset disposition on duplicated handle if delete-on-close flag is specified */
2855 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2856 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2857 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2858 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
2859 CloseHandle( handle );
2860 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2861 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2862 fdi.DoDeleteFile = FALSE;
2863 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
2864 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2865 CloseHandle( handle2 );
2866 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2867 ok( fileDeleted, "File should have been deleted\n" );
2869 /* DeleteFile fails for wrong sharing mode */
2870 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2871 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2872 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2873 fileDeleted = DeleteFileA( buffer );
2874 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2875 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %u\n", GetLastError());
2876 CloseHandle( handle );
2877 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2878 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2879 DeleteFileA( buffer );
2881 /* DeleteFile succeeds for proper sharing mode */
2882 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2883 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0);
2884 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2885 fileDeleted = DeleteFileA( buffer );
2886 ok( fileDeleted, "File should have been deleted\n" );
2887 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2888 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2889 res = nt_get_file_attrs( buffer, &fdi2 );
2890 todo_wine
2891 ok( res == STATUS_DELETE_PENDING, "got %#x\n", res );
2892 /* can't open the deleted file */
2893 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0);
2894 ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2895 todo_wine
2896 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %u\n", GetLastError());
2897 CloseHandle( handle );
2898 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2899 ok( fileDeleted, "File should have been deleted\n" );
2901 /* can set disposition on a directory opened with proper access */
2902 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2903 DeleteFileA( buffer );
2904 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2905 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2906 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2907 fdi.DoDeleteFile = TRUE;
2908 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2909 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2910 CloseHandle( handle );
2911 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2912 ok( fileDeleted, "Directory should have been deleted\n" );
2914 /* RemoveDirectory fails for wrong sharing mode */
2915 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2916 DeleteFileA( buffer );
2917 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2918 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2919 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2920 fileDeleted = RemoveDirectoryA( buffer );
2921 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2922 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %u\n", GetLastError());
2923 CloseHandle( handle );
2924 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2925 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2926 RemoveDirectoryA( buffer );
2928 /* RemoveDirectory succeeds for proper sharing mode */
2929 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2930 DeleteFileA( buffer );
2931 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2932 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2933 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2934 fileDeleted = RemoveDirectoryA( buffer );
2935 ok( fileDeleted, "Directory should have been deleted\n" );
2936 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2937 todo_wine
2938 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2939 res = nt_get_file_attrs( buffer, &fdi2 );
2940 todo_wine
2941 ok( res == STATUS_DELETE_PENDING, "got %#x\n", res );
2942 /* can't open the deleted directory */
2943 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2944 ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2945 todo_wine
2946 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %u\n", GetLastError());
2947 CloseHandle( handle );
2948 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2949 ok( fileDeleted, "Directory should have been deleted\n" );
2951 /* directory exists until all handles to it get closed */
2952 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2953 DeleteFileA( buffer );
2954 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2955 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2956 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2957 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2958 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2959 fdi.DoDeleteFile = TRUE;
2960 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
2961 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2962 res = nt_get_file_attrs( buffer, &fdi2 );
2963 todo_wine
2964 ok( res == STATUS_DELETE_PENDING, "got %#x\n", res );
2965 /* can't open the deleted directory */
2966 handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2967 todo_wine
2968 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2969 if (handle3 != INVALID_HANDLE_VALUE)
2970 CloseHandle( handle3 );
2971 todo_wine
2972 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %u\n", GetLastError());
2973 /* can't open the deleted directory (wrong sharing mode) */
2974 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2975 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2976 todo_wine
2977 ok(GetLastError() == ERROR_ACCESS_DENIED, "got %u\n", GetLastError());
2978 CloseHandle( handle2 );
2979 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2980 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2981 CloseHandle( handle );
2982 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2983 ok( fileDeleted, "Directory should have been deleted\n" );
2985 /* directory exists until all handles to it get closed */
2986 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2987 DeleteFileA( buffer );
2988 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2989 handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
2990 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2991 /* can open the marked for delete directory (proper sharing mode) */
2992 handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2993 ok( handle2 != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2994 /* can't open the marked for delete file (wrong sharing mode) */
2995 handle3 = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2996 ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" );
2997 ok(GetLastError() == ERROR_SHARING_VIOLATION, "got %u\n", GetLastError());
2998 CloseHandle( handle );
2999 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3000 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3001 CloseHandle( handle2 );
3002 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3003 ok( fileDeleted, "Directory should have been deleted\n" );
3005 /* can open a non-empty directory with FILE_FLAG_DELETE_ON_CLOSE */
3006 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3007 DeleteFileA( buffer );
3008 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3009 dirpos = lstrlenA( buffer );
3010 lstrcpyA( buffer + dirpos, "\\tst" );
3011 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3012 CloseHandle( handle2 );
3013 buffer[dirpos] = '\0';
3014 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
3015 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3016 SetLastError(0xdeadbeef);
3017 CloseHandle( handle );
3018 ok(GetLastError() == 0xdeadbeef, "got %u\n", GetLastError());
3019 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3020 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3021 buffer[dirpos] = '\\';
3022 fileDeleted = DeleteFileA( buffer );
3023 ok( fileDeleted, "File should have been deleted\n" );
3024 buffer[dirpos] = '\0';
3025 fileDeleted = RemoveDirectoryA( buffer );
3026 ok( fileDeleted, "Directory should have been deleted\n" );
3028 /* cannot set disposition on a non-empty directory */
3029 GetTempFileNameA( tmp_path, "dis", 0, buffer );
3030 DeleteFileA( buffer );
3031 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
3032 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
3033 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
3034 dirpos = lstrlenA( buffer );
3035 lstrcpyA( buffer + dirpos, "\\tst" );
3036 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3037 CloseHandle( handle2 );
3038 fdi.DoDeleteFile = TRUE;
3039 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
3040 todo_wine
3041 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
3042 fileDeleted = DeleteFileA( buffer );
3043 ok( fileDeleted, "File should have been deleted\n" );
3044 buffer[dirpos] = '\0';
3045 CloseHandle( handle );
3046 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
3047 todo_wine
3048 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
3049 fileDeleted = RemoveDirectoryA( buffer );
3050 todo_wine
3051 ok( fileDeleted, "Directory should have been deleted\n" );
3054 static void test_file_name_information(void)
3056 WCHAR *file_name, *volume_prefix, *expected;
3057 FILE_NAME_INFORMATION *info;
3058 ULONG old_redir = 1, tmp;
3059 UINT file_name_size;
3060 IO_STATUS_BLOCK io;
3061 UINT info_size;
3062 HRESULT hr;
3063 HANDLE h;
3064 UINT len;
3066 /* GetVolumePathName is not present before w2k */
3067 if (!pGetVolumePathNameW) {
3068 win_skip("GetVolumePathNameW not found\n");
3069 return;
3072 file_name_size = GetSystemDirectoryW( NULL, 0 );
3073 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3074 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3075 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3077 len = GetSystemDirectoryW( file_name, file_name_size );
3078 ok(len == file_name_size - 1,
3079 "GetSystemDirectoryW returned %u, expected %u.\n",
3080 len, file_name_size - 1);
3082 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3083 ok(len, "GetVolumePathNameW failed.\n");
3085 len = lstrlenW( volume_prefix );
3086 if (len && volume_prefix[len - 1] == '\\') --len;
3087 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3088 expected[file_name_size - len - 1] = '\0';
3090 /* A bit more than we actually need, but it keeps the calculation simple. */
3091 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3092 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3094 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3095 h = CreateFileW( file_name, GENERIC_READ,
3096 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3097 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3098 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3099 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3101 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
3102 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
3104 memset( info, 0xcc, info_size );
3105 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
3106 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3107 hr, STATUS_BUFFER_OVERFLOW);
3108 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3109 U(io).Status, STATUS_BUFFER_OVERFLOW);
3110 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
3111 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
3112 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3113 "info->FileName[1] is %p, expected %p.\n",
3114 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3115 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3117 memset( info, 0xcc, info_size );
3118 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3119 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3120 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3121 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
3122 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
3123 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
3124 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3125 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3126 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3127 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
3128 "io.Information is %lu, expected %u.\n",
3129 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
3131 CloseHandle( h );
3132 HeapFree( GetProcessHeap(), 0, info );
3133 HeapFree( GetProcessHeap(), 0, expected );
3134 HeapFree( GetProcessHeap(), 0, volume_prefix );
3136 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3138 skip("Not running on WoW64, skipping test.\n");
3139 HeapFree( GetProcessHeap(), 0, file_name );
3140 return;
3143 h = CreateFileW( file_name, GENERIC_READ,
3144 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3145 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3146 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3147 HeapFree( GetProcessHeap(), 0, file_name );
3149 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3150 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3151 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3153 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3154 ok(len == file_name_size - 1,
3155 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3156 len, file_name_size - 1);
3158 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3159 ok(len, "GetVolumePathNameW failed.\n");
3161 len = lstrlenW( volume_prefix );
3162 if (len && volume_prefix[len - 1] == '\\') --len;
3163 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3164 expected[file_name_size - len - 1] = '\0';
3166 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3167 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3169 memset( info, 0xcc, info_size );
3170 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3171 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3172 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3173 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3174 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3176 CloseHandle( h );
3177 HeapFree( GetProcessHeap(), 0, info );
3178 HeapFree( GetProcessHeap(), 0, expected );
3179 HeapFree( GetProcessHeap(), 0, volume_prefix );
3180 HeapFree( GetProcessHeap(), 0, file_name );
3183 static void test_file_all_name_information(void)
3185 WCHAR *file_name, *volume_prefix, *expected;
3186 FILE_ALL_INFORMATION *info;
3187 ULONG old_redir = 1, tmp;
3188 UINT file_name_size;
3189 IO_STATUS_BLOCK io;
3190 UINT info_size;
3191 HRESULT hr;
3192 HANDLE h;
3193 UINT len;
3195 /* GetVolumePathName is not present before w2k */
3196 if (!pGetVolumePathNameW) {
3197 win_skip("GetVolumePathNameW not found\n");
3198 return;
3201 file_name_size = GetSystemDirectoryW( NULL, 0 );
3202 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3203 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3204 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3206 len = GetSystemDirectoryW( file_name, file_name_size );
3207 ok(len == file_name_size - 1,
3208 "GetSystemDirectoryW returned %u, expected %u.\n",
3209 len, file_name_size - 1);
3211 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3212 ok(len, "GetVolumePathNameW failed.\n");
3214 len = lstrlenW( volume_prefix );
3215 if (len && volume_prefix[len - 1] == '\\') --len;
3216 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3217 expected[file_name_size - len - 1] = '\0';
3219 /* A bit more than we actually need, but it keeps the calculation simple. */
3220 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3221 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3223 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3224 h = CreateFileW( file_name, GENERIC_READ,
3225 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3226 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3227 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3228 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3230 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
3231 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
3232 hr, STATUS_INFO_LENGTH_MISMATCH);
3234 memset( info, 0xcc, info_size );
3235 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
3236 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3237 hr, STATUS_BUFFER_OVERFLOW);
3238 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3239 U(io).Status, STATUS_BUFFER_OVERFLOW);
3240 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3241 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3242 ok(info->NameInformation.FileName[2] == 0xcccc,
3243 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
3244 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3245 "info->NameInformation.FileName[1] is %p, expected %p.\n",
3246 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3247 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3249 memset( info, 0xcc, info_size );
3250 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3251 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3252 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3253 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3254 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3255 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
3256 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3257 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
3258 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3259 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
3260 "info->NameInformation.FileName is %s, expected %s.\n",
3261 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3262 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
3263 + info->NameInformation.FileNameLength,
3264 "io.Information is %lu\n", io.Information );
3266 CloseHandle( h );
3267 HeapFree( GetProcessHeap(), 0, info );
3268 HeapFree( GetProcessHeap(), 0, expected );
3269 HeapFree( GetProcessHeap(), 0, volume_prefix );
3271 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3273 skip("Not running on WoW64, skipping test.\n");
3274 HeapFree( GetProcessHeap(), 0, file_name );
3275 return;
3278 h = CreateFileW( file_name, GENERIC_READ,
3279 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3280 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3281 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3282 HeapFree( GetProcessHeap(), 0, file_name );
3284 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3285 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3286 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3288 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3289 ok(len == file_name_size - 1,
3290 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3291 len, file_name_size - 1);
3293 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3294 ok(len, "GetVolumePathNameW failed.\n");
3296 len = lstrlenW( volume_prefix );
3297 if (len && volume_prefix[len - 1] == '\\') --len;
3298 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3299 expected[file_name_size - len - 1] = '\0';
3301 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3302 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3304 memset( info, 0xcc, info_size );
3305 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3306 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3307 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3308 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
3309 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3311 CloseHandle( h );
3312 HeapFree( GetProcessHeap(), 0, info );
3313 HeapFree( GetProcessHeap(), 0, expected );
3314 HeapFree( GetProcessHeap(), 0, volume_prefix );
3315 HeapFree( GetProcessHeap(), 0, file_name );
3318 static void test_file_completion_information(void)
3320 static const char buf[] = "testdata";
3321 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
3322 OVERLAPPED ov, *pov;
3323 IO_STATUS_BLOCK io;
3324 NTSTATUS status;
3325 DWORD num_bytes;
3326 HANDLE port, h;
3327 ULONG_PTR key;
3328 BOOL ret;
3329 int i;
3331 if (!(h = create_temp_file(0))) return;
3333 status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
3334 todo_wine
3335 ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_INVALID_INFO_CLASS /* XP */,
3336 "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
3337 if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED)
3339 skip("FileIoCompletionNotificationInformation class not supported\n");
3340 CloseHandle(h);
3341 return;
3344 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3345 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3346 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %08x\n", status);
3348 CloseHandle(h);
3349 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3351 info.Flags = FILE_SKIP_SET_EVENT_ON_HANDLE;
3352 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3353 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3355 info.Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO;
3356 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3357 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3359 CloseHandle(h);
3360 if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3362 memset(&ov, 0, sizeof(ov));
3363 ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
3364 port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
3365 ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError());
3367 for (i = 0; i < 10; i++)
3369 SetLastError(0xdeadbeef);
3370 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3371 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3372 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3373 ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3374 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3375 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3376 ret = FALSE;
3378 if (ret)
3380 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3382 key = 0;
3383 pov = NULL;
3384 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3385 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3386 ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key);
3387 ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
3389 else
3390 win_skip("WriteFile never returned TRUE\n");
3392 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3393 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3394 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3396 for (i = 0; i < 10; i++)
3398 SetLastError(0xdeadbeef);
3399 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3400 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3401 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3402 ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3403 ret = FALSE;
3405 if (ret)
3407 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3409 pov = (void *)0xdeadbeef;
3410 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
3411 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3412 ok(pov == NULL, "expected NULL, got %p\n", pov);
3414 else
3415 win_skip("WriteFile never returned TRUE\n");
3417 info.Flags = 0;
3418 status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3419 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3421 for (i = 0; i < 10; i++)
3423 SetLastError(0xdeadbeef);
3424 ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3425 if (ret || GetLastError() != ERROR_IO_PENDING) break;
3426 ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3427 ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3428 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3429 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3430 ret = FALSE;
3432 if (ret)
3434 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3436 pov = (void *)0xdeadbeef;
3437 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3438 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3439 ok(pov == NULL, "expected NULL, got %p\n", pov);
3441 else
3442 win_skip("WriteFile never returned TRUE\n");
3444 CloseHandle(ov.hEvent);
3445 CloseHandle(port);
3446 CloseHandle(h);
3449 static void test_file_id_information(void)
3451 BY_HANDLE_FILE_INFORMATION info;
3452 FILE_ID_INFORMATION fid;
3453 IO_STATUS_BLOCK io;
3454 NTSTATUS status;
3455 DWORD *dwords;
3456 HANDLE h;
3457 BOOL ret;
3459 if (!(h = create_temp_file(0))) return;
3461 memset( &fid, 0x11, sizeof(fid) );
3462 status = pNtQueryInformationFile( h, &io, &fid, sizeof(fid), FileIdInformation );
3463 if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
3465 win_skip( "FileIdInformation not supported\n" );
3466 CloseHandle( h );
3467 return;
3470 memset( &info, 0x22, sizeof(info) );
3471 ret = GetFileInformationByHandle( h, &info );
3472 ok( ret, "GetFileInformationByHandle failed\n" );
3474 dwords = (DWORD *)&fid.VolumeSerialNumber;
3475 ok( dwords[0] == info.dwVolumeSerialNumber, "expected %08x, got %08x\n",
3476 info.dwVolumeSerialNumber, dwords[0] );
3477 ok( dwords[1] != 0x11111111, "expected != 0x11111111\n" );
3479 dwords = (DWORD *)&fid.FileId;
3480 ok( dwords[0] == info.nFileIndexLow, "expected %08x, got %08x\n", info.nFileIndexLow, dwords[0] );
3481 ok( dwords[1] == info.nFileIndexHigh, "expected %08x, got %08x\n", info.nFileIndexHigh, dwords[1] );
3482 ok( dwords[2] == 0, "expected 0, got %08x\n", dwords[2] );
3483 ok( dwords[3] == 0, "expected 0, got %08x\n", dwords[3] );
3485 CloseHandle( h );
3488 static void test_file_access_information(void)
3490 FILE_ACCESS_INFORMATION info;
3491 IO_STATUS_BLOCK io;
3492 NTSTATUS status;
3493 HANDLE h;
3495 if (!(h = create_temp_file(0))) return;
3497 status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation );
3498 ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
3500 status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation );
3501 ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status );
3503 memset(&info, 0x11, sizeof(info));
3504 status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation );
3505 ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status );
3506 ok( info.AccessFlags == 0x13019f, "got %08x\n", info.AccessFlags );
3508 CloseHandle( h );
3511 static void test_query_volume_information_file(void)
3513 NTSTATUS status;
3514 HANDLE dir;
3515 WCHAR path[MAX_PATH];
3516 OBJECT_ATTRIBUTES attr;
3517 IO_STATUS_BLOCK io;
3518 UNICODE_STRING nameW;
3519 FILE_FS_VOLUME_INFORMATION *ffvi;
3520 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3522 GetWindowsDirectoryW( path, MAX_PATH );
3523 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3524 attr.Length = sizeof(attr);
3525 attr.RootDirectory = 0;
3526 attr.ObjectName = &nameW;
3527 attr.Attributes = OBJ_CASE_INSENSITIVE;
3528 attr.SecurityDescriptor = NULL;
3529 attr.SecurityQualityOfService = NULL;
3531 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3532 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3533 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3534 pRtlFreeUnicodeString( &nameW );
3536 ZeroMemory( buf, sizeof(buf) );
3537 U(io).Status = 0xdadadada;
3538 io.Information = 0xcacacaca;
3540 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
3542 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
3544 todo_wine
3546 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3547 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3549 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3550 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3551 io.Information);
3553 ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
3554 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
3555 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
3557 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
3559 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
3561 CloseHandle( dir );
3564 static void test_query_attribute_information_file(void)
3566 NTSTATUS status;
3567 HANDLE dir;
3568 WCHAR path[MAX_PATH];
3569 OBJECT_ATTRIBUTES attr;
3570 IO_STATUS_BLOCK io;
3571 UNICODE_STRING nameW;
3572 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
3573 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3575 GetWindowsDirectoryW( path, MAX_PATH );
3576 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3577 attr.Length = sizeof(attr);
3578 attr.RootDirectory = 0;
3579 attr.ObjectName = &nameW;
3580 attr.Attributes = OBJ_CASE_INSENSITIVE;
3581 attr.SecurityDescriptor = NULL;
3582 attr.SecurityQualityOfService = NULL;
3584 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3585 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3586 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3587 pRtlFreeUnicodeString( &nameW );
3589 ZeroMemory( buf, sizeof(buf) );
3590 U(io).Status = 0xdadadada;
3591 io.Information = 0xcacacaca;
3593 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
3595 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
3597 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3598 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3599 ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
3600 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
3601 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
3603 trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
3604 ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
3605 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
3607 CloseHandle( dir );
3610 static void test_NtCreateFile(void)
3612 static const struct test_data
3614 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
3615 } td[] =
3617 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3618 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
3619 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3620 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3621 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3622 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3623 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3624 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3625 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3626 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3627 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3628 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3629 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3630 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3631 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3632 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3633 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3634 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
3635 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
3637 static const WCHAR fooW[] = {'f','o','o',0};
3638 NTSTATUS status;
3639 HANDLE handle;
3640 WCHAR path[MAX_PATH];
3641 OBJECT_ATTRIBUTES attr;
3642 IO_STATUS_BLOCK io;
3643 UNICODE_STRING nameW;
3644 DWORD ret, i;
3646 GetTempPathW(MAX_PATH, path);
3647 GetTempFileNameW(path, fooW, 0, path);
3648 DeleteFileW(path);
3649 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
3651 attr.Length = sizeof(attr);
3652 attr.RootDirectory = NULL;
3653 attr.ObjectName = &nameW;
3654 attr.Attributes = OBJ_CASE_INSENSITIVE;
3655 attr.SecurityDescriptor = NULL;
3656 attr.SecurityQualityOfService = NULL;
3658 for (i = 0; i < ARRAY_SIZE(td); i++)
3660 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
3661 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
3662 td[i].disposition, 0, NULL, 0);
3664 ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
3666 if (!status)
3668 ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
3670 ret = GetFileAttributesW(path);
3671 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
3672 /* FIXME: leave only 'else' case below once Wine is fixed */
3673 if (ret != td[i].attrib_out)
3675 todo_wine
3676 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3677 SetFileAttributesW(path, td[i].attrib_out);
3679 else
3680 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3682 CloseHandle(handle);
3685 if (td[i].needs_cleanup)
3687 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3688 DeleteFileW(path);
3692 pRtlFreeUnicodeString( &nameW );
3693 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3694 DeleteFileW( path );
3697 static void test_read_write(void)
3699 static const char contents[14] = "1234567890abcd";
3700 char buf[256];
3701 HANDLE hfile, event;
3702 OVERLAPPED ovl;
3703 IO_STATUS_BLOCK iob;
3704 DWORD ret, bytes, status, off;
3705 LARGE_INTEGER offset;
3706 LONG i;
3708 event = CreateEventA( NULL, TRUE, FALSE, NULL );
3710 U(iob).Status = -1;
3711 iob.Information = -1;
3712 offset.QuadPart = 0;
3713 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3714 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3715 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3716 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3718 U(iob).Status = -1;
3719 iob.Information = -1;
3720 offset.QuadPart = 0;
3721 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, NULL, sizeof(buf), &offset, NULL);
3722 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3723 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3724 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3726 U(iob).Status = -1;
3727 iob.Information = -1;
3728 offset.QuadPart = 0;
3729 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3730 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3731 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3732 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3734 U(iob).Status = -1;
3735 iob.Information = -1;
3736 offset.QuadPart = 0;
3737 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3738 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3739 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3740 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3742 hfile = create_temp_file(0);
3743 if (!hfile) return;
3745 U(iob).Status = -1;
3746 iob.Information = -1;
3747 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3748 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3749 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3750 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3752 U(iob).Status = -1;
3753 iob.Information = -1;
3754 SetEvent(event);
3755 status = pNtWriteFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3756 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3757 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3758 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3759 ok(!is_signaled(event), "event is not signaled\n");
3761 U(iob).Status = -1;
3762 iob.Information = -1;
3763 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3764 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3765 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3766 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3768 U(iob).Status = -1;
3769 iob.Information = -1;
3770 SetEvent(event);
3771 status = pNtReadFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3772 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3773 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3774 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3775 ok(is_signaled(event), "event is not signaled\n");
3777 U(iob).Status = -1;
3778 iob.Information = -1;
3779 SetEvent(event);
3780 status = pNtReadFile(hfile, event, NULL, NULL, &iob, (void*)0xdeadbeef, sizeof(contents), NULL, NULL);
3781 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3782 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3783 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3784 ok(is_signaled(event), "event is not signaled\n");
3786 U(iob).Status = -1;
3787 iob.Information = -1;
3788 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
3789 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3790 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3791 ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
3793 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3795 U(iob).Status = -1;
3796 iob.Information = -1;
3797 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
3798 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
3799 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3800 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3801 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
3803 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3804 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3806 bytes = 0xdeadbeef;
3807 SetLastError(0xdeadbeef);
3808 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
3809 ok(!ret, "ReadFile should fail\n");
3810 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3811 ok(bytes == 0, "bytes %u\n", bytes);
3813 bytes = 0xdeadbeef;
3814 SetLastError(0xdeadbeef);
3815 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3816 ok(ret, "ReadFile error %d\n", GetLastError());
3817 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3818 ok(bytes == 0, "bytes %u\n", bytes);
3820 bytes = 0xdeadbeef;
3821 SetLastError(0xdeadbeef);
3822 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3823 ok(ret, "ReadFile error %d\n", GetLastError());
3824 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3825 ok(bytes == 0, "bytes %u\n", bytes);
3827 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3829 bytes = 0;
3830 SetLastError(0xdeadbeef);
3831 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3832 ok(ret, "ReadFile error %d\n", GetLastError());
3833 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3834 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3836 for (i = -20; i < -1; i++)
3838 if (i == -2) continue;
3840 U(iob).Status = -1;
3841 iob.Information = -1;
3842 offset.QuadPart = (LONGLONG)i;
3843 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3844 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3845 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3846 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3849 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
3851 U(iob).Status = -1;
3852 iob.Information = -1;
3853 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3854 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3855 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3856 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3857 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3859 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3860 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3862 U(iob).Status = -1;
3863 iob.Information = -1;
3864 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3865 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3866 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3867 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3869 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3871 bytes = 0;
3872 SetLastError(0xdeadbeef);
3873 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3874 ok(ret, "ReadFile error %d\n", GetLastError());
3875 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3876 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3877 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3879 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3880 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3882 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3884 bytes = 0;
3885 SetLastError(0xdeadbeef);
3886 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
3887 ok(ret, "WriteFile error %d\n", GetLastError());
3888 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3890 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3891 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3893 /* test reading beyond EOF */
3894 bytes = -1;
3895 SetLastError(0xdeadbeef);
3896 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3897 ok(ret, "ReadFile error %d\n", GetLastError());
3898 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3899 ok(bytes == 0, "bytes %u\n", bytes);
3901 bytes = -1;
3902 SetLastError(0xdeadbeef);
3903 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3904 ok(ret, "ReadFile error %d\n", GetLastError());
3905 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3906 ok(bytes == 0, "bytes %u\n", bytes);
3908 bytes = -1;
3909 SetLastError(0xdeadbeef);
3910 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
3911 ok(ret, "ReadFile error %d\n", GetLastError());
3912 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3913 ok(bytes == 0, "bytes %u\n", bytes);
3915 S(U(ovl)).Offset = sizeof(contents);
3916 S(U(ovl)).OffsetHigh = 0;
3917 ovl.Internal = -1;
3918 ovl.InternalHigh = -1;
3919 ovl.hEvent = 0;
3920 bytes = -1;
3921 SetLastError(0xdeadbeef);
3922 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3923 ok(!ret, "ReadFile should fail\n");
3924 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
3925 ok(bytes == 0, "bytes %u\n", bytes);
3926 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
3927 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3929 S(U(ovl)).Offset = sizeof(contents);
3930 S(U(ovl)).OffsetHigh = 0;
3931 ovl.Internal = -1;
3932 ovl.InternalHigh = -1;
3933 ovl.hEvent = 0;
3934 bytes = -1;
3935 SetLastError(0xdeadbeef);
3936 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
3937 ok(ret, "ReadFile error %d\n", GetLastError());
3938 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3939 ok(bytes == 0, "bytes %u\n", bytes);
3940 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3941 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3943 U(iob).Status = -1;
3944 iob.Information = -1;
3945 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3946 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3947 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3948 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3950 U(iob).Status = -1;
3951 iob.Information = -1;
3952 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
3953 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3954 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3955 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3957 U(iob).Status = -1;
3958 iob.Information = -1;
3959 offset.QuadPart = sizeof(contents);
3960 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3961 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3962 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3963 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3965 U(iob).Status = -1;
3966 iob.Information = -1;
3967 offset.QuadPart = sizeof(contents);
3968 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3969 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3970 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3971 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3973 U(iob).Status = -1;
3974 iob.Information = -1;
3975 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3976 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3977 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3978 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3979 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3981 U(iob).Status = -1;
3982 iob.Information = -1;
3983 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3984 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3985 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3986 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3987 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3989 for (i = -20; i < 0; i++)
3991 if (i == -2) continue;
3993 U(iob).Status = -1;
3994 iob.Information = -1;
3995 offset.QuadPart = (LONGLONG)i;
3996 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3997 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3998 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3999 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4002 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4004 bytes = 0;
4005 SetLastError(0xdeadbeef);
4006 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4007 ok(ret, "ReadFile error %d\n", GetLastError());
4008 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4009 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4011 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4012 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4014 U(iob).Status = -1;
4015 iob.Information = -1;
4016 offset.QuadPart = 0;
4017 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4018 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
4019 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4020 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4021 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4023 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4024 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4026 U(iob).Status = -1;
4027 iob.Information = -1;
4028 offset.QuadPart = sizeof(contents) - 4;
4029 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4030 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
4031 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4032 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
4034 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4035 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4037 U(iob).Status = -1;
4038 iob.Information = -1;
4039 offset.QuadPart = 0;
4040 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4041 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
4042 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4043 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4044 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4045 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4047 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4048 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4050 S(U(ovl)).Offset = sizeof(contents) - 4;
4051 S(U(ovl)).OffsetHigh = 0;
4052 ovl.hEvent = 0;
4053 bytes = 0;
4054 SetLastError(0xdeadbeef);
4055 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4056 ok(ret, "WriteFile error %d\n", GetLastError());
4057 ok(bytes == 4, "bytes %u\n", bytes);
4059 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4060 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4062 S(U(ovl)).Offset = 0;
4063 S(U(ovl)).OffsetHigh = 0;
4064 ovl.Internal = -1;
4065 ovl.InternalHigh = -1;
4066 ovl.hEvent = 0;
4067 bytes = 0;
4068 SetLastError(0xdeadbeef);
4069 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4070 ok(ret, "ReadFile error %d\n", GetLastError());
4071 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4072 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4073 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4074 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4075 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4077 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4078 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4080 CloseHandle(hfile);
4082 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
4083 if (!hfile) return;
4085 bytes = 0xdeadbeef;
4086 SetLastError(0xdeadbeef);
4087 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
4088 ok(!ret, "ReadFile should fail\n");
4089 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
4090 ok(bytes == 0, "bytes %u\n", bytes);
4092 S(U(ovl)).Offset = 0;
4093 S(U(ovl)).OffsetHigh = 0;
4094 ovl.Internal = -1;
4095 ovl.InternalHigh = -1;
4096 ovl.hEvent = 0;
4097 bytes = 0xdeadbeef;
4098 SetLastError(0xdeadbeef);
4099 /* ReadFile return value depends on Windows version and testing it is not practical */
4100 ReadFile(hfile, buf, 0, &bytes, &ovl);
4101 ok(bytes == 0, "bytes %u\n", bytes);
4102 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4103 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4105 bytes = 0xdeadbeef;
4106 SetLastError(0xdeadbeef);
4107 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
4108 ok(!ret, "WriteFile should fail\n");
4109 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4110 ok(bytes == 0, "bytes %u\n", bytes);
4112 U(iob).Status = -1;
4113 iob.Information = -1;
4114 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
4115 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
4116 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4117 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4119 for (i = -20; i < -1; i++)
4121 U(iob).Status = -1;
4122 iob.Information = -1;
4123 offset.QuadPart = (LONGLONG)i;
4124 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4125 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
4126 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4127 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4130 U(iob).Status = -1;
4131 iob.Information = -1;
4132 offset.QuadPart = 0;
4133 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4134 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4135 if (status == STATUS_PENDING)
4137 ret = WaitForSingleObject(hfile, 3000);
4138 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4140 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4141 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4143 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4144 ok(off == 0, "expected 0, got %u\n", off);
4146 bytes = 0xdeadbeef;
4147 SetLastError(0xdeadbeef);
4148 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4149 ok(!ret, "ReadFile should fail\n");
4150 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4151 ok(bytes == 0, "bytes %u\n", bytes);
4153 U(iob).Status = -1;
4154 iob.Information = -1;
4155 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
4156 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
4157 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4158 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4160 for (i = -20; i < 0; i++)
4162 U(iob).Status = -1;
4163 iob.Information = -1;
4164 offset.QuadPart = (LONGLONG)i;
4165 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4166 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
4167 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4168 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4171 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4172 ok(off == 0, "expected 0, got %u\n", off);
4174 /* test reading beyond EOF */
4175 offset.QuadPart = sizeof(contents);
4176 S(U(ovl)).Offset = offset.u.LowPart;
4177 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4178 ovl.Internal = -1;
4179 ovl.InternalHigh = -1;
4180 ovl.hEvent = 0;
4181 bytes = 0xdeadbeef;
4182 SetLastError(0xdeadbeef);
4183 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4184 ok(!ret, "ReadFile should fail\n");
4185 ret = GetLastError();
4186 ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
4187 ok(bytes == 0, "bytes %u\n", bytes);
4189 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4190 ok(off == 0, "expected 0, got %u\n", off);
4192 if (ret == ERROR_IO_PENDING)
4194 bytes = 0xdeadbeef;
4195 SetLastError(0xdeadbeef);
4196 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4197 ok(!ret, "GetOverlappedResult should report FALSE\n");
4198 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
4199 ok(bytes == 0, "expected 0, read %u\n", bytes);
4200 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
4201 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4204 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4205 ok(off == 0, "expected 0, got %u\n", off);
4207 offset.QuadPart = sizeof(contents);
4208 S(U(ovl)).Offset = offset.u.LowPart;
4209 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4210 ovl.Internal = -1;
4211 ovl.InternalHigh = -1;
4212 ovl.hEvent = 0;
4213 bytes = 0xdeadbeef;
4214 SetLastError(0xdeadbeef);
4215 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
4216 /* ReadFile return value depends on Windows version and testing it is not practical */
4217 if (!ret)
4218 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4219 ret = GetLastError();
4220 ok(bytes == 0, "bytes %u\n", bytes);
4222 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4223 ok(off == 0, "expected 0, got %u\n", off);
4225 if (ret == ERROR_IO_PENDING)
4227 bytes = 0xdeadbeef;
4228 SetLastError(0xdeadbeef);
4229 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4230 ok(ret, "GetOverlappedResult should report TRUE\n");
4231 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4232 ok(bytes == 0, "expected 0, read %u\n", bytes);
4233 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4234 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4237 offset.QuadPart = sizeof(contents);
4238 S(U(ovl)).Offset = offset.u.LowPart;
4239 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4240 ovl.Internal = -1;
4241 ovl.InternalHigh = -1;
4242 ovl.hEvent = 0;
4243 bytes = 0xdeadbeef;
4244 SetLastError(0xdeadbeef);
4245 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
4246 /* ReadFile return value depends on Windows version and testing it is not practical */
4247 if (!ret)
4248 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4249 ret = GetLastError();
4250 ok(bytes == 0, "bytes %u\n", bytes);
4252 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4253 ok(off == 0, "expected 0, got %u\n", off);
4255 if (ret == ERROR_IO_PENDING)
4257 bytes = 0xdeadbeef;
4258 SetLastError(0xdeadbeef);
4259 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4260 ok(ret, "GetOverlappedResult should report TRUE\n");
4261 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4262 ok(bytes == 0, "expected 0, read %u\n", bytes);
4263 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4264 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4267 U(iob).Status = -1;
4268 iob.Information = -1;
4269 offset.QuadPart = sizeof(contents);
4270 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4271 if (status == STATUS_PENDING)
4273 ret = WaitForSingleObject(hfile, 3000);
4274 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4275 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
4276 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4278 else
4280 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
4281 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4282 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
4285 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4286 ok(off == 0, "expected 0, got %u\n", off);
4288 U(iob).Status = -1;
4289 iob.Information = -1;
4290 offset.QuadPart = sizeof(contents);
4291 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4292 if (status == STATUS_PENDING)
4294 ret = WaitForSingleObject(hfile, 3000);
4295 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4296 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4297 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4299 else
4301 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
4302 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4303 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4306 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4307 ok(off == 0, "expected 0, got %u\n", off);
4309 S(U(ovl)).Offset = 0;
4310 S(U(ovl)).OffsetHigh = 0;
4311 ovl.Internal = -1;
4312 ovl.InternalHigh = -1;
4313 ovl.hEvent = 0;
4314 bytes = 0;
4315 SetLastError(0xdeadbeef);
4316 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4317 /* ReadFile return value depends on Windows version and testing it is not practical */
4318 if (!ret)
4320 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4321 ok(bytes == 0, "bytes %u\n", bytes);
4323 else ok(bytes == 14, "bytes %u\n", bytes);
4324 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4325 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4327 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4328 ok(off == 0, "expected 0, got %u\n", off);
4330 bytes = 0xdeadbeef;
4331 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4332 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4333 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4334 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4335 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4336 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4338 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4339 ok(off == 0, "expected 0, got %u\n", off);
4341 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4342 SetEndOfFile(hfile);
4343 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4345 U(iob).Status = -1;
4346 iob.Information = -1;
4347 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4348 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4349 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4350 if (status == STATUS_PENDING)
4352 ret = WaitForSingleObject(hfile, 3000);
4353 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4355 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4356 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
4358 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4359 ok(off == 0, "expected 0, got %u\n", off);
4361 U(iob).Status = -1;
4362 iob.Information = -1;
4363 offset.QuadPart = 0;
4364 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4365 ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4366 if (status == STATUS_PENDING)
4368 ret = WaitForSingleObject(hfile, 3000);
4369 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4371 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4372 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4374 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4375 ok(off == 0, "expected 0, got %u\n", off);
4377 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4378 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4380 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4381 ok(off == 0, "expected 0, got %u\n", off);
4383 S(U(ovl)).Offset = sizeof(contents) - 4;
4384 S(U(ovl)).OffsetHigh = 0;
4385 ovl.Internal = -1;
4386 ovl.InternalHigh = -1;
4387 ovl.hEvent = 0;
4388 bytes = 0;
4389 SetLastError(0xdeadbeef);
4390 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4391 /* WriteFile return value depends on Windows version and testing it is not practical */
4392 if (!ret)
4394 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4395 ok(bytes == 0, "bytes %u\n", bytes);
4396 ret = WaitForSingleObject(hfile, 3000);
4397 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4399 else ok(bytes == 4, "bytes %u\n", bytes);
4400 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4401 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4403 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4404 ok(off == 0, "expected 0, got %u\n", off);
4406 bytes = 0xdeadbeef;
4407 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4408 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4409 ok(bytes == 4, "bytes %u\n", bytes);
4410 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4411 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4413 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4414 ok(off == 0, "expected 0, got %u\n", off);
4416 S(U(ovl)).Offset = 0;
4417 S(U(ovl)).OffsetHigh = 0;
4418 ovl.Internal = -1;
4419 ovl.InternalHigh = -1;
4420 ovl.hEvent = 0;
4421 bytes = 0;
4422 SetLastError(0xdeadbeef);
4423 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4424 /* ReadFile return value depends on Windows version and testing it is not practical */
4425 if (!ret)
4427 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4428 ok(bytes == 0, "bytes %u\n", bytes);
4429 ret = WaitForSingleObject(hfile, 3000);
4430 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4432 else ok(bytes == 14, "bytes %u\n", bytes);
4433 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4434 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4436 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4437 ok(off == 0, "expected 0, got %u\n", off);
4439 bytes = 0xdeadbeef;
4440 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4441 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4442 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4443 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4444 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4445 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4446 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4448 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4449 ok(off == 0, "expected 0, got %u\n", off);
4451 CloseHandle(event);
4452 CloseHandle(hfile);
4455 static void test_ioctl(void)
4457 HANDLE event = CreateEventA(NULL, TRUE, FALSE, NULL);
4458 FILE_PIPE_PEEK_BUFFER peek_buf;
4459 IO_STATUS_BLOCK iosb;
4460 HANDLE file;
4461 NTSTATUS status;
4463 file = create_temp_file(FILE_FLAG_OVERLAPPED);
4464 ok(file != INVALID_HANDLE_VALUE, "could not create temp file\n");
4466 SetEvent(event);
4467 status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
4468 todo_wine
4469 ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile returned %x\n", status);
4470 ok(!is_signaled(event), "event is signaled\n");
4472 status = pNtFsControlFile(file, (HANDLE)0xdeadbeef, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
4473 ok(status == STATUS_INVALID_HANDLE, "NtFsControlFile returned %x\n", status);
4475 memset(&iosb, 0x55, sizeof(iosb));
4476 status = pNtFsControlFile(file, NULL, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0,
4477 &peek_buf, sizeof(peek_buf));
4478 todo_wine
4479 ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile failed: %x\n", status);
4480 ok(iosb.Status == 0x55555555, "iosb.Status = %x\n", iosb.Status);
4482 CloseHandle(event);
4483 CloseHandle(file);
4486 static void test_flush_buffers_file(void)
4488 char path[MAX_PATH], buffer[MAX_PATH];
4489 HANDLE hfile, hfileread;
4490 NTSTATUS status;
4491 IO_STATUS_BLOCK io_status_block;
4493 GetTempPathA(MAX_PATH, path);
4494 GetTempFileNameA(path, "foo", 0, buffer);
4495 hfile = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
4496 FILE_ATTRIBUTE_NORMAL, 0);
4497 ok(hfile != INVALID_HANDLE_VALUE, "failed to create temp file.\n" );
4499 hfileread = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
4500 OPEN_EXISTING, 0, NULL);
4501 ok(hfileread != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
4503 status = pNtFlushBuffersFile(hfile, NULL);
4504 todo_wine
4505 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
4507 status = pNtFlushBuffersFile(hfile, (IO_STATUS_BLOCK *)0xdeadbeaf);
4508 todo_wine
4509 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
4511 status = pNtFlushBuffersFile(hfile, &io_status_block);
4512 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
4514 status = pNtFlushBuffersFile(hfileread, &io_status_block);
4515 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#x.\n", status);
4517 status = pNtFlushBuffersFile(NULL, &io_status_block);
4518 ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#x.\n", status);
4520 CloseHandle(hfileread);
4521 CloseHandle(hfile);
4522 hfile = CreateFileA(buffer, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
4523 OPEN_EXISTING, 0, NULL);
4524 ok(hfile != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
4526 status = pNtFlushBuffersFile(hfile, &io_status_block);
4527 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
4529 CloseHandle(hfile);
4530 DeleteFileA(buffer);
4533 START_TEST(file)
4535 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
4536 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
4537 if (!hntdll)
4539 skip("not running on NT, skipping test\n");
4540 return;
4543 pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
4544 pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
4546 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
4547 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
4548 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
4549 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
4550 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
4551 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
4552 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
4553 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
4554 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
4555 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
4556 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
4557 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
4558 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
4559 pNtFsControlFile = (void *)GetProcAddress(hntdll, "NtFsControlFile");
4560 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
4561 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
4562 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
4563 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
4564 pNtRemoveIoCompletionEx = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletionEx");
4565 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
4566 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
4567 pNtQueryAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryAttributesFile");
4568 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
4569 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
4570 pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
4571 pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
4572 pNtFlushBuffersFile = (void *)GetProcAddress(hntdll, "NtFlushBuffersFile");
4574 test_read_write();
4575 test_NtCreateFile();
4576 create_file_test();
4577 open_file_test();
4578 delete_file_test();
4579 read_file_test();
4580 append_file_test();
4581 nt_mailslot_test();
4582 test_set_io_completion();
4583 test_file_io_completion();
4584 test_file_basic_information();
4585 test_file_all_information();
4586 test_file_both_information();
4587 test_file_name_information();
4588 test_file_full_size_information();
4589 test_file_all_name_information();
4590 test_file_rename_information();
4591 test_file_link_information();
4592 test_file_disposition_information();
4593 test_file_completion_information();
4594 test_file_id_information();
4595 test_file_access_information();
4596 test_query_volume_information_file();
4597 test_query_attribute_information_file();
4598 test_ioctl();
4599 test_flush_buffers_file();