ntdll/tests: Add additional tests for NtQueryFullAttributesFile.
[wine.git] / dlls / ntdll / tests / file.c
blob6602581ef29e5b6dc6b280f8ae4c4a74e1828708
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"
41 #ifndef IO_COMPLETION_ALL_ACCESS
42 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
43 #endif
45 static BOOL (WINAPI * pGetVolumePathNameW)(LPCWSTR, LPWSTR, DWORD);
46 static UINT (WINAPI *pGetSystemWow64DirectoryW)( LPWSTR, UINT );
48 static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
49 static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
50 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
51 static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
53 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
54 ULONG, ULONG, ULONG, PLARGE_INTEGER );
55 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
56 static NTSTATUS (WINAPI *pNtOpenFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
57 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
58 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
59 PIO_APC_ROUTINE apc, void* apc_user,
60 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
61 PLARGE_INTEGER offset, PULONG key);
62 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
63 PIO_APC_ROUTINE apc, void* apc_user,
64 PIO_STATUS_BLOCK io_status,
65 const void* buffer, ULONG length,
66 PLARGE_INTEGER offset, PULONG key);
67 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
68 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
69 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
71 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
72 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
73 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
74 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
75 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
76 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
77 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
78 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
79 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
80 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
81 static NTSTATUS (WINAPI *pNtQueryFullAttributesFile)(const OBJECT_ATTRIBUTES*, FILE_NETWORK_OPEN_INFORMATION*);
83 static inline BOOL is_signaled( HANDLE obj )
85 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
88 static const char* debugstr_longlong(ULONGLONG ll)
90 static char str[17];
91 if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
92 sprintf(str, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
93 else
94 sprintf(str, "%lx", (unsigned long)ll);
95 return str;
98 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
99 #define TEST_BUF_LEN 3
101 static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
103 *read = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
104 1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
105 ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
107 *write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
108 ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
110 return TRUE;
113 static HANDLE create_temp_file( ULONG flags )
115 char path[MAX_PATH], buffer[MAX_PATH];
116 HANDLE handle;
118 GetTempPathA( MAX_PATH, path );
119 GetTempFileNameA( path, "foo", 0, buffer );
120 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
121 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
122 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
123 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
126 #define CVALUE_FIRST 0xfffabbcc
127 #define CKEY_FIRST 0x1030341
128 #define CKEY_SECOND 0x132E46
130 static ULONG_PTR completionKey;
131 static IO_STATUS_BLOCK ioSb;
132 static ULONG_PTR completionValue;
134 static ULONG get_pending_msgs(HANDLE h)
136 NTSTATUS res;
137 ULONG a, req;
139 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
140 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
141 if (res != STATUS_SUCCESS) return -1;
142 ok( req == sizeof(a), "Unexpected response size: %x\n", req );
143 return a;
146 static BOOL get_msg(HANDLE h)
148 LARGE_INTEGER timeout = {{-10000000*3}};
149 DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
150 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
151 if (res != STATUS_SUCCESS)
153 completionKey = completionValue = 0;
154 memset(&ioSb, 0, sizeof(ioSb));
155 return FALSE;
157 return TRUE;
161 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
163 int *count = arg;
165 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
166 iosb, U(*iosb).Status, iosb->Information );
167 (*count)++;
168 ok( !reserved, "reserved is not 0: %x\n", reserved );
171 static void create_file_test(void)
173 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
174 '\\','f','a','i','l','i','n','g',0};
175 static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
176 static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
177 static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
178 static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
179 static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
180 FILE_NETWORK_OPEN_INFORMATION info;
181 NTSTATUS status;
182 HANDLE dir, file;
183 WCHAR path[MAX_PATH];
184 OBJECT_ATTRIBUTES attr;
185 IO_STATUS_BLOCK io;
186 UNICODE_STRING nameW;
188 GetCurrentDirectoryW( MAX_PATH, path );
189 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
190 attr.Length = sizeof(attr);
191 attr.RootDirectory = 0;
192 attr.ObjectName = &nameW;
193 attr.Attributes = OBJ_CASE_INSENSITIVE;
194 attr.SecurityDescriptor = NULL;
195 attr.SecurityQualityOfService = NULL;
197 /* try various open modes and options on directories */
198 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
199 FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
200 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
201 CloseHandle( dir );
203 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
204 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
205 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
206 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
208 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
209 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
210 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
211 CloseHandle( dir );
213 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
214 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
215 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
217 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
218 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
219 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
221 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
222 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
223 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
225 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
226 FILE_OPEN, 0, NULL, 0 );
227 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
228 CloseHandle( dir );
230 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
231 FILE_CREATE, 0, NULL, 0 );
232 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
233 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
235 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
236 FILE_OPEN_IF, 0, NULL, 0 );
237 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
238 CloseHandle( dir );
240 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
241 FILE_SUPERSEDE, 0, NULL, 0 );
242 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
243 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
245 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
246 FILE_OVERWRITE, 0, NULL, 0 );
247 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
248 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
250 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
251 FILE_OVERWRITE_IF, 0, NULL, 0 );
252 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
253 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
255 pRtlFreeUnicodeString( &nameW );
257 pRtlInitUnicodeString( &nameW, systemrootW );
258 attr.Length = sizeof(attr);
259 attr.RootDirectory = NULL;
260 attr.ObjectName = &nameW;
261 attr.Attributes = OBJ_CASE_INSENSITIVE;
262 attr.SecurityDescriptor = NULL;
263 attr.SecurityQualityOfService = NULL;
264 dir = NULL;
265 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
266 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
267 todo_wine
268 ok( status == STATUS_INVALID_PARAMETER,
269 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
271 /* Invalid chars in file/dirnames */
272 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
273 attr.ObjectName = &nameW;
274 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
275 FILE_SHARE_READ, FILE_CREATE,
276 FILE_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);
280 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
281 0, FILE_CREATE,
282 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
283 ok(status == STATUS_OBJECT_NAME_INVALID,
284 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
285 pRtlFreeUnicodeString(&nameW);
287 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
288 attr.ObjectName = &nameW;
289 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
290 FILE_SHARE_READ, FILE_CREATE,
291 FILE_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);
295 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
296 0, FILE_CREATE,
297 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
298 ok(status == STATUS_OBJECT_NAME_INVALID,
299 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
300 pRtlFreeUnicodeString(&nameW);
302 pRtlInitUnicodeString( &nameW, pathInvalidNtW );
303 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
304 FILE_SHARE_READ, FILE_CREATE,
305 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
306 ok( status == STATUS_OBJECT_NAME_INVALID,
307 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
309 status = pNtQueryFullAttributesFile( &attr, &info );
310 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
311 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
313 pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
314 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
315 FILE_SHARE_READ, FILE_CREATE,
316 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
317 ok( status == STATUS_OBJECT_NAME_INVALID,
318 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
320 status = pNtQueryFullAttributesFile( &attr, &info );
321 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
322 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
324 pRtlInitUnicodeString( &nameW, pathInvalidDosW );
325 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
326 FILE_SHARE_READ, FILE_CREATE,
327 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
328 ok( status == STATUS_OBJECT_NAME_INVALID,
329 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
331 status = pNtQueryFullAttributesFile( &attr, &info );
332 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
333 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
336 static void open_file_test(void)
338 static const char testdata[] = "Hello World";
339 static WCHAR fooW[] = {'f','o','o',0};
340 NTSTATUS status;
341 HANDLE dir, root, handle, file;
342 WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
343 BYTE data[1024];
344 OBJECT_ATTRIBUTES attr;
345 IO_STATUS_BLOCK io;
346 UNICODE_STRING nameW;
347 UINT i, len;
348 BOOL ret, restart = TRUE;
349 DWORD numbytes;
351 len = GetWindowsDirectoryW( path, MAX_PATH );
352 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
353 attr.Length = sizeof(attr);
354 attr.RootDirectory = 0;
355 attr.ObjectName = &nameW;
356 attr.Attributes = OBJ_CASE_INSENSITIVE;
357 attr.SecurityDescriptor = NULL;
358 attr.SecurityQualityOfService = NULL;
359 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
360 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
361 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
362 pRtlFreeUnicodeString( &nameW );
364 path[3] = 0; /* root of the drive */
365 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
366 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
367 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
368 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
369 pRtlFreeUnicodeString( &nameW );
371 /* test opening system dir with RootDirectory set to windows dir */
372 GetSystemDirectoryW( path, MAX_PATH );
373 while (path[len] == '\\') len++;
374 nameW.Buffer = path + len;
375 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
376 attr.RootDirectory = dir;
377 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
378 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
379 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
380 CloseHandle( handle );
382 /* try uppercase name */
383 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
384 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
385 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
386 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
387 CloseHandle( handle );
389 /* try with leading backslash */
390 nameW.Buffer--;
391 nameW.Length += sizeof(WCHAR);
392 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
393 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
394 ok( status == STATUS_INVALID_PARAMETER ||
395 status == STATUS_OBJECT_NAME_INVALID ||
396 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
397 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
398 if (!status) CloseHandle( handle );
400 /* try with empty name */
401 nameW.Length = 0;
402 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
403 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
404 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
405 CloseHandle( handle );
407 /* try open by file id */
409 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
410 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
412 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
414 restart = FALSE;
416 if (!info->FileId.QuadPart) continue;
418 nameW.Buffer = (WCHAR *)&info->FileId;
419 nameW.Length = sizeof(info->FileId);
420 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
421 attr.RootDirectory = dir;
422 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
423 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
424 FILE_SHARE_READ,
425 FILE_OPEN_BY_FILE_ID |
426 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
427 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
428 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
429 if (status == STATUS_NOT_IMPLEMENTED)
431 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
432 break;
434 if (status == STATUS_SHARING_VIOLATION)
435 trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
436 if (!status)
438 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
440 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
442 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
444 /* check that it's the same file/directory */
446 /* don't check the size for directories */
447 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
448 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
449 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
451 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
452 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
454 CloseHandle( handle );
456 /* try same thing from drive root */
457 attr.RootDirectory = root;
458 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
459 FILE_SHARE_READ|FILE_SHARE_WRITE,
460 FILE_OPEN_BY_FILE_ID |
461 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
462 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
463 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
464 if (!status) CloseHandle( handle );
468 CloseHandle( dir );
469 CloseHandle( root );
471 GetTempPathW( MAX_PATH, path );
472 GetTempFileNameW( path, fooW, 0, tmpfile );
473 pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
475 file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
476 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
477 numbytes = 0xdeadbeef;
478 ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
479 ok( ret, "WriteFile failed with error %u\n", GetLastError() );
480 ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
481 CloseHandle( file );
483 attr.Length = sizeof(attr);
484 attr.RootDirectory = 0;
485 attr.ObjectName = &nameW;
486 attr.Attributes = OBJ_CASE_INSENSITIVE;
487 attr.SecurityDescriptor = NULL;
488 attr.SecurityQualityOfService = NULL;
489 status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
490 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
491 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
492 pRtlFreeUnicodeString( &nameW );
494 numbytes = 0xdeadbeef;
495 memset( data, 0, sizeof(data) );
496 ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
497 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
498 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
499 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
501 nameW.Length = sizeof(fooW) - sizeof(WCHAR);
502 nameW.Buffer = fooW;
503 attr.RootDirectory = file;
504 attr.ObjectName = &nameW;
505 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
506 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
507 ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
508 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
510 nameW.Length = 0;
511 nameW.Buffer = NULL;
512 attr.RootDirectory = file;
513 attr.ObjectName = &nameW;
514 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
515 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
516 ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
518 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
519 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
520 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
521 ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
523 numbytes = 0xdeadbeef;
524 memset( data, 0, sizeof(data) );
525 ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
526 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
527 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
528 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
530 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
531 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
532 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
533 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
535 CloseHandle( file );
536 CloseHandle( root );
537 DeleteFileW( tmpfile );
540 static void delete_file_test(void)
542 NTSTATUS ret;
543 OBJECT_ATTRIBUTES attr;
544 UNICODE_STRING nameW;
545 WCHAR pathW[MAX_PATH];
546 WCHAR pathsubW[MAX_PATH];
547 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
548 static const WCHAR subdirW[] = {'\\','s','u','b',0};
550 ret = GetTempPathW(MAX_PATH, pathW);
551 if (!ret)
553 ok(0, "couldn't get temp dir\n");
554 return;
556 if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
558 ok(0, "MAX_PATH exceeded in constructing paths\n");
559 return;
562 lstrcatW(pathW, testdirW);
563 lstrcpyW(pathsubW, pathW);
564 lstrcatW(pathsubW, subdirW);
566 ret = CreateDirectoryW(pathW, NULL);
567 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
568 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
570 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
571 return;
574 attr.Length = sizeof(attr);
575 attr.RootDirectory = 0;
576 attr.Attributes = OBJ_CASE_INSENSITIVE;
577 attr.ObjectName = &nameW;
578 attr.SecurityDescriptor = NULL;
579 attr.SecurityQualityOfService = NULL;
581 /* test NtDeleteFile on an empty directory */
582 ret = pNtDeleteFile(&attr);
583 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
584 ret = RemoveDirectoryW(pathW);
585 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
587 /* test NtDeleteFile on a non-empty directory */
588 ret = CreateDirectoryW(pathW, NULL);
589 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
590 ret = CreateDirectoryW(pathsubW, NULL);
591 ok(ret == TRUE, "couldn't create directory subdir\n");
592 ret = pNtDeleteFile(&attr);
593 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
594 ret = RemoveDirectoryW(pathsubW);
595 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
596 ret = RemoveDirectoryW(pathW);
597 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
599 pRtlFreeUnicodeString( &nameW );
602 static void read_file_test(void)
604 const char text[] = "foobar";
605 HANDLE handle, read, write;
606 NTSTATUS status;
607 IO_STATUS_BLOCK iosb, iosb2;
608 DWORD written;
609 int apc_count = 0;
610 char buffer[128];
611 LARGE_INTEGER offset;
612 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
613 BOOL ret;
615 buffer[0] = 1;
617 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
619 /* try read with no data */
620 U(iosb).Status = 0xdeadbabe;
621 iosb.Information = 0xdeadbeef;
622 ok( is_signaled( read ), "read handle is not signaled\n" );
623 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
624 ok( status == STATUS_PENDING, "wrong status %x\n", status );
625 ok( !is_signaled( read ), "read handle is signaled\n" );
626 ok( !is_signaled( event ), "event is signaled\n" );
627 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
628 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
629 ok( !apc_count, "apc was called\n" );
630 ret = WriteFile( write, buffer, 1, &written, NULL );
631 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
632 /* iosb updated here by async i/o */
633 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
634 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
635 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
636 ok( !is_signaled( read ), "read handle is signaled\n" );
637 ok( is_signaled( event ), "event is not signaled\n" );
638 ok( !apc_count, "apc was called\n" );
639 apc_count = 0;
640 SleepEx( 1, FALSE ); /* non-alertable sleep */
641 ok( !apc_count, "apc was called\n" );
642 SleepEx( 1, TRUE ); /* alertable sleep */
643 ok( apc_count == 1, "apc not called\n" );
645 /* with no event, the pipe handle itself gets signaled */
646 apc_count = 0;
647 U(iosb).Status = 0xdeadbabe;
648 iosb.Information = 0xdeadbeef;
649 ok( !is_signaled( read ), "read handle is not signaled\n" );
650 status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
651 ok( status == STATUS_PENDING, "wrong status %x\n", status );
652 ok( !is_signaled( read ), "read handle is signaled\n" );
653 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
654 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
655 ok( !apc_count, "apc was called\n" );
656 ret = WriteFile( write, buffer, 1, &written, NULL );
657 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
658 /* iosb updated here by async i/o */
659 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
660 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
661 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
662 ok( is_signaled( read ), "read handle is signaled\n" );
663 ok( !apc_count, "apc was called\n" );
664 apc_count = 0;
665 SleepEx( 1, FALSE ); /* non-alertable sleep */
666 ok( !apc_count, "apc was called\n" );
667 SleepEx( 1, TRUE ); /* alertable sleep */
668 ok( apc_count == 1, "apc not called\n" );
670 /* now read with data ready */
671 apc_count = 0;
672 U(iosb).Status = 0xdeadbabe;
673 iosb.Information = 0xdeadbeef;
674 ResetEvent( event );
675 ret = WriteFile( write, buffer, 1, &written, NULL );
676 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
677 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
678 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
679 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
680 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
681 ok( is_signaled( event ), "event is not signaled\n" );
682 ok( !apc_count, "apc was called\n" );
683 SleepEx( 1, FALSE ); /* non-alertable sleep */
684 ok( !apc_count, "apc was called\n" );
685 SleepEx( 1, TRUE ); /* alertable sleep */
686 ok( apc_count == 1, "apc not called\n" );
688 /* try read with no data */
689 apc_count = 0;
690 U(iosb).Status = 0xdeadbabe;
691 iosb.Information = 0xdeadbeef;
692 ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
693 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
694 ok( status == STATUS_PENDING, "wrong status %x\n", status );
695 ok( !is_signaled( event ), "event is signaled\n" );
696 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
697 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
698 ok( !apc_count, "apc was called\n" );
699 ret = WriteFile( write, buffer, 1, &written, NULL );
700 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
701 /* partial read is good enough */
702 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
703 ok( is_signaled( event ), "event is signaled\n" );
704 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
705 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
706 ok( !apc_count, "apc was called\n" );
707 SleepEx( 1, TRUE ); /* alertable sleep */
708 ok( apc_count == 1, "apc was not called\n" );
710 /* read from disconnected pipe */
711 apc_count = 0;
712 U(iosb).Status = 0xdeadbabe;
713 iosb.Information = 0xdeadbeef;
714 CloseHandle( write );
715 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
716 ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
717 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
718 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
719 ok( !is_signaled( event ), "event is signaled\n" );
720 ok( !apc_count, "apc was called\n" );
721 SleepEx( 1, TRUE ); /* alertable sleep */
722 ok( !apc_count, "apc was called\n" );
723 CloseHandle( read );
725 /* read from closed handle */
726 apc_count = 0;
727 U(iosb).Status = 0xdeadbabe;
728 iosb.Information = 0xdeadbeef;
729 SetEvent( event );
730 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
731 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
732 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
733 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
734 ok( is_signaled( event ), "event is signaled\n" ); /* not reset on invalid handle */
735 ok( !apc_count, "apc was called\n" );
736 SleepEx( 1, TRUE ); /* alertable sleep */
737 ok( !apc_count, "apc was called\n" );
739 /* disconnect while async read is in progress */
740 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
741 apc_count = 0;
742 U(iosb).Status = 0xdeadbabe;
743 iosb.Information = 0xdeadbeef;
744 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
745 ok( status == STATUS_PENDING, "wrong status %x\n", status );
746 ok( !is_signaled( event ), "event is signaled\n" );
747 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
748 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
749 ok( !apc_count, "apc was called\n" );
750 CloseHandle( write );
751 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
752 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
753 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
754 ok( is_signaled( event ), "event is signaled\n" );
755 ok( !apc_count, "apc was called\n" );
756 SleepEx( 1, TRUE ); /* alertable sleep */
757 ok( apc_count == 1, "apc was not called\n" );
758 CloseHandle( read );
760 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
761 ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
762 ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
764 apc_count = 0;
765 U(iosb).Status = 0xdeadbabe;
766 iosb.Information = 0xdeadbeef;
767 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
768 ok( status == STATUS_PENDING, "wrong status %x\n", status );
769 ok( !is_signaled( event ), "event is signaled\n" );
770 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
771 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
772 ok( !apc_count, "apc was called\n" );
773 /* Cancel by other handle */
774 status = pNtCancelIoFile( read, &iosb2 );
775 ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
776 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
777 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
778 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
779 ok( is_signaled( event ), "event is signaled\n" );
780 ok( !apc_count, "apc was called\n" );
781 SleepEx( 1, TRUE ); /* alertable sleep */
782 ok( apc_count == 1, "apc was not called\n" );
784 apc_count = 0;
785 U(iosb).Status = 0xdeadbabe;
786 iosb.Information = 0xdeadbeef;
787 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
788 ok( status == STATUS_PENDING, "wrong status %x\n", status );
789 ok( !is_signaled( event ), "event is signaled\n" );
790 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
791 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
792 ok( !apc_count, "apc was called\n" );
793 /* Close queued handle */
794 CloseHandle( read );
795 SleepEx( 1, TRUE ); /* alertable sleep */
796 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
797 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
798 status = pNtCancelIoFile( read, &iosb2 );
799 ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
800 status = pNtCancelIoFile( handle, &iosb2 );
801 ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
802 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
803 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
804 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
805 ok( is_signaled( event ), "event is signaled\n" );
806 ok( !apc_count, "apc was called\n" );
807 SleepEx( 1, TRUE ); /* alertable sleep */
808 ok( apc_count == 1, "apc was not called\n" );
809 CloseHandle( handle );
810 CloseHandle( write );
812 if (pNtCancelIoFileEx)
814 /* Basic Cancel Ex */
815 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
817 apc_count = 0;
818 U(iosb).Status = 0xdeadbabe;
819 iosb.Information = 0xdeadbeef;
820 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
821 ok( status == STATUS_PENDING, "wrong status %x\n", status );
822 ok( !is_signaled( event ), "event is signaled\n" );
823 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
824 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
825 ok( !apc_count, "apc was called\n" );
826 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
827 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
828 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
829 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
830 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
831 ok( is_signaled( event ), "event is signaled\n" );
832 ok( !apc_count, "apc was called\n" );
833 SleepEx( 1, TRUE ); /* alertable sleep */
834 ok( apc_count == 1, "apc was not called\n" );
836 /* Duplicate iosb */
837 apc_count = 0;
838 U(iosb).Status = 0xdeadbabe;
839 iosb.Information = 0xdeadbeef;
840 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
841 ok( status == STATUS_PENDING, "wrong status %x\n", status );
842 ok( !is_signaled( event ), "event is signaled\n" );
843 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
844 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
845 ok( !apc_count, "apc was called\n" );
846 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
847 ok( status == STATUS_PENDING, "wrong status %x\n", status );
848 ok( !is_signaled( event ), "event is signaled\n" );
849 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
850 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
851 ok( !apc_count, "apc was called\n" );
852 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
853 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
854 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
855 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
856 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
857 ok( is_signaled( event ), "event is signaled\n" );
858 ok( !apc_count, "apc was called\n" );
859 SleepEx( 1, TRUE ); /* alertable sleep */
860 ok( apc_count == 2, "apc was not called\n" );
862 CloseHandle( read );
863 CloseHandle( write );
866 /* now try a real file */
867 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
868 apc_count = 0;
869 U(iosb).Status = 0xdeadbabe;
870 iosb.Information = 0xdeadbeef;
871 offset.QuadPart = 0;
872 ResetEvent( event );
873 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
874 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
875 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
876 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
877 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
878 ok( is_signaled( event ), "event is signaled\n" );
879 ok( !apc_count, "apc was called\n" );
880 SleepEx( 1, TRUE ); /* alertable sleep */
881 ok( apc_count == 1, "apc was not called\n" );
883 apc_count = 0;
884 U(iosb).Status = 0xdeadbabe;
885 iosb.Information = 0xdeadbeef;
886 offset.QuadPart = 0;
887 ResetEvent( event );
888 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
889 ok( status == STATUS_SUCCESS ||
890 status == STATUS_PENDING, /* vista */
891 "wrong status %x\n", status );
892 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
893 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
894 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
895 ok( is_signaled( event ), "event is signaled\n" );
896 ok( !apc_count, "apc was called\n" );
897 SleepEx( 1, TRUE ); /* alertable sleep */
898 ok( apc_count == 1, "apc was not called\n" );
900 /* read beyond eof */
901 apc_count = 0;
902 U(iosb).Status = 0xdeadbabe;
903 iosb.Information = 0xdeadbeef;
904 offset.QuadPart = strlen(text) + 2;
905 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
906 ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
907 if (status == STATUS_PENDING) /* vista */
909 WaitForSingleObject( event, 1000 );
910 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
911 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
912 ok( is_signaled( event ), "event is signaled\n" );
913 ok( !apc_count, "apc was called\n" );
914 SleepEx( 1, TRUE ); /* alertable sleep */
915 ok( apc_count == 1, "apc was not called\n" );
917 CloseHandle( handle );
919 /* now a non-overlapped file */
920 if (!(handle = create_temp_file(0))) return;
921 apc_count = 0;
922 U(iosb).Status = 0xdeadbabe;
923 iosb.Information = 0xdeadbeef;
924 offset.QuadPart = 0;
925 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
926 ok( status == STATUS_END_OF_FILE ||
927 status == STATUS_SUCCESS ||
928 status == STATUS_PENDING, /* vista */
929 "wrong status %x\n", status );
930 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
931 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
932 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
933 ok( is_signaled( event ), "event is signaled\n" );
934 ok( !apc_count, "apc was called\n" );
935 SleepEx( 1, TRUE ); /* alertable sleep */
936 ok( apc_count == 1, "apc was not called\n" );
938 apc_count = 0;
939 U(iosb).Status = 0xdeadbabe;
940 iosb.Information = 0xdeadbeef;
941 offset.QuadPart = 0;
942 ResetEvent( event );
943 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
944 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
945 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
946 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
947 ok( is_signaled( event ), "event is signaled\n" );
948 ok( !apc_count, "apc was called\n" );
949 SleepEx( 1, TRUE ); /* alertable sleep */
950 todo_wine ok( !apc_count, "apc was called\n" );
952 /* read beyond eof */
953 apc_count = 0;
954 U(iosb).Status = 0xdeadbabe;
955 iosb.Information = 0xdeadbeef;
956 offset.QuadPart = strlen(text) + 2;
957 ResetEvent( event );
958 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
959 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
960 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
961 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
962 ok( is_signaled( event ), "event is not signaled\n" );
963 ok( !apc_count, "apc was called\n" );
964 SleepEx( 1, TRUE ); /* alertable sleep */
965 ok( !apc_count, "apc was called\n" );
967 CloseHandle( handle );
969 CloseHandle( event );
972 static void append_file_test(void)
974 static const char text[6] = "foobar";
975 HANDLE handle;
976 NTSTATUS status;
977 IO_STATUS_BLOCK iosb;
978 LARGE_INTEGER offset;
979 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
980 DWORD ret;
982 GetTempPathA( MAX_PATH, path );
983 GetTempFileNameA( path, "foo", 0, buffer );
985 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
986 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
988 U(iosb).Status = -1;
989 iosb.Information = -1;
990 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
991 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
992 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
993 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
995 CloseHandle(handle);
997 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
998 It matches the O_WRONLY|O_APPEND open() posix behavior */
999 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
1000 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1002 U(iosb).Status = -1;
1003 iosb.Information = -1;
1004 offset.QuadPart = 1;
1005 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
1006 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
1007 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1008 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
1010 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
1011 ok(ret == 4, "expected 4, got %u\n", ret);
1013 U(iosb).Status = -1;
1014 iosb.Information = -1;
1015 offset.QuadPart = 3;
1016 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
1017 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
1018 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1019 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
1021 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
1022 ok(ret == 6, "expected 6, got %u\n", ret);
1024 CloseHandle(handle);
1026 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
1027 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1029 memset(buf, 0, sizeof(buf));
1030 U(iosb).Status = -1;
1031 iosb.Information = -1;
1032 offset.QuadPart = 0;
1033 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
1034 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
1035 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1036 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
1037 buf[6] = 0;
1038 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
1040 U(iosb).Status = -1;
1041 iosb.Information = -1;
1042 offset.QuadPart = 0;
1043 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
1044 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
1045 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1046 ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
1048 memset(buf, 0, sizeof(buf));
1049 U(iosb).Status = -1;
1050 iosb.Information = -1;
1051 offset.QuadPart = 0;
1052 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
1053 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
1054 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1055 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
1056 buf[6] = 0;
1057 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
1059 CloseHandle(handle);
1060 DeleteFileA(buffer);
1063 static void nt_mailslot_test(void)
1065 HANDLE hslot;
1066 ACCESS_MASK DesiredAccess;
1067 OBJECT_ATTRIBUTES attr;
1069 ULONG CreateOptions;
1070 ULONG MailslotQuota;
1071 ULONG MaxMessageSize;
1072 LARGE_INTEGER TimeOut;
1073 IO_STATUS_BLOCK IoStatusBlock;
1074 NTSTATUS rc;
1075 UNICODE_STRING str;
1076 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
1077 'R',':','\\','F','R','E','D','\0' };
1079 TimeOut.QuadPart = -1;
1081 pRtlInitUnicodeString(&str, buffer1);
1082 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1083 CreateOptions = MailslotQuota = MaxMessageSize = 0;
1084 DesiredAccess = GENERIC_READ;
1087 * Check for NULL pointer handling
1089 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
1090 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1091 &TimeOut);
1092 ok( rc == STATUS_ACCESS_VIOLATION ||
1093 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
1094 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
1097 * Test to see if the Timeout can be NULL
1099 hslot = (HANDLE)0xdeadbeef;
1100 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1101 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1102 NULL);
1103 ok( rc == STATUS_SUCCESS ||
1104 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
1105 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
1106 ok( hslot != 0, "Handle is invalid\n");
1108 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
1111 * Test that the length field is checked properly
1113 attr.Length = 0;
1114 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1115 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1116 &TimeOut);
1117 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
1119 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1121 attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
1122 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1123 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1124 &TimeOut);
1125 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
1127 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1130 * Test handling of a NULL unicode string in ObjectName
1132 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1133 attr.ObjectName = NULL;
1134 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1135 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1136 &TimeOut);
1137 ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
1138 rc == STATUS_INVALID_PARAMETER,
1139 "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
1141 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1144 * Test a valid call
1146 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1147 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1148 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1149 &TimeOut);
1150 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
1151 ok( hslot != 0, "Handle is invalid\n");
1153 rc = pNtClose(hslot);
1154 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
1157 static void test_iocp_setcompletion(HANDLE h)
1159 NTSTATUS res;
1160 ULONG count;
1161 SIZE_T size = 3;
1163 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
1165 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
1166 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
1168 count = get_pending_msgs(h);
1169 ok( count == 1, "Unexpected msg count: %d\n", count );
1171 if (get_msg(h))
1173 ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
1174 ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
1175 ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1176 ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
1179 count = get_pending_msgs(h);
1180 ok( !count, "Unexpected msg count: %d\n", count );
1183 static void test_iocp_fileio(HANDLE h)
1185 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1187 IO_STATUS_BLOCK iosb;
1188 FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
1189 HANDLE hPipeSrv, hPipeClt;
1190 NTSTATUS res;
1192 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1193 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1194 if (hPipeSrv != INVALID_HANDLE_VALUE )
1196 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1197 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1198 if (hPipeClt != INVALID_HANDLE_VALUE)
1200 U(iosb).Status = 0xdeadbeef;
1201 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1202 ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
1203 ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
1204 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
1205 CloseHandle(hPipeClt);
1207 CloseHandle( hPipeSrv );
1210 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1211 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1212 if (hPipeSrv == INVALID_HANDLE_VALUE )
1213 return;
1215 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1216 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1217 if (hPipeClt != INVALID_HANDLE_VALUE)
1219 OVERLAPPED o = {0,};
1220 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1221 DWORD read;
1222 long count;
1224 U(iosb).Status = 0xdeadbeef;
1225 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1226 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1227 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1229 memset( send_buf, 0, TEST_BUF_LEN );
1230 memset( recv_buf, 0xde, TEST_BUF_LEN );
1231 count = get_pending_msgs(h);
1232 ok( !count, "Unexpected msg count: %ld\n", count );
1233 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1234 count = get_pending_msgs(h);
1235 ok( !count, "Unexpected msg count: %ld\n", count );
1236 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1238 if (get_msg(h))
1240 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1241 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1242 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1243 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1244 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1246 count = get_pending_msgs(h);
1247 ok( !count, "Unexpected msg count: %ld\n", count );
1249 memset( send_buf, 0, TEST_BUF_LEN );
1250 memset( recv_buf, 0xde, TEST_BUF_LEN );
1251 WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1252 count = get_pending_msgs(h);
1253 ok( !count, "Unexpected msg count: %ld\n", count );
1254 ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1255 count = get_pending_msgs(h);
1256 ok( count == 1, "Unexpected msg count: %ld\n", count );
1257 if (get_msg(h))
1259 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1260 ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1261 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1262 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1263 ok( !memcmp( send_buf, recv_buf, 2 ), "Receive buffer (%x %x) did not match send buffer (%x %x)\n", recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
1266 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1267 CloseHandle( hPipeSrv );
1268 count = get_pending_msgs(h);
1269 ok( count == 1, "Unexpected msg count: %ld\n", count );
1270 if (get_msg(h))
1272 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1273 ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1274 /* wine sends wrong status here */
1275 todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1276 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1280 CloseHandle( hPipeClt );
1282 /* test associating a completion port with a handle after an async is queued */
1283 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1284 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1285 if (hPipeSrv == INVALID_HANDLE_VALUE )
1286 return;
1287 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1288 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1289 if (hPipeClt != INVALID_HANDLE_VALUE)
1291 OVERLAPPED o = {0,};
1292 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1293 DWORD read;
1294 long count;
1296 memset( send_buf, 0, TEST_BUF_LEN );
1297 memset( recv_buf, 0xde, TEST_BUF_LEN );
1298 count = get_pending_msgs(h);
1299 ok( !count, "Unexpected msg count: %ld\n", count );
1300 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1302 U(iosb).Status = 0xdeadbeef;
1303 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1304 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1305 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1306 count = get_pending_msgs(h);
1307 ok( !count, "Unexpected msg count: %ld\n", count );
1309 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1311 if (get_msg(h))
1313 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1314 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1315 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1316 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1317 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1319 count = get_pending_msgs(h);
1320 ok( !count, "Unexpected msg count: %ld\n", count );
1323 CloseHandle( hPipeSrv );
1324 CloseHandle( hPipeClt );
1327 static void test_file_full_size_information(void)
1329 IO_STATUS_BLOCK io;
1330 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1331 FILE_FS_SIZE_INFORMATION fsi;
1332 HANDLE h;
1333 NTSTATUS res;
1335 if(!(h = create_temp_file(0))) return ;
1337 memset(&ffsi,0,sizeof(ffsi));
1338 memset(&fsi,0,sizeof(fsi));
1340 /* Assume No Quota Settings configured on Wine Testbot */
1341 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1342 todo_wine ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1343 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1344 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1346 /* Test for FileFsSizeInformation */
1347 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1348 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1349 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1350 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1351 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1352 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1354 /* Assume file system is NTFS */
1355 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1356 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1358 todo_wine
1360 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1361 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1362 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1363 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1364 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1365 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1366 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1367 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1368 debugstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1369 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1370 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1371 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1372 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1373 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1374 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1375 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1376 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1379 /* Assume file system is NTFS */
1380 todo_wine
1382 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1383 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1386 CloseHandle( h );
1389 static void test_file_basic_information(void)
1391 IO_STATUS_BLOCK io;
1392 FILE_BASIC_INFORMATION fbi;
1393 HANDLE h;
1394 int res;
1395 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1397 if (!(h = create_temp_file(0))) return;
1399 /* Check default first */
1400 memset(&fbi, 0, sizeof(fbi));
1401 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1402 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1403 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1404 "attribute %x not expected\n", fbi.FileAttributes );
1406 /* Then SYSTEM */
1407 /* Clear fbi to avoid setting times */
1408 memset(&fbi, 0, sizeof(fbi));
1409 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1410 U(io).Status = 0xdeadbeef;
1411 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1412 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1413 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1415 memset(&fbi, 0, sizeof(fbi));
1416 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1417 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1418 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1420 /* Then HIDDEN */
1421 memset(&fbi, 0, sizeof(fbi));
1422 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1423 U(io).Status = 0xdeadbeef;
1424 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1425 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1426 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1428 memset(&fbi, 0, sizeof(fbi));
1429 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1430 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1431 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1433 /* Check NORMAL last of all (to make sure we can clear attributes) */
1434 memset(&fbi, 0, sizeof(fbi));
1435 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1436 U(io).Status = 0xdeadbeef;
1437 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1438 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1439 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1441 memset(&fbi, 0, sizeof(fbi));
1442 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1443 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1444 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1446 CloseHandle( h );
1449 static void test_file_all_information(void)
1451 IO_STATUS_BLOCK io;
1452 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1453 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1454 * don't leave enough room there.
1456 struct {
1457 FILE_ALL_INFORMATION fai;
1458 WCHAR buf[256];
1459 } fai_buf;
1460 HANDLE h;
1461 int res;
1462 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1464 if (!(h = create_temp_file(0))) return;
1466 /* Check default first */
1467 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1468 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1469 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1470 "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1472 /* Then SYSTEM */
1473 /* Clear fbi to avoid setting times */
1474 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1475 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1476 U(io).Status = 0xdeadbeef;
1477 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1478 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1479 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1480 U(io).Status = 0xdeadbeef;
1481 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1482 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1483 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1485 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1486 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1487 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1488 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 );
1490 /* Then HIDDEN */
1491 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1492 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1493 U(io).Status = 0xdeadbeef;
1494 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1495 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1496 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1498 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1499 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1500 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1501 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 );
1503 /* Check NORMAL last of all (to make sure we can clear attributes) */
1504 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1505 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1506 U(io).Status = 0xdeadbeef;
1507 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1508 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1509 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1511 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1512 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1513 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1514 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 );
1516 CloseHandle( h );
1519 static void delete_object( WCHAR *path )
1521 BOOL ret = DeleteFileW( path );
1522 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1523 "DeleteFileW failed with %u\n", GetLastError() );
1524 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1526 ret = RemoveDirectoryW( path );
1527 ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
1531 static void test_file_rename_information(void)
1533 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1534 static const WCHAR fooW[] = {'f','o','o',0};
1535 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1536 FILE_RENAME_INFORMATION *fri;
1537 FILE_NAME_INFORMATION *fni;
1538 BOOL success, fileDeleted;
1539 UNICODE_STRING name_str;
1540 HANDLE handle, handle2;
1541 IO_STATUS_BLOCK io;
1542 NTSTATUS res;
1544 GetTempPathW( MAX_PATH, tmp_path );
1546 /* oldpath is a file, newpath doesn't exist */
1547 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1548 ok( res != 0, "failed to create temp file\n" );
1549 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1550 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1552 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1553 ok( res != 0, "failed to create temp file\n" );
1554 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1555 DeleteFileW( newpath );
1556 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1557 fri->Replace = FALSE;
1558 fri->RootDir = NULL;
1559 fri->FileNameLength = name_str.Length;
1560 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1561 pRtlFreeUnicodeString( &name_str );
1563 U(io).Status = 0xdeadbeef;
1564 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1565 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1566 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1567 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1568 ok( fileDeleted, "file should not exist\n" );
1569 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1570 ok( !fileDeleted, "file should exist\n" );
1572 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1573 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1574 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1575 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1576 ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1577 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1578 HeapFree( GetProcessHeap(), 0, fni );
1580 CloseHandle( handle );
1581 HeapFree( GetProcessHeap(), 0, fri );
1582 delete_object( oldpath );
1583 delete_object( newpath );
1585 /* oldpath is a file, newpath is a file, Replace = FALSE */
1586 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1587 ok( res != 0, "failed to create temp file\n" );
1588 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1589 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1591 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1592 ok( res != 0, "failed to create temp file\n" );
1593 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1594 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1595 fri->Replace = FALSE;
1596 fri->RootDir = NULL;
1597 fri->FileNameLength = name_str.Length;
1598 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1599 pRtlFreeUnicodeString( &name_str );
1601 U(io).Status = 0xdeadbeef;
1602 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1603 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1604 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1605 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1606 ok( !fileDeleted, "file should exist\n" );
1607 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1608 ok( !fileDeleted, "file should exist\n" );
1610 CloseHandle( handle );
1611 HeapFree( GetProcessHeap(), 0, fri );
1612 delete_object( oldpath );
1613 delete_object( newpath );
1615 /* oldpath is a file, newpath is a file, Replace = TRUE */
1616 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1617 ok( res != 0, "failed to create temp file\n" );
1618 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1619 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1621 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1622 ok( res != 0, "failed to create temp file\n" );
1623 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1624 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1625 fri->Replace = TRUE;
1626 fri->RootDir = NULL;
1627 fri->FileNameLength = name_str.Length;
1628 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1629 pRtlFreeUnicodeString( &name_str );
1631 U(io).Status = 0xdeadbeef;
1632 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1633 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1634 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1635 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1636 ok( fileDeleted, "file should not exist\n" );
1637 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1638 ok( !fileDeleted, "file should exist\n" );
1640 CloseHandle( handle );
1641 HeapFree( GetProcessHeap(), 0, fri );
1642 delete_object( oldpath );
1643 delete_object( newpath );
1645 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1646 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1647 ok( res != 0, "failed to create temp file\n" );
1648 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1649 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1651 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1652 ok( res != 0, "failed to create temp file\n" );
1653 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1654 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1656 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1657 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1658 fri->Replace = FALSE;
1659 fri->RootDir = NULL;
1660 fri->FileNameLength = name_str.Length;
1661 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1662 pRtlFreeUnicodeString( &name_str );
1664 U(io).Status = 0xdeadbeef;
1665 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1666 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1667 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1668 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1669 ok( !fileDeleted, "file should exist\n" );
1670 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1671 ok( !fileDeleted, "file should exist\n" );
1673 CloseHandle( handle );
1674 CloseHandle( handle2 );
1675 HeapFree( GetProcessHeap(), 0, fri );
1676 delete_object( oldpath );
1677 delete_object( newpath );
1679 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1680 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1681 ok( res != 0, "failed to create temp file\n" );
1682 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1683 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1685 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1686 ok( res != 0, "failed to create temp file\n" );
1687 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1688 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1690 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1691 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1692 fri->Replace = TRUE;
1693 fri->RootDir = NULL;
1694 fri->FileNameLength = name_str.Length;
1695 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1696 pRtlFreeUnicodeString( &name_str );
1698 U(io).Status = 0xdeadbeef;
1699 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1700 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1701 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1702 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1703 ok( !fileDeleted, "file should exist\n" );
1704 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1705 ok( !fileDeleted, "file should exist\n" );
1707 CloseHandle( handle );
1708 CloseHandle( handle2 );
1709 HeapFree( GetProcessHeap(), 0, fri );
1710 delete_object( oldpath );
1711 delete_object( newpath );
1713 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1714 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1715 ok( res != 0, "failed to create temp file\n" );
1716 DeleteFileW( oldpath );
1717 success = CreateDirectoryW( oldpath, NULL );
1718 ok( success != 0, "failed to create temp directory\n" );
1719 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1720 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1722 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1723 ok( res != 0, "failed to create temp file\n" );
1724 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1725 DeleteFileW( newpath );
1726 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1727 fri->Replace = FALSE;
1728 fri->RootDir = NULL;
1729 fri->FileNameLength = name_str.Length;
1730 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1731 pRtlFreeUnicodeString( &name_str );
1733 U(io).Status = 0xdeadbeef;
1734 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1735 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1736 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1737 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1738 ok( fileDeleted, "file should not exist\n" );
1739 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1740 ok( !fileDeleted, "file should exist\n" );
1742 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1743 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1744 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1745 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1746 ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1747 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1748 HeapFree( GetProcessHeap(), 0, fni );
1750 CloseHandle( handle );
1751 HeapFree( GetProcessHeap(), 0, fri );
1752 delete_object( oldpath );
1753 delete_object( newpath );
1755 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1756 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1757 ok( res != 0, "failed to create temp file\n" );
1758 DeleteFileW( oldpath );
1759 success = CreateDirectoryW( oldpath, NULL );
1760 ok( success != 0, "failed to create temp directory\n" );
1761 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1762 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1764 lstrcpyW( newpath, oldpath );
1765 lstrcatW( newpath, foo_txtW );
1766 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1767 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1769 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1770 ok( res != 0, "failed to create temp file\n" );
1771 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1772 DeleteFileW( newpath );
1773 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1774 fri->Replace = FALSE;
1775 fri->RootDir = NULL;
1776 fri->FileNameLength = name_str.Length;
1777 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1778 pRtlFreeUnicodeString( &name_str );
1780 U(io).Status = 0xdeadbeef;
1781 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1782 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1783 todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1784 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1785 todo_wine ok( !fileDeleted, "file should exist\n" );
1786 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1787 todo_wine ok( fileDeleted, "file should not exist\n" );
1789 CloseHandle( handle );
1790 CloseHandle( handle2 );
1791 HeapFree( GetProcessHeap(), 0, fri );
1792 delete_object( oldpath );
1793 if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1795 lstrcpyW( oldpath, newpath );
1796 lstrcatW( oldpath, foo_txtW );
1797 delete_object( oldpath );
1799 delete_object( newpath );
1801 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1802 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1803 ok( res != 0, "failed to create temp file\n" );
1804 DeleteFileW( oldpath );
1805 success = CreateDirectoryW( oldpath, NULL );
1806 ok( success != 0, "failed to create temp directory\n" );
1807 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1808 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1810 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1811 ok( res != 0, "failed to create temp file\n" );
1812 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1813 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1814 fri->Replace = FALSE;
1815 fri->RootDir = NULL;
1816 fri->FileNameLength = name_str.Length;
1817 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1818 pRtlFreeUnicodeString( &name_str );
1820 U(io).Status = 0xdeadbeef;
1821 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1822 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1823 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1824 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1825 ok( !fileDeleted, "file should exist\n" );
1826 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1827 ok( !fileDeleted, "file should exist\n" );
1829 CloseHandle( handle );
1830 HeapFree( GetProcessHeap(), 0, fri );
1831 delete_object( oldpath );
1832 delete_object( newpath );
1834 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1835 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1836 ok( res != 0, "failed to create temp file\n" );
1837 DeleteFileW( oldpath );
1838 success = CreateDirectoryW( oldpath, NULL );
1839 ok( success != 0, "failed to create temp directory\n" );
1840 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1841 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1843 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1844 ok( res != 0, "failed to create temp file\n" );
1845 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1846 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1848 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1849 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1850 fri->Replace = FALSE;
1851 fri->RootDir = NULL;
1852 fri->FileNameLength = name_str.Length;
1853 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1854 pRtlFreeUnicodeString( &name_str );
1856 U(io).Status = 0xdeadbeef;
1857 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1858 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1859 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1860 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1861 ok( !fileDeleted, "file should exist\n" );
1862 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1863 ok( !fileDeleted, "file should exist\n" );
1865 CloseHandle( handle );
1866 CloseHandle( handle2 );
1867 HeapFree( GetProcessHeap(), 0, fri );
1868 delete_object( oldpath );
1869 delete_object( newpath );
1871 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1872 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1873 ok( res != 0, "failed to create temp file\n" );
1874 DeleteFileW( oldpath );
1875 success = CreateDirectoryW( oldpath, NULL );
1876 ok( success != 0, "failed to create temp directory\n" );
1877 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1878 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1880 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1881 ok( res != 0, "failed to create temp file\n" );
1882 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1883 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1884 fri->Replace = TRUE;
1885 fri->RootDir = NULL;
1886 fri->FileNameLength = name_str.Length;
1887 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1888 pRtlFreeUnicodeString( &name_str );
1890 U(io).Status = 0xdeadbeef;
1891 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1892 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1893 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1894 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1895 ok( fileDeleted, "file should not exist\n" );
1896 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1897 ok( !fileDeleted, "file should exist\n" );
1899 CloseHandle( handle );
1900 HeapFree( GetProcessHeap(), 0, fri );
1901 delete_object( oldpath );
1902 delete_object( newpath );
1904 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1905 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1906 ok( res != 0, "failed to create temp file\n" );
1907 DeleteFileW( oldpath );
1908 success = CreateDirectoryW( oldpath, NULL );
1909 ok( success != 0, "failed to create temp directory\n" );
1910 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1911 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1913 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1914 ok( res != 0, "failed to create temp file\n" );
1915 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1916 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1918 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1919 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1920 fri->Replace = TRUE;
1921 fri->RootDir = NULL;
1922 fri->FileNameLength = name_str.Length;
1923 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1924 pRtlFreeUnicodeString( &name_str );
1926 U(io).Status = 0xdeadbeef;
1927 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1928 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1929 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1930 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1931 ok( !fileDeleted, "file should exist\n" );
1932 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1933 ok( !fileDeleted, "file should exist\n" );
1935 CloseHandle( handle );
1936 CloseHandle( handle2 );
1937 HeapFree( GetProcessHeap(), 0, fri );
1938 delete_object( oldpath );
1939 delete_object( newpath );
1941 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1942 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1943 ok( res != 0, "failed to create temp file\n" );
1944 DeleteFileW( oldpath );
1945 success = CreateDirectoryW( oldpath, NULL );
1946 ok( success != 0, "failed to create temp directory\n" );
1947 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1948 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1950 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1951 ok( res != 0, "failed to create temp file\n" );
1952 DeleteFileW( newpath );
1953 success = CreateDirectoryW( newpath, NULL );
1954 ok( success != 0, "failed to create temp directory\n" );
1955 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1956 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1957 fri->Replace = FALSE;
1958 fri->RootDir = NULL;
1959 fri->FileNameLength = name_str.Length;
1960 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1961 pRtlFreeUnicodeString( &name_str );
1963 U(io).Status = 0xdeadbeef;
1964 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1965 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1966 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1967 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1968 ok( !fileDeleted, "file should exist\n" );
1969 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1970 ok( !fileDeleted, "file should exist\n" );
1972 CloseHandle( handle );
1973 HeapFree( GetProcessHeap(), 0, fri );
1974 delete_object( oldpath );
1975 delete_object( newpath );
1977 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1978 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1979 ok( res != 0, "failed to create temp file\n" );
1980 DeleteFileW( oldpath );
1981 success = CreateDirectoryW( oldpath, NULL );
1982 ok( success != 0, "failed to create temp directory\n" );
1983 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1984 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1986 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1987 ok( res != 0, "failed to create temp file\n" );
1988 DeleteFileW( newpath );
1989 success = CreateDirectoryW( newpath, NULL );
1990 ok( success != 0, "failed to create temp directory\n" );
1991 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1992 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1993 fri->Replace = TRUE;
1994 fri->RootDir = NULL;
1995 fri->FileNameLength = name_str.Length;
1996 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1997 pRtlFreeUnicodeString( &name_str );
1999 U(io).Status = 0xdeadbeef;
2000 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2001 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2002 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2003 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2004 ok( !fileDeleted, "file should exist\n" );
2005 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2006 ok( !fileDeleted, "file should exist\n" );
2008 CloseHandle( handle );
2009 HeapFree( GetProcessHeap(), 0, fri );
2010 delete_object( oldpath );
2011 delete_object( newpath );
2013 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
2014 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2015 ok( res != 0, "failed to create temp file\n" );
2016 DeleteFileW( oldpath );
2017 success = CreateDirectoryW( oldpath, NULL );
2018 ok( success != 0, "failed to create temp directory\n" );
2019 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2020 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2022 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2023 ok( res != 0, "failed to create temp file\n" );
2024 DeleteFileW( newpath );
2025 success = CreateDirectoryW( newpath, NULL );
2026 ok( success != 0, "failed to create temp directory\n" );
2027 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2028 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2030 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2031 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2032 fri->Replace = TRUE;
2033 fri->RootDir = NULL;
2034 fri->FileNameLength = name_str.Length;
2035 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2036 pRtlFreeUnicodeString( &name_str );
2038 U(io).Status = 0xdeadbeef;
2039 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2040 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2041 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2042 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2043 ok( !fileDeleted, "file should exist\n" );
2044 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2045 ok( !fileDeleted, "file should exist\n" );
2047 CloseHandle( handle );
2048 CloseHandle( handle2 );
2049 HeapFree( GetProcessHeap(), 0, fri );
2050 delete_object( oldpath );
2051 delete_object( newpath );
2053 /* oldpath is a file, newpath is a directory, Replace = FALSE */
2054 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2055 ok( res != 0, "failed to create temp file\n" );
2056 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2057 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2059 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2060 ok( res != 0, "failed to create temp file\n" );
2061 DeleteFileW( newpath );
2062 success = CreateDirectoryW( newpath, NULL );
2063 ok( success != 0, "failed to create temp directory\n" );
2064 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2065 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2066 fri->Replace = FALSE;
2067 fri->RootDir = NULL;
2068 fri->FileNameLength = name_str.Length;
2069 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2070 pRtlFreeUnicodeString( &name_str );
2072 U(io).Status = 0xdeadbeef;
2073 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2074 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2075 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2076 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2077 ok( !fileDeleted, "file should exist\n" );
2078 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2079 ok( !fileDeleted, "file should exist\n" );
2081 CloseHandle( handle );
2082 HeapFree( GetProcessHeap(), 0, fri );
2083 delete_object( oldpath );
2084 delete_object( newpath );
2086 /* oldpath is a file, newpath is a directory, Replace = TRUE */
2087 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2088 ok( res != 0, "failed to create temp file\n" );
2089 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2090 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2092 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2093 ok( res != 0, "failed to create temp file\n" );
2094 DeleteFileW( newpath );
2095 success = CreateDirectoryW( newpath, NULL );
2096 ok( success != 0, "failed to create temp directory\n" );
2097 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2098 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2099 fri->Replace = TRUE;
2100 fri->RootDir = NULL;
2101 fri->FileNameLength = name_str.Length;
2102 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2103 pRtlFreeUnicodeString( &name_str );
2105 U(io).Status = 0xdeadbeef;
2106 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2107 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2108 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2109 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2110 ok( !fileDeleted, "file should exist\n" );
2111 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2112 ok( !fileDeleted, "file should exist\n" );
2114 CloseHandle( handle );
2115 HeapFree( GetProcessHeap(), 0, fri );
2116 delete_object( oldpath );
2117 delete_object( newpath );
2119 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
2120 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2121 ok( res != 0, "failed to create temp file\n" );
2122 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2123 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2125 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2126 ok( res != 0, "failed to create temp file\n" );
2127 DeleteFileW( newpath );
2128 for (filename = newpath, p = newpath; *p; p++)
2129 if (*p == '\\') filename = p + 1;
2130 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2131 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2133 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2134 fri->Replace = FALSE;
2135 fri->RootDir = handle2;
2136 fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2137 memcpy( fri->FileName, filename, fri->FileNameLength );
2139 U(io).Status = 0xdeadbeef;
2140 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2141 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2142 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2143 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2144 ok( fileDeleted, "file should not exist\n" );
2145 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2146 ok( !fileDeleted, "file should exist\n" );
2148 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2149 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2150 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2151 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2152 todo_wine ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
2153 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
2154 HeapFree( GetProcessHeap(), 0, fni );
2156 CloseHandle( handle );
2157 CloseHandle( handle2 );
2158 HeapFree( GetProcessHeap(), 0, fri );
2159 delete_object( oldpath );
2160 delete_object( newpath );
2163 static void test_file_link_information(void)
2165 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
2166 static const WCHAR fooW[] = {'f','o','o',0};
2167 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
2168 FILE_LINK_INFORMATION *fli;
2169 FILE_NAME_INFORMATION *fni;
2170 BOOL success, fileDeleted;
2171 UNICODE_STRING name_str;
2172 HANDLE handle, handle2;
2173 IO_STATUS_BLOCK io;
2174 NTSTATUS res;
2176 GetTempPathW( MAX_PATH, tmp_path );
2178 /* oldpath is a file, newpath doesn't exist */
2179 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2180 ok( res != 0, "failed to create temp file\n" );
2181 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2182 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2184 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2185 ok( res != 0, "failed to create temp file\n" );
2186 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2187 DeleteFileW( newpath );
2188 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2189 fli->ReplaceIfExists = FALSE;
2190 fli->RootDirectory = NULL;
2191 fli->FileNameLength = name_str.Length;
2192 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2193 pRtlFreeUnicodeString( &name_str );
2195 U(io).Status = 0xdeadbeef;
2196 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2197 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2198 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2199 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2200 ok( !fileDeleted, "file should exist\n" );
2201 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2202 ok( !fileDeleted, "file should exist\n" );
2204 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2205 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2206 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2207 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2208 ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2209 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2210 HeapFree( GetProcessHeap(), 0, fni );
2212 CloseHandle( handle );
2213 HeapFree( GetProcessHeap(), 0, fli );
2214 delete_object( oldpath );
2215 delete_object( newpath );
2217 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2218 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2219 ok( res != 0, "failed to create temp file\n" );
2220 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2221 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2223 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2224 ok( res != 0, "failed to create temp file\n" );
2225 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2226 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2227 fli->ReplaceIfExists = FALSE;
2228 fli->RootDirectory = NULL;
2229 fli->FileNameLength = name_str.Length;
2230 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2231 pRtlFreeUnicodeString( &name_str );
2233 U(io).Status = 0xdeadbeef;
2234 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2235 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2236 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2237 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2238 ok( !fileDeleted, "file should exist\n" );
2239 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2240 ok( !fileDeleted, "file should exist\n" );
2242 CloseHandle( handle );
2243 HeapFree( GetProcessHeap(), 0, fli );
2244 delete_object( oldpath );
2245 delete_object( newpath );
2247 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2248 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2249 ok( res != 0, "failed to create temp file\n" );
2250 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2251 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2253 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2254 ok( res != 0, "failed to create temp file\n" );
2255 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2256 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2257 fli->ReplaceIfExists = TRUE;
2258 fli->RootDirectory = NULL;
2259 fli->FileNameLength = name_str.Length;
2260 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2261 pRtlFreeUnicodeString( &name_str );
2263 U(io).Status = 0xdeadbeef;
2264 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2265 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2266 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2267 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2268 ok( !fileDeleted, "file should exist\n" );
2269 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2270 ok( !fileDeleted, "file should exist\n" );
2272 CloseHandle( handle );
2273 HeapFree( GetProcessHeap(), 0, fli );
2274 delete_object( oldpath );
2275 delete_object( newpath );
2277 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2278 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2279 ok( res != 0, "failed to create temp file\n" );
2280 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2281 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2283 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2284 ok( res != 0, "failed to create temp file\n" );
2285 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2286 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2288 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2289 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2290 fli->ReplaceIfExists = FALSE;
2291 fli->RootDirectory = NULL;
2292 fli->FileNameLength = name_str.Length;
2293 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2294 pRtlFreeUnicodeString( &name_str );
2296 U(io).Status = 0xdeadbeef;
2297 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2298 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2299 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2300 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2301 ok( !fileDeleted, "file should exist\n" );
2302 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2303 ok( !fileDeleted, "file should exist\n" );
2305 CloseHandle( handle );
2306 CloseHandle( handle2 );
2307 HeapFree( GetProcessHeap(), 0, fli );
2308 delete_object( oldpath );
2309 delete_object( newpath );
2311 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2312 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2313 ok( res != 0, "failed to create temp file\n" );
2314 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2315 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2317 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2318 ok( res != 0, "failed to create temp file\n" );
2319 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2320 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2322 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2323 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2324 fli->ReplaceIfExists = TRUE;
2325 fli->RootDirectory = NULL;
2326 fli->FileNameLength = name_str.Length;
2327 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2328 pRtlFreeUnicodeString( &name_str );
2330 U(io).Status = 0xdeadbeef;
2331 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2332 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2333 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2334 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2335 ok( !fileDeleted, "file should exist\n" );
2336 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2337 ok( !fileDeleted, "file should exist\n" );
2339 CloseHandle( handle );
2340 CloseHandle( handle2 );
2341 HeapFree( GetProcessHeap(), 0, fli );
2342 delete_object( oldpath );
2343 delete_object( newpath );
2345 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2346 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2347 ok( res != 0, "failed to create temp file\n" );
2348 DeleteFileW( oldpath );
2349 success = CreateDirectoryW( oldpath, NULL );
2350 ok( success != 0, "failed to create temp directory\n" );
2351 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2352 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2354 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2355 ok( res != 0, "failed to create temp file\n" );
2356 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2357 DeleteFileW( newpath );
2358 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2359 fli->ReplaceIfExists = FALSE;
2360 fli->RootDirectory = NULL;
2361 fli->FileNameLength = name_str.Length;
2362 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2363 pRtlFreeUnicodeString( &name_str );
2365 U(io).Status = 0xdeadbeef;
2366 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2367 todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2368 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2369 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2370 ok( !fileDeleted, "file should exist\n" );
2371 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2372 ok( fileDeleted, "file should not exist\n" );
2374 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2375 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2376 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2377 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2378 ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2379 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2380 HeapFree( GetProcessHeap(), 0, fni );
2382 CloseHandle( handle );
2383 HeapFree( GetProcessHeap(), 0, fli );
2384 delete_object( oldpath );
2385 delete_object( newpath );
2387 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
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 lstrcpyW( newpath, oldpath );
2397 lstrcatW( newpath, foo_txtW );
2398 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2399 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2401 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2402 ok( res != 0, "failed to create temp file\n" );
2403 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2404 DeleteFileW( newpath );
2405 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2406 fli->ReplaceIfExists = FALSE;
2407 fli->RootDirectory = NULL;
2408 fli->FileNameLength = name_str.Length;
2409 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2410 pRtlFreeUnicodeString( &name_str );
2412 U(io).Status = 0xdeadbeef;
2413 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2414 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2415 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2416 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2417 ok( !fileDeleted, "file should exist\n" );
2418 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2419 ok( fileDeleted, "file should not exist\n" );
2421 CloseHandle( handle );
2422 CloseHandle( handle2 );
2423 HeapFree( GetProcessHeap(), 0, fli );
2424 delete_object( oldpath );
2425 delete_object( newpath );
2427 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2428 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2429 ok( res != 0, "failed to create temp file\n" );
2430 DeleteFileW( oldpath );
2431 success = CreateDirectoryW( oldpath, NULL );
2432 ok( success != 0, "failed to create temp directory\n" );
2433 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2434 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2436 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2437 ok( res != 0, "failed to create temp file\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 file, ReplaceIfExists = FALSE, target file opened */
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 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2473 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2475 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2476 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2477 fli->ReplaceIfExists = FALSE;
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_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2487 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2488 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2489 ok( !fileDeleted, "file should exist\n" );
2490 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2491 ok( !fileDeleted, "file should exist\n" );
2493 CloseHandle( handle );
2494 CloseHandle( handle2 );
2495 HeapFree( GetProcessHeap(), 0, fli );
2496 delete_object( oldpath );
2497 delete_object( newpath );
2499 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2500 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2501 ok( res != 0, "failed to create temp file\n" );
2502 DeleteFileW( oldpath );
2503 success = CreateDirectoryW( oldpath, NULL );
2504 ok( success != 0, "failed to create temp directory\n" );
2505 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2506 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2508 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2509 ok( res != 0, "failed to create temp file\n" );
2510 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2511 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2512 fli->ReplaceIfExists = TRUE;
2513 fli->RootDirectory = NULL;
2514 fli->FileNameLength = name_str.Length;
2515 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2516 pRtlFreeUnicodeString( &name_str );
2518 U(io).Status = 0xdeadbeef;
2519 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2520 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2521 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2522 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2523 ok( !fileDeleted, "file should exist\n" );
2524 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2525 ok( !fileDeleted, "file should exist\n" );
2527 CloseHandle( handle );
2528 HeapFree( GetProcessHeap(), 0, fli );
2529 delete_object( oldpath );
2530 delete_object( newpath );
2532 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2533 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2534 ok( res != 0, "failed to create temp file\n" );
2535 DeleteFileW( oldpath );
2536 success = CreateDirectoryW( oldpath, NULL );
2537 ok( success != 0, "failed to create temp directory\n" );
2538 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2539 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2541 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2542 ok( res != 0, "failed to create temp file\n" );
2543 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2544 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2546 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2547 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2548 fli->ReplaceIfExists = TRUE;
2549 fli->RootDirectory = NULL;
2550 fli->FileNameLength = name_str.Length;
2551 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2552 pRtlFreeUnicodeString( &name_str );
2554 U(io).Status = 0xdeadbeef;
2555 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2556 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2557 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2558 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2559 ok( !fileDeleted, "file should exist\n" );
2560 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2561 ok( !fileDeleted, "file should exist\n" );
2563 CloseHandle( handle );
2564 CloseHandle( handle2 );
2565 HeapFree( GetProcessHeap(), 0, fli );
2566 delete_object( oldpath );
2567 delete_object( newpath );
2569 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2570 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2571 ok( res != 0, "failed to create temp file\n" );
2572 DeleteFileW( oldpath );
2573 success = CreateDirectoryW( oldpath, NULL );
2574 ok( success != 0, "failed to create temp directory\n" );
2575 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2576 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2578 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2579 ok( res != 0, "failed to create temp file\n" );
2580 DeleteFileW( newpath );
2581 success = CreateDirectoryW( newpath, NULL );
2582 ok( success != 0, "failed to create temp directory\n" );
2583 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2584 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2585 fli->ReplaceIfExists = FALSE;
2586 fli->RootDirectory = NULL;
2587 fli->FileNameLength = name_str.Length;
2588 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2589 pRtlFreeUnicodeString( &name_str );
2591 U(io).Status = 0xdeadbeef;
2592 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2593 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2594 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2595 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2596 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2597 ok( !fileDeleted, "file should exist\n" );
2598 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2599 ok( !fileDeleted, "file should exist\n" );
2601 CloseHandle( handle );
2602 HeapFree( GetProcessHeap(), 0, fli );
2603 delete_object( oldpath );
2604 delete_object( newpath );
2606 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2607 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2608 ok( res != 0, "failed to create temp file\n" );
2609 DeleteFileW( oldpath );
2610 success = CreateDirectoryW( oldpath, NULL );
2611 ok( success != 0, "failed to create temp directory\n" );
2612 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2613 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2615 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2616 ok( res != 0, "failed to create temp file\n" );
2617 DeleteFileW( newpath );
2618 success = CreateDirectoryW( newpath, NULL );
2619 ok( success != 0, "failed to create temp directory\n" );
2620 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2621 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2622 fli->ReplaceIfExists = TRUE;
2623 fli->RootDirectory = NULL;
2624 fli->FileNameLength = name_str.Length;
2625 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2626 pRtlFreeUnicodeString( &name_str );
2628 U(io).Status = 0xdeadbeef;
2629 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2630 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2631 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2632 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2633 ok( !fileDeleted, "file should exist\n" );
2634 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2635 ok( !fileDeleted, "file should exist\n" );
2637 CloseHandle( handle );
2638 HeapFree( GetProcessHeap(), 0, fli );
2639 delete_object( oldpath );
2640 delete_object( newpath );
2642 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2643 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2644 ok( res != 0, "failed to create temp file\n" );
2645 DeleteFileW( oldpath );
2646 success = CreateDirectoryW( oldpath, NULL );
2647 ok( success != 0, "failed to create temp directory\n" );
2648 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2649 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2651 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2652 ok( res != 0, "failed to create temp file\n" );
2653 DeleteFileW( newpath );
2654 success = CreateDirectoryW( newpath, NULL );
2655 ok( success != 0, "failed to create temp directory\n" );
2656 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2657 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2659 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2660 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2661 fli->ReplaceIfExists = TRUE;
2662 fli->RootDirectory = NULL;
2663 fli->FileNameLength = name_str.Length;
2664 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2665 pRtlFreeUnicodeString( &name_str );
2667 U(io).Status = 0xdeadbeef;
2668 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2669 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2670 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2671 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2672 ok( !fileDeleted, "file should exist\n" );
2673 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2674 ok( !fileDeleted, "file should exist\n" );
2676 CloseHandle( handle );
2677 CloseHandle( handle2 );
2678 HeapFree( GetProcessHeap(), 0, fli );
2679 delete_object( oldpath );
2680 delete_object( newpath );
2682 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2683 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2684 ok( res != 0, "failed to create temp file\n" );
2685 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2686 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2688 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2689 ok( res != 0, "failed to create temp file\n" );
2690 DeleteFileW( newpath );
2691 success = CreateDirectoryW( newpath, NULL );
2692 ok( success != 0, "failed to create temp directory\n" );
2693 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2694 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2695 fli->ReplaceIfExists = FALSE;
2696 fli->RootDirectory = NULL;
2697 fli->FileNameLength = name_str.Length;
2698 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2699 pRtlFreeUnicodeString( &name_str );
2701 U(io).Status = 0xdeadbeef;
2702 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2703 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2704 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2705 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2706 ok( !fileDeleted, "file should exist\n" );
2707 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2708 ok( !fileDeleted, "file should exist\n" );
2710 CloseHandle( handle );
2711 HeapFree( GetProcessHeap(), 0, fli );
2712 delete_object( oldpath );
2713 delete_object( newpath );
2715 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2716 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2717 ok( res != 0, "failed to create temp file\n" );
2718 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2719 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2721 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2722 ok( res != 0, "failed to create temp file\n" );
2723 DeleteFileW( newpath );
2724 success = CreateDirectoryW( newpath, NULL );
2725 ok( success != 0, "failed to create temp directory\n" );
2726 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2727 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2728 fli->ReplaceIfExists = TRUE;
2729 fli->RootDirectory = NULL;
2730 fli->FileNameLength = name_str.Length;
2731 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2732 pRtlFreeUnicodeString( &name_str );
2734 U(io).Status = 0xdeadbeef;
2735 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2736 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2737 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2738 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2739 ok( !fileDeleted, "file should exist\n" );
2740 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2741 ok( !fileDeleted, "file should exist\n" );
2743 CloseHandle( handle );
2744 HeapFree( GetProcessHeap(), 0, fli );
2745 delete_object( oldpath );
2746 delete_object( newpath );
2748 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2749 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2750 ok( res != 0, "failed to create temp file\n" );
2751 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2752 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2754 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2755 ok( res != 0, "failed to create temp file\n" );
2756 DeleteFileW( newpath );
2757 for (filename = newpath, p = newpath; *p; p++)
2758 if (*p == '\\') filename = p + 1;
2759 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2760 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2762 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2763 fli->ReplaceIfExists = FALSE;
2764 fli->RootDirectory = handle2;
2765 fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2766 memcpy( fli->FileName, filename, fli->FileNameLength );
2768 U(io).Status = 0xdeadbeef;
2769 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2770 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2771 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2772 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2773 ok( !fileDeleted, "file should exist\n" );
2774 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2775 ok( !fileDeleted, "file should exist\n" );
2777 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2778 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2779 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2780 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2781 ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2782 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2783 HeapFree( GetProcessHeap(), 0, fni );
2785 CloseHandle( handle );
2786 CloseHandle( handle2 );
2787 HeapFree( GetProcessHeap(), 0, fli );
2788 delete_object( oldpath );
2789 delete_object( newpath );
2792 static void test_file_both_information(void)
2794 IO_STATUS_BLOCK io;
2795 FILE_BOTH_DIR_INFORMATION fbi;
2796 HANDLE h;
2797 int res;
2799 if (!(h = create_temp_file(0))) return;
2801 memset(&fbi, 0, sizeof(fbi));
2802 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
2803 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
2805 CloseHandle( h );
2808 static void test_file_disposition_information(void)
2810 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
2811 DWORD dirpos;
2812 HANDLE handle, handle2;
2813 NTSTATUS res;
2814 IO_STATUS_BLOCK io;
2815 FILE_DISPOSITION_INFORMATION fdi;
2816 BOOL fileDeleted;
2817 DWORD fdi2;
2819 GetTempPathA( MAX_PATH, tmp_path );
2821 /* tests for info struct size */
2822 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2823 handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2824 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2825 res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
2826 todo_wine
2827 ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %x\n", res );
2828 fdi2 = 0x100;
2829 res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
2830 ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x\n", res );
2831 CloseHandle( handle );
2832 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2833 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2834 DeleteFileA( buffer );
2836 /* cannot set disposition on file not opened with delete access */
2837 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2838 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2839 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2840 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2841 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
2842 fdi.DoDeleteFile = TRUE;
2843 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2844 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
2845 CloseHandle( handle );
2846 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2847 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2848 DeleteFileA( buffer );
2850 /* can set disposition on file opened with proper access */
2851 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2852 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2853 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2854 fdi.DoDeleteFile = TRUE;
2855 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2856 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2857 CloseHandle( handle );
2858 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2859 ok( fileDeleted, "File should have been deleted\n" );
2860 DeleteFileA( buffer );
2862 /* cannot set disposition on readonly file */
2863 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2864 DeleteFileA( buffer );
2865 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2866 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2867 fdi.DoDeleteFile = TRUE;
2868 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2869 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2870 CloseHandle( handle );
2871 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2872 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2873 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2874 DeleteFileA( buffer );
2876 /* cannot set disposition on readonly file */
2877 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2878 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2879 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2880 fdi.DoDeleteFile = TRUE;
2881 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2882 todo_wine
2883 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2884 CloseHandle( handle );
2885 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2886 todo_wine
2887 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2888 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2889 DeleteFileA( buffer );
2891 /* can set disposition on file and then reset it */
2892 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2893 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2894 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2895 fdi.DoDeleteFile = TRUE;
2896 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2897 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2898 fdi.DoDeleteFile = FALSE;
2899 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2900 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2901 CloseHandle( handle );
2902 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2903 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2904 DeleteFileA( buffer );
2906 /* Delete-on-close flag doesn't change file disposition until a handle is closed */
2907 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2908 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2909 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2910 fdi.DoDeleteFile = FALSE;
2911 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2912 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2913 CloseHandle( handle );
2914 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2915 ok( fileDeleted, "File should have been deleted\n" );
2916 DeleteFileA( buffer );
2918 /* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
2919 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2920 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2921 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2922 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
2923 CloseHandle( handle );
2924 fdi.DoDeleteFile = FALSE;
2925 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
2926 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2927 CloseHandle( handle2 );
2928 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2929 ok( fileDeleted, "File should have been deleted\n" );
2930 DeleteFileA( buffer );
2932 /* can set disposition on a directory opened with proper access */
2933 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2934 DeleteFileA( buffer );
2935 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2936 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2937 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2938 fdi.DoDeleteFile = TRUE;
2939 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2940 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2941 CloseHandle( handle );
2942 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2943 ok( fileDeleted, "Directory should have been deleted\n" );
2944 RemoveDirectoryA( buffer );
2946 /* RemoveDirectory sets directory disposition and it can be undone */
2947 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2948 DeleteFileA( buffer );
2949 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2950 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2951 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2952 RemoveDirectoryA( buffer );
2953 fdi.DoDeleteFile = FALSE;
2954 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2955 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2956 CloseHandle( handle );
2957 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2958 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2959 RemoveDirectoryA( buffer );
2961 /* cannot set disposition on a non-empty directory */
2962 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2963 DeleteFileA( buffer );
2964 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2965 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2966 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2967 dirpos = lstrlenA( buffer );
2968 lstrcpyA( buffer + dirpos, "\\tst" );
2969 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2970 CloseHandle( handle2 );
2971 fdi.DoDeleteFile = TRUE;
2972 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2973 todo_wine
2974 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
2975 DeleteFileA( buffer );
2976 buffer[dirpos] = '\0';
2977 CloseHandle( handle );
2978 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2979 todo_wine
2980 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2981 RemoveDirectoryA( buffer );
2984 static void test_iocompletion(void)
2986 HANDLE h = INVALID_HANDLE_VALUE;
2987 NTSTATUS res;
2989 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
2991 ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
2992 ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
2994 if ( h && h != INVALID_HANDLE_VALUE)
2996 test_iocp_setcompletion(h);
2997 test_iocp_fileio(h);
2998 pNtClose(h);
3002 static void test_file_name_information(void)
3004 WCHAR *file_name, *volume_prefix, *expected;
3005 FILE_NAME_INFORMATION *info;
3006 ULONG old_redir = 1, tmp;
3007 UINT file_name_size;
3008 IO_STATUS_BLOCK io;
3009 UINT info_size;
3010 HRESULT hr;
3011 HANDLE h;
3012 UINT len;
3014 /* GetVolumePathName is not present before w2k */
3015 if (!pGetVolumePathNameW) {
3016 win_skip("GetVolumePathNameW not found\n");
3017 return;
3020 file_name_size = GetSystemDirectoryW( NULL, 0 );
3021 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3022 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3023 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3025 len = GetSystemDirectoryW( file_name, file_name_size );
3026 ok(len == file_name_size - 1,
3027 "GetSystemDirectoryW returned %u, expected %u.\n",
3028 len, file_name_size - 1);
3030 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3031 ok(len, "GetVolumePathNameW failed.\n");
3033 len = lstrlenW( volume_prefix );
3034 if (len && volume_prefix[len - 1] == '\\') --len;
3035 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3036 expected[file_name_size - len - 1] = '\0';
3038 /* A bit more than we actually need, but it keeps the calculation simple. */
3039 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3040 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3042 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3043 h = CreateFileW( file_name, GENERIC_READ,
3044 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3045 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3046 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3047 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3049 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
3050 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
3052 memset( info, 0xcc, info_size );
3053 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
3054 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3055 hr, STATUS_BUFFER_OVERFLOW);
3056 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3057 U(io).Status, STATUS_BUFFER_OVERFLOW);
3058 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
3059 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
3060 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3061 "info->FileName[1] is %p, expected %p.\n",
3062 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3063 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3065 memset( info, 0xcc, info_size );
3066 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3067 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3068 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3069 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
3070 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
3071 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
3072 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3073 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3074 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3075 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
3076 "io.Information is %lu, expected %u.\n",
3077 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
3079 CloseHandle( h );
3080 HeapFree( GetProcessHeap(), 0, info );
3081 HeapFree( GetProcessHeap(), 0, expected );
3082 HeapFree( GetProcessHeap(), 0, volume_prefix );
3084 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3086 skip("Not running on WoW64, skipping test.\n");
3087 HeapFree( GetProcessHeap(), 0, file_name );
3088 return;
3091 h = CreateFileW( file_name, GENERIC_READ,
3092 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3093 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3094 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3095 HeapFree( GetProcessHeap(), 0, file_name );
3097 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3098 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3099 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3101 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3102 ok(len == file_name_size - 1,
3103 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3104 len, file_name_size - 1);
3106 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3107 ok(len, "GetVolumePathNameW failed.\n");
3109 len = lstrlenW( volume_prefix );
3110 if (len && volume_prefix[len - 1] == '\\') --len;
3111 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3112 expected[file_name_size - len - 1] = '\0';
3114 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3115 info = HeapAlloc( GetProcessHeap(), 0, info_size );
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 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3121 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3122 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3124 CloseHandle( h );
3125 HeapFree( GetProcessHeap(), 0, info );
3126 HeapFree( GetProcessHeap(), 0, expected );
3127 HeapFree( GetProcessHeap(), 0, volume_prefix );
3128 HeapFree( GetProcessHeap(), 0, file_name );
3131 static void test_file_all_name_information(void)
3133 WCHAR *file_name, *volume_prefix, *expected;
3134 FILE_ALL_INFORMATION *info;
3135 ULONG old_redir = 1, tmp;
3136 UINT file_name_size;
3137 IO_STATUS_BLOCK io;
3138 UINT info_size;
3139 HRESULT hr;
3140 HANDLE h;
3141 UINT len;
3143 /* GetVolumePathName is not present before w2k */
3144 if (!pGetVolumePathNameW) {
3145 win_skip("GetVolumePathNameW not found\n");
3146 return;
3149 file_name_size = GetSystemDirectoryW( NULL, 0 );
3150 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3151 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3152 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3154 len = GetSystemDirectoryW( file_name, file_name_size );
3155 ok(len == file_name_size - 1,
3156 "GetSystemDirectoryW returned %u, expected %u.\n",
3157 len, file_name_size - 1);
3159 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3160 ok(len, "GetVolumePathNameW failed.\n");
3162 len = lstrlenW( volume_prefix );
3163 if (len && volume_prefix[len - 1] == '\\') --len;
3164 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3165 expected[file_name_size - len - 1] = '\0';
3167 /* A bit more than we actually need, but it keeps the calculation simple. */
3168 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3169 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3171 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3172 h = CreateFileW( file_name, GENERIC_READ,
3173 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3174 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3175 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3176 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3178 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
3179 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
3180 hr, STATUS_INFO_LENGTH_MISMATCH);
3182 memset( info, 0xcc, info_size );
3183 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
3184 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3185 hr, STATUS_BUFFER_OVERFLOW);
3186 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3187 U(io).Status, STATUS_BUFFER_OVERFLOW);
3188 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3189 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3190 ok(info->NameInformation.FileName[2] == 0xcccc,
3191 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
3192 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3193 "info->NameInformation.FileName[1] is %p, expected %p.\n",
3194 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3195 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3197 memset( info, 0xcc, info_size );
3198 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3199 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3200 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3201 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3202 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3203 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
3204 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3205 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
3206 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3207 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
3208 "info->NameInformation.FileName is %s, expected %s.\n",
3209 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3210 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
3211 + info->NameInformation.FileNameLength,
3212 "io.Information is %lu\n", io.Information );
3214 CloseHandle( h );
3215 HeapFree( GetProcessHeap(), 0, info );
3216 HeapFree( GetProcessHeap(), 0, expected );
3217 HeapFree( GetProcessHeap(), 0, volume_prefix );
3219 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3221 skip("Not running on WoW64, skipping test.\n");
3222 HeapFree( GetProcessHeap(), 0, file_name );
3223 return;
3226 h = CreateFileW( file_name, GENERIC_READ,
3227 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3228 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3229 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3230 HeapFree( GetProcessHeap(), 0, file_name );
3232 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3233 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3234 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3236 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3237 ok(len == file_name_size - 1,
3238 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3239 len, file_name_size - 1);
3241 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3242 ok(len, "GetVolumePathNameW failed.\n");
3244 len = lstrlenW( volume_prefix );
3245 if (len && volume_prefix[len - 1] == '\\') --len;
3246 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3247 expected[file_name_size - len - 1] = '\0';
3249 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3250 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3252 memset( info, 0xcc, info_size );
3253 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3254 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3255 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3256 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
3257 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3259 CloseHandle( h );
3260 HeapFree( GetProcessHeap(), 0, info );
3261 HeapFree( GetProcessHeap(), 0, expected );
3262 HeapFree( GetProcessHeap(), 0, volume_prefix );
3263 HeapFree( GetProcessHeap(), 0, file_name );
3266 static void test_query_volume_information_file(void)
3268 NTSTATUS status;
3269 HANDLE dir;
3270 WCHAR path[MAX_PATH];
3271 OBJECT_ATTRIBUTES attr;
3272 IO_STATUS_BLOCK io;
3273 UNICODE_STRING nameW;
3274 FILE_FS_VOLUME_INFORMATION *ffvi;
3275 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3277 GetWindowsDirectoryW( path, MAX_PATH );
3278 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3279 attr.Length = sizeof(attr);
3280 attr.RootDirectory = 0;
3281 attr.ObjectName = &nameW;
3282 attr.Attributes = OBJ_CASE_INSENSITIVE;
3283 attr.SecurityDescriptor = NULL;
3284 attr.SecurityQualityOfService = NULL;
3286 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3287 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3288 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3289 pRtlFreeUnicodeString( &nameW );
3291 ZeroMemory( buf, sizeof(buf) );
3292 U(io).Status = 0xdadadada;
3293 io.Information = 0xcacacaca;
3295 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
3297 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
3299 todo_wine
3301 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3302 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3304 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3305 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3306 io.Information);
3308 ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
3309 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
3310 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
3312 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
3314 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
3316 CloseHandle( dir );
3319 static void test_query_attribute_information_file(void)
3321 NTSTATUS status;
3322 HANDLE dir;
3323 WCHAR path[MAX_PATH];
3324 OBJECT_ATTRIBUTES attr;
3325 IO_STATUS_BLOCK io;
3326 UNICODE_STRING nameW;
3327 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
3328 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3330 GetWindowsDirectoryW( path, MAX_PATH );
3331 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3332 attr.Length = sizeof(attr);
3333 attr.RootDirectory = 0;
3334 attr.ObjectName = &nameW;
3335 attr.Attributes = OBJ_CASE_INSENSITIVE;
3336 attr.SecurityDescriptor = NULL;
3337 attr.SecurityQualityOfService = NULL;
3339 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3340 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3341 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3342 pRtlFreeUnicodeString( &nameW );
3344 ZeroMemory( buf, sizeof(buf) );
3345 U(io).Status = 0xdadadada;
3346 io.Information = 0xcacacaca;
3348 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
3350 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
3352 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3353 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3354 ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
3355 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
3356 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
3358 trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
3359 ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
3360 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
3362 CloseHandle( dir );
3365 static void test_NtCreateFile(void)
3367 static const struct test_data
3369 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
3370 } td[] =
3372 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3373 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
3374 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3375 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3376 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3377 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3378 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3379 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3380 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3381 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3382 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3383 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3384 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3385 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3386 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3387 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3388 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3389 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
3390 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
3392 static const WCHAR fooW[] = {'f','o','o',0};
3393 NTSTATUS status;
3394 HANDLE handle;
3395 WCHAR path[MAX_PATH];
3396 OBJECT_ATTRIBUTES attr;
3397 IO_STATUS_BLOCK io;
3398 UNICODE_STRING nameW;
3399 DWORD ret, i;
3401 GetTempPathW(MAX_PATH, path);
3402 GetTempFileNameW(path, fooW, 0, path);
3403 DeleteFileW(path);
3404 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
3406 attr.Length = sizeof(attr);
3407 attr.RootDirectory = NULL;
3408 attr.ObjectName = &nameW;
3409 attr.Attributes = OBJ_CASE_INSENSITIVE;
3410 attr.SecurityDescriptor = NULL;
3411 attr.SecurityQualityOfService = NULL;
3413 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3415 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
3416 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
3417 td[i].disposition, 0, NULL, 0);
3419 ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
3421 if (!status)
3423 ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
3425 ret = GetFileAttributesW(path);
3426 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
3427 /* FIXME: leave only 'else' case below once Wine is fixed */
3428 if (ret != td[i].attrib_out)
3430 todo_wine
3431 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3432 SetFileAttributesW(path, td[i].attrib_out);
3434 else
3435 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3437 CloseHandle(handle);
3440 if (td[i].needs_cleanup)
3442 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3443 DeleteFileW(path);
3447 pRtlFreeUnicodeString( &nameW );
3448 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3449 DeleteFileW( path );
3452 static void test_read_write(void)
3454 static const char contents[14] = "1234567890abcd";
3455 char buf[256];
3456 HANDLE hfile;
3457 OVERLAPPED ovl;
3458 IO_STATUS_BLOCK iob;
3459 DWORD ret, bytes, status, off;
3460 LARGE_INTEGER offset;
3461 LONG i;
3463 U(iob).Status = -1;
3464 iob.Information = -1;
3465 offset.QuadPart = 0;
3466 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3467 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3468 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3469 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3471 U(iob).Status = -1;
3472 iob.Information = -1;
3473 offset.QuadPart = 0;
3474 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3475 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3476 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3477 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3479 hfile = create_temp_file(0);
3480 if (!hfile) return;
3482 U(iob).Status = -1;
3483 iob.Information = -1;
3484 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3485 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3486 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3487 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3489 U(iob).Status = -1;
3490 iob.Information = -1;
3491 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3492 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3493 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3494 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3496 U(iob).Status = -1;
3497 iob.Information = -1;
3498 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
3499 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3500 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3501 ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
3503 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3505 U(iob).Status = -1;
3506 iob.Information = -1;
3507 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
3508 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
3509 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3510 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3511 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
3513 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3514 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3516 bytes = 0xdeadbeef;
3517 SetLastError(0xdeadbeef);
3518 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
3519 ok(!ret, "ReadFile should fail\n");
3520 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3521 ok(bytes == 0, "bytes %u\n", bytes);
3523 bytes = 0xdeadbeef;
3524 SetLastError(0xdeadbeef);
3525 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3526 ok(ret, "ReadFile error %d\n", GetLastError());
3527 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3528 ok(bytes == 0, "bytes %u\n", bytes);
3530 bytes = 0xdeadbeef;
3531 SetLastError(0xdeadbeef);
3532 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3533 ok(ret, "ReadFile error %d\n", GetLastError());
3534 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3535 ok(bytes == 0, "bytes %u\n", bytes);
3537 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3539 bytes = 0;
3540 SetLastError(0xdeadbeef);
3541 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3542 ok(ret, "ReadFile error %d\n", GetLastError());
3543 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3544 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3546 for (i = -20; i < -1; i++)
3548 if (i == -2) continue;
3550 U(iob).Status = -1;
3551 iob.Information = -1;
3552 offset.QuadPart = (LONGLONG)i;
3553 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3554 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3555 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3556 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3559 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
3561 U(iob).Status = -1;
3562 iob.Information = -1;
3563 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3564 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3565 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3566 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3567 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3569 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3570 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3572 U(iob).Status = -1;
3573 iob.Information = -1;
3574 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3575 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3576 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3577 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3579 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3581 bytes = 0;
3582 SetLastError(0xdeadbeef);
3583 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3584 ok(ret, "ReadFile error %d\n", GetLastError());
3585 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3586 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3587 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3589 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3590 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3592 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3594 bytes = 0;
3595 SetLastError(0xdeadbeef);
3596 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
3597 ok(ret, "WriteFile error %d\n", GetLastError());
3598 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3600 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3601 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3603 /* test reading beyond EOF */
3604 bytes = -1;
3605 SetLastError(0xdeadbeef);
3606 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3607 ok(ret, "ReadFile error %d\n", GetLastError());
3608 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3609 ok(bytes == 0, "bytes %u\n", bytes);
3611 bytes = -1;
3612 SetLastError(0xdeadbeef);
3613 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3614 ok(ret, "ReadFile error %d\n", GetLastError());
3615 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3616 ok(bytes == 0, "bytes %u\n", bytes);
3618 bytes = -1;
3619 SetLastError(0xdeadbeef);
3620 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
3621 ok(ret, "ReadFile error %d\n", GetLastError());
3622 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3623 ok(bytes == 0, "bytes %u\n", bytes);
3625 S(U(ovl)).Offset = sizeof(contents);
3626 S(U(ovl)).OffsetHigh = 0;
3627 ovl.Internal = -1;
3628 ovl.InternalHigh = -1;
3629 ovl.hEvent = 0;
3630 bytes = -1;
3631 SetLastError(0xdeadbeef);
3632 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3633 ok(!ret, "ReadFile should fail\n");
3634 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
3635 ok(bytes == 0, "bytes %u\n", bytes);
3636 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
3637 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3639 S(U(ovl)).Offset = sizeof(contents);
3640 S(U(ovl)).OffsetHigh = 0;
3641 ovl.Internal = -1;
3642 ovl.InternalHigh = -1;
3643 ovl.hEvent = 0;
3644 bytes = -1;
3645 SetLastError(0xdeadbeef);
3646 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
3647 ok(ret, "ReadFile error %d\n", GetLastError());
3648 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3649 ok(bytes == 0, "bytes %u\n", bytes);
3650 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3651 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3653 U(iob).Status = -1;
3654 iob.Information = -1;
3655 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3656 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3657 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3658 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3660 U(iob).Status = -1;
3661 iob.Information = -1;
3662 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
3663 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3664 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3665 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3667 U(iob).Status = -1;
3668 iob.Information = -1;
3669 offset.QuadPart = sizeof(contents);
3670 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3671 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3672 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3673 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3675 U(iob).Status = -1;
3676 iob.Information = -1;
3677 offset.QuadPart = sizeof(contents);
3678 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3679 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3680 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3681 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3683 U(iob).Status = -1;
3684 iob.Information = -1;
3685 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3686 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3687 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3688 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3689 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3691 U(iob).Status = -1;
3692 iob.Information = -1;
3693 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3694 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3695 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3696 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3697 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3699 for (i = -20; i < 0; i++)
3701 if (i == -2) continue;
3703 U(iob).Status = -1;
3704 iob.Information = -1;
3705 offset.QuadPart = (LONGLONG)i;
3706 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3707 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3708 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3709 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3712 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3714 bytes = 0;
3715 SetLastError(0xdeadbeef);
3716 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3717 ok(ret, "ReadFile error %d\n", GetLastError());
3718 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3719 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3721 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3722 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3724 U(iob).Status = -1;
3725 iob.Information = -1;
3726 offset.QuadPart = 0;
3727 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3728 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3729 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3730 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3731 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3733 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3734 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3736 U(iob).Status = -1;
3737 iob.Information = -1;
3738 offset.QuadPart = sizeof(contents) - 4;
3739 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3740 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3741 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3742 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3744 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3745 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3747 U(iob).Status = -1;
3748 iob.Information = -1;
3749 offset.QuadPart = 0;
3750 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3751 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3752 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3753 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3754 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3755 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3757 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3758 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3760 S(U(ovl)).Offset = sizeof(contents) - 4;
3761 S(U(ovl)).OffsetHigh = 0;
3762 ovl.hEvent = 0;
3763 bytes = 0;
3764 SetLastError(0xdeadbeef);
3765 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
3766 ok(ret, "WriteFile error %d\n", GetLastError());
3767 ok(bytes == 4, "bytes %u\n", bytes);
3769 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3770 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3772 S(U(ovl)).Offset = 0;
3773 S(U(ovl)).OffsetHigh = 0;
3774 ovl.Internal = -1;
3775 ovl.InternalHigh = -1;
3776 ovl.hEvent = 0;
3777 bytes = 0;
3778 SetLastError(0xdeadbeef);
3779 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3780 ok(ret, "ReadFile error %d\n", GetLastError());
3781 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3782 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3783 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
3784 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3785 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
3787 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3788 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3790 CloseHandle(hfile);
3792 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
3793 if (!hfile) return;
3795 bytes = 0xdeadbeef;
3796 SetLastError(0xdeadbeef);
3797 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
3798 ok(!ret, "ReadFile should fail\n");
3799 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3800 ok(bytes == 0, "bytes %u\n", bytes);
3802 S(U(ovl)).Offset = 0;
3803 S(U(ovl)).OffsetHigh = 0;
3804 ovl.Internal = -1;
3805 ovl.InternalHigh = -1;
3806 ovl.hEvent = 0;
3807 bytes = 0xdeadbeef;
3808 SetLastError(0xdeadbeef);
3809 /* ReadFile return value depends on Windows version and testing it is not practical */
3810 ReadFile(hfile, buf, 0, &bytes, &ovl);
3811 ok(bytes == 0, "bytes %u\n", bytes);
3812 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3813 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3815 bytes = 0xdeadbeef;
3816 SetLastError(0xdeadbeef);
3817 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
3818 ok(!ret, "WriteFile should fail\n");
3819 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3820 ok(bytes == 0, "bytes %u\n", bytes);
3822 U(iob).Status = -1;
3823 iob.Information = -1;
3824 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
3825 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
3826 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3827 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3829 for (i = -20; i < -1; i++)
3831 U(iob).Status = -1;
3832 iob.Information = -1;
3833 offset.QuadPart = (LONGLONG)i;
3834 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3835 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3836 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3837 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3840 U(iob).Status = -1;
3841 iob.Information = -1;
3842 offset.QuadPart = 0;
3843 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3844 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
3845 if (status == STATUS_PENDING)
3847 ret = WaitForSingleObject(hfile, 3000);
3848 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
3850 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3851 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3853 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3854 ok(off == 0, "expected 0, got %u\n", off);
3856 bytes = 0xdeadbeef;
3857 SetLastError(0xdeadbeef);
3858 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3859 ok(!ret, "ReadFile should fail\n");
3860 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3861 ok(bytes == 0, "bytes %u\n", bytes);
3863 U(iob).Status = -1;
3864 iob.Information = -1;
3865 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3866 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
3867 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3868 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3870 for (i = -20; i < 0; i++)
3872 U(iob).Status = -1;
3873 iob.Information = -1;
3874 offset.QuadPart = (LONGLONG)i;
3875 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3876 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3877 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3878 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3881 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3882 ok(off == 0, "expected 0, got %u\n", off);
3884 /* test reading beyond EOF */
3885 offset.QuadPart = sizeof(contents);
3886 S(U(ovl)).Offset = offset.u.LowPart;
3887 S(U(ovl)).OffsetHigh = offset.u.HighPart;
3888 ovl.Internal = -1;
3889 ovl.InternalHigh = -1;
3890 ovl.hEvent = 0;
3891 bytes = 0xdeadbeef;
3892 SetLastError(0xdeadbeef);
3893 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3894 ok(!ret, "ReadFile should fail\n");
3895 ret = GetLastError();
3896 ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
3897 ok(bytes == 0, "bytes %u\n", bytes);
3899 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3900 ok(off == 0, "expected 0, got %u\n", off);
3902 if (ret == ERROR_IO_PENDING)
3904 bytes = 0xdeadbeef;
3905 SetLastError(0xdeadbeef);
3906 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
3907 ok(!ret, "GetOverlappedResult should report FALSE\n");
3908 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
3909 ok(bytes == 0, "expected 0, read %u\n", bytes);
3910 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
3911 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3914 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3915 ok(off == 0, "expected 0, got %u\n", off);
3917 offset.QuadPart = sizeof(contents);
3918 S(U(ovl)).Offset = offset.u.LowPart;
3919 S(U(ovl)).OffsetHigh = offset.u.HighPart;
3920 ovl.Internal = -1;
3921 ovl.InternalHigh = -1;
3922 ovl.hEvent = 0;
3923 bytes = 0xdeadbeef;
3924 SetLastError(0xdeadbeef);
3925 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
3926 /* ReadFile return value depends on Windows version and testing it is not practical */
3927 if (!ret)
3928 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
3929 ret = GetLastError();
3930 ok(bytes == 0, "bytes %u\n", bytes);
3932 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3933 ok(off == 0, "expected 0, got %u\n", off);
3935 if (ret == ERROR_IO_PENDING)
3937 bytes = 0xdeadbeef;
3938 SetLastError(0xdeadbeef);
3939 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
3940 ok(ret, "GetOverlappedResult should report TRUE\n");
3941 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3942 ok(bytes == 0, "expected 0, read %u\n", bytes);
3943 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3944 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3947 offset.QuadPart = sizeof(contents);
3948 S(U(ovl)).Offset = offset.u.LowPart;
3949 S(U(ovl)).OffsetHigh = offset.u.HighPart;
3950 ovl.Internal = -1;
3951 ovl.InternalHigh = -1;
3952 ovl.hEvent = 0;
3953 bytes = 0xdeadbeef;
3954 SetLastError(0xdeadbeef);
3955 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
3956 /* ReadFile return value depends on Windows version and testing it is not practical */
3957 if (!ret)
3958 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
3959 ret = GetLastError();
3960 ok(bytes == 0, "bytes %u\n", bytes);
3962 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3963 ok(off == 0, "expected 0, got %u\n", off);
3965 if (ret == ERROR_IO_PENDING)
3967 bytes = 0xdeadbeef;
3968 SetLastError(0xdeadbeef);
3969 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
3970 ok(ret, "GetOverlappedResult should report TRUE\n");
3971 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3972 ok(bytes == 0, "expected 0, read %u\n", bytes);
3973 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3974 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3977 U(iob).Status = -1;
3978 iob.Information = -1;
3979 offset.QuadPart = sizeof(contents);
3980 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3981 if (status == STATUS_PENDING)
3983 ret = WaitForSingleObject(hfile, 3000);
3984 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
3985 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3986 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3988 else
3990 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3991 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3992 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3995 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3996 ok(off == 0, "expected 0, got %u\n", off);
3998 U(iob).Status = -1;
3999 iob.Information = -1;
4000 offset.QuadPart = sizeof(contents);
4001 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4002 if (status == STATUS_PENDING)
4004 ret = WaitForSingleObject(hfile, 3000);
4005 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4006 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4007 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4009 else
4011 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
4012 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4013 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4016 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4017 ok(off == 0, "expected 0, got %u\n", off);
4019 S(U(ovl)).Offset = 0;
4020 S(U(ovl)).OffsetHigh = 0;
4021 ovl.Internal = -1;
4022 ovl.InternalHigh = -1;
4023 ovl.hEvent = 0;
4024 bytes = 0;
4025 SetLastError(0xdeadbeef);
4026 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4027 /* ReadFile return value depends on Windows version and testing it is not practical */
4028 if (!ret)
4030 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4031 ok(bytes == 0, "bytes %u\n", bytes);
4033 else ok(bytes == 14, "bytes %u\n", bytes);
4034 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4035 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4037 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4038 ok(off == 0, "expected 0, got %u\n", off);
4040 bytes = 0xdeadbeef;
4041 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4042 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4043 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4044 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4045 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4046 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4048 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4049 ok(off == 0, "expected 0, got %u\n", off);
4051 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4052 SetEndOfFile(hfile);
4053 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4055 U(iob).Status = -1;
4056 iob.Information = -1;
4057 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4058 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4059 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4060 if (status == STATUS_PENDING)
4062 ret = WaitForSingleObject(hfile, 3000);
4063 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4065 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4066 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
4068 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4069 ok(off == 0, "expected 0, got %u\n", off);
4071 U(iob).Status = -1;
4072 iob.Information = -1;
4073 offset.QuadPart = 0;
4074 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4075 ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4076 if (status == STATUS_PENDING)
4078 ret = WaitForSingleObject(hfile, 3000);
4079 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4081 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4082 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4084 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4085 ok(off == 0, "expected 0, got %u\n", off);
4087 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4088 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4090 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4091 ok(off == 0, "expected 0, got %u\n", off);
4093 S(U(ovl)).Offset = sizeof(contents) - 4;
4094 S(U(ovl)).OffsetHigh = 0;
4095 ovl.Internal = -1;
4096 ovl.InternalHigh = -1;
4097 ovl.hEvent = 0;
4098 bytes = 0;
4099 SetLastError(0xdeadbeef);
4100 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4101 /* WriteFile return value depends on Windows version and testing it is not practical */
4102 if (!ret)
4104 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4105 ok(bytes == 0, "bytes %u\n", bytes);
4106 ret = WaitForSingleObject(hfile, 3000);
4107 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4109 else ok(bytes == 4, "bytes %u\n", bytes);
4110 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4111 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4113 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4114 ok(off == 0, "expected 0, got %u\n", off);
4116 bytes = 0xdeadbeef;
4117 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4118 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4119 ok(bytes == 4, "bytes %u\n", bytes);
4120 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4121 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4123 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4124 ok(off == 0, "expected 0, got %u\n", off);
4126 S(U(ovl)).Offset = 0;
4127 S(U(ovl)).OffsetHigh = 0;
4128 ovl.Internal = -1;
4129 ovl.InternalHigh = -1;
4130 ovl.hEvent = 0;
4131 bytes = 0;
4132 SetLastError(0xdeadbeef);
4133 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4134 /* ReadFile return value depends on Windows version and testing it is not practical */
4135 if (!ret)
4137 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4138 ok(bytes == 0, "bytes %u\n", bytes);
4139 ret = WaitForSingleObject(hfile, 3000);
4140 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4142 else ok(bytes == 14, "bytes %u\n", bytes);
4143 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4144 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4146 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4147 ok(off == 0, "expected 0, got %u\n", off);
4149 bytes = 0xdeadbeef;
4150 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4151 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4152 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4153 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4154 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4155 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4156 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4158 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4159 ok(off == 0, "expected 0, got %u\n", off);
4161 CloseHandle(hfile);
4164 START_TEST(file)
4166 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
4167 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
4168 if (!hntdll)
4170 skip("not running on NT, skipping test\n");
4171 return;
4174 pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
4175 pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
4177 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
4178 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
4179 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
4180 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
4181 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
4182 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
4183 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
4184 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
4185 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
4186 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
4187 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
4188 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
4189 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
4190 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
4191 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
4192 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
4193 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
4194 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
4195 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
4196 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
4197 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
4198 pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
4199 pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
4201 test_read_write();
4202 test_NtCreateFile();
4203 create_file_test();
4204 open_file_test();
4205 delete_file_test();
4206 read_file_test();
4207 append_file_test();
4208 nt_mailslot_test();
4209 test_iocompletion();
4210 test_file_basic_information();
4211 test_file_all_information();
4212 test_file_both_information();
4213 test_file_name_information();
4214 test_file_full_size_information();
4215 test_file_all_name_information();
4216 test_file_rename_information();
4217 test_file_link_information();
4218 test_file_disposition_information();
4219 test_query_volume_information_file();
4220 test_query_attribute_information_file();