ntdll: Implement FileIdInformation class in NtQueryInformationFile.
[wine.git] / dlls / ntdll / tests / file.c
blob1a02ce5eaa5d85b483b8e1a452f571d697af4d0c
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 static const char testdata[] = "Hello World";
181 FILE_NETWORK_OPEN_INFORMATION info;
182 NTSTATUS status;
183 HANDLE dir, file;
184 WCHAR path[MAX_PATH];
185 OBJECT_ATTRIBUTES attr;
186 IO_STATUS_BLOCK io;
187 UNICODE_STRING nameW;
188 LARGE_INTEGER offset;
189 char buf[32];
190 DWORD ret;
192 GetCurrentDirectoryW( MAX_PATH, path );
193 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
194 attr.Length = sizeof(attr);
195 attr.RootDirectory = 0;
196 attr.ObjectName = &nameW;
197 attr.Attributes = OBJ_CASE_INSENSITIVE;
198 attr.SecurityDescriptor = NULL;
199 attr.SecurityQualityOfService = NULL;
201 /* try various open modes and options on directories */
202 status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0,
203 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
204 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
206 U(io).Status = 0xdeadbeef;
207 offset.QuadPart = 0;
208 status = pNtReadFile( dir, NULL, NULL, NULL, &io, buf, sizeof(buf), &offset, NULL );
209 todo_wine
210 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtReadFile error %08x\n", status );
211 if (status == STATUS_PENDING)
213 ret = WaitForSingleObject( dir, 1000 );
214 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
215 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
216 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
219 U(io).Status = 0xdeadbeef;
220 offset.QuadPart = 0;
221 status = pNtWriteFile( dir, NULL, NULL, NULL, &io, testdata, sizeof(testdata), &offset, NULL);
222 todo_wine
223 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtWriteFile error %08x\n", status );
224 if (status == STATUS_PENDING)
226 ret = WaitForSingleObject( dir, 1000 );
227 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
228 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
229 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
232 CloseHandle( dir );
234 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
235 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
236 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
237 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
239 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
240 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
241 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
242 CloseHandle( dir );
244 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
245 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
246 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
248 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
249 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
250 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
252 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
253 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
254 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
256 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
257 FILE_OPEN, 0, NULL, 0 );
258 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
259 CloseHandle( dir );
261 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
262 FILE_CREATE, 0, NULL, 0 );
263 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
264 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
266 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
267 FILE_OPEN_IF, 0, NULL, 0 );
268 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
269 CloseHandle( dir );
271 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
272 FILE_SUPERSEDE, 0, NULL, 0 );
273 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
274 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
276 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
277 FILE_OVERWRITE, 0, NULL, 0 );
278 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
279 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
281 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
282 FILE_OVERWRITE_IF, 0, NULL, 0 );
283 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
284 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
286 pRtlFreeUnicodeString( &nameW );
288 pRtlInitUnicodeString( &nameW, systemrootW );
289 attr.Length = sizeof(attr);
290 attr.RootDirectory = NULL;
291 attr.ObjectName = &nameW;
292 attr.Attributes = OBJ_CASE_INSENSITIVE;
293 attr.SecurityDescriptor = NULL;
294 attr.SecurityQualityOfService = NULL;
295 dir = NULL;
296 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
297 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
298 todo_wine
299 ok( status == STATUS_INVALID_PARAMETER,
300 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
302 /* Invalid chars in file/dirnames */
303 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
304 attr.ObjectName = &nameW;
305 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
306 FILE_SHARE_READ, FILE_CREATE,
307 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
308 ok(status == STATUS_OBJECT_NAME_INVALID,
309 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
311 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
312 0, FILE_CREATE,
313 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
314 ok(status == STATUS_OBJECT_NAME_INVALID,
315 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
316 pRtlFreeUnicodeString(&nameW);
318 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
319 attr.ObjectName = &nameW;
320 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
321 FILE_SHARE_READ, FILE_CREATE,
322 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
323 ok(status == STATUS_OBJECT_NAME_INVALID,
324 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
326 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
327 0, FILE_CREATE,
328 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
329 ok(status == STATUS_OBJECT_NAME_INVALID,
330 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
331 pRtlFreeUnicodeString(&nameW);
333 pRtlInitUnicodeString( &nameW, pathInvalidNtW );
334 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
335 FILE_SHARE_READ, FILE_CREATE,
336 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
337 ok( status == STATUS_OBJECT_NAME_INVALID,
338 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
340 status = pNtQueryFullAttributesFile( &attr, &info );
341 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
342 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
344 pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
345 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
346 FILE_SHARE_READ, FILE_CREATE,
347 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
348 ok( status == STATUS_OBJECT_NAME_INVALID,
349 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
351 status = pNtQueryFullAttributesFile( &attr, &info );
352 ok( status == STATUS_OBJECT_NAME_INVALID,
353 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
355 pRtlInitUnicodeString( &nameW, pathInvalidDosW );
356 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
357 FILE_SHARE_READ, FILE_CREATE,
358 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
359 ok( status == STATUS_OBJECT_NAME_INVALID,
360 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
362 status = pNtQueryFullAttributesFile( &attr, &info );
363 ok( status == STATUS_OBJECT_NAME_INVALID,
364 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
367 static void open_file_test(void)
369 static const char testdata[] = "Hello World";
370 static WCHAR fooW[] = {'f','o','o',0};
371 NTSTATUS status;
372 HANDLE dir, root, handle, file;
373 WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
374 BYTE data[1024];
375 OBJECT_ATTRIBUTES attr;
376 IO_STATUS_BLOCK io;
377 UNICODE_STRING nameW;
378 UINT i, len;
379 BOOL ret, restart = TRUE;
380 DWORD numbytes;
382 len = GetWindowsDirectoryW( path, MAX_PATH );
383 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
384 attr.Length = sizeof(attr);
385 attr.RootDirectory = 0;
386 attr.ObjectName = &nameW;
387 attr.Attributes = OBJ_CASE_INSENSITIVE;
388 attr.SecurityDescriptor = NULL;
389 attr.SecurityQualityOfService = NULL;
390 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
391 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
392 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
393 pRtlFreeUnicodeString( &nameW );
395 path[3] = 0; /* root of the drive */
396 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
397 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
398 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
399 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
400 pRtlFreeUnicodeString( &nameW );
402 /* test opening system dir with RootDirectory set to windows dir */
403 GetSystemDirectoryW( path, MAX_PATH );
404 while (path[len] == '\\') len++;
405 nameW.Buffer = path + len;
406 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
407 attr.RootDirectory = dir;
408 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
409 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
410 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
411 CloseHandle( handle );
413 /* try uppercase name */
414 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
415 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
416 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
417 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
418 CloseHandle( handle );
420 /* try with leading backslash */
421 nameW.Buffer--;
422 nameW.Length += sizeof(WCHAR);
423 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
424 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
425 ok( status == STATUS_INVALID_PARAMETER ||
426 status == STATUS_OBJECT_NAME_INVALID ||
427 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
428 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
429 if (!status) CloseHandle( handle );
431 /* try with empty name */
432 nameW.Length = 0;
433 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
434 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
435 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
436 CloseHandle( handle );
438 /* try open by file id */
440 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
441 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
443 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
445 restart = FALSE;
447 if (!info->FileId.QuadPart) continue;
449 nameW.Buffer = (WCHAR *)&info->FileId;
450 nameW.Length = sizeof(info->FileId);
451 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
452 attr.RootDirectory = dir;
453 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
454 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
455 FILE_SHARE_READ,
456 FILE_OPEN_BY_FILE_ID |
457 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
458 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
459 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
460 if (status == STATUS_NOT_IMPLEMENTED)
462 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
463 break;
465 if (status == STATUS_SHARING_VIOLATION)
466 trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
467 if (!status)
469 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
471 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
473 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
475 /* check that it's the same file/directory */
477 /* don't check the size for directories */
478 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
479 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
480 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
482 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
483 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
485 CloseHandle( handle );
487 /* try same thing from drive root */
488 attr.RootDirectory = root;
489 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
490 FILE_SHARE_READ|FILE_SHARE_WRITE,
491 FILE_OPEN_BY_FILE_ID |
492 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
493 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
494 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
495 if (!status) CloseHandle( handle );
499 CloseHandle( dir );
500 CloseHandle( root );
502 GetTempPathW( MAX_PATH, path );
503 GetTempFileNameW( path, fooW, 0, tmpfile );
504 pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
506 file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
507 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
508 numbytes = 0xdeadbeef;
509 ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
510 ok( ret, "WriteFile failed with error %u\n", GetLastError() );
511 ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
512 CloseHandle( file );
514 attr.Length = sizeof(attr);
515 attr.RootDirectory = 0;
516 attr.ObjectName = &nameW;
517 attr.Attributes = OBJ_CASE_INSENSITIVE;
518 attr.SecurityDescriptor = NULL;
519 attr.SecurityQualityOfService = NULL;
520 status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
521 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
522 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
523 pRtlFreeUnicodeString( &nameW );
525 numbytes = 0xdeadbeef;
526 memset( data, 0, sizeof(data) );
527 ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
528 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
529 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
530 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
532 nameW.Length = sizeof(fooW) - sizeof(WCHAR);
533 nameW.Buffer = fooW;
534 attr.RootDirectory = file;
535 attr.ObjectName = &nameW;
536 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
537 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
538 ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
539 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
541 nameW.Length = 0;
542 nameW.Buffer = NULL;
543 attr.RootDirectory = file;
544 attr.ObjectName = &nameW;
545 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
546 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
547 ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
549 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
550 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
551 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
552 ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
554 numbytes = 0xdeadbeef;
555 memset( data, 0, sizeof(data) );
556 ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
557 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
558 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
559 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
561 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
562 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
563 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
564 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
566 CloseHandle( file );
567 CloseHandle( root );
568 DeleteFileW( tmpfile );
571 static void delete_file_test(void)
573 NTSTATUS ret;
574 OBJECT_ATTRIBUTES attr;
575 UNICODE_STRING nameW;
576 WCHAR pathW[MAX_PATH];
577 WCHAR pathsubW[MAX_PATH];
578 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
579 static const WCHAR subdirW[] = {'\\','s','u','b',0};
581 ret = GetTempPathW(MAX_PATH, pathW);
582 if (!ret)
584 ok(0, "couldn't get temp dir\n");
585 return;
587 if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
589 ok(0, "MAX_PATH exceeded in constructing paths\n");
590 return;
593 lstrcatW(pathW, testdirW);
594 lstrcpyW(pathsubW, pathW);
595 lstrcatW(pathsubW, subdirW);
597 ret = CreateDirectoryW(pathW, NULL);
598 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
599 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
601 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
602 return;
605 attr.Length = sizeof(attr);
606 attr.RootDirectory = 0;
607 attr.Attributes = OBJ_CASE_INSENSITIVE;
608 attr.ObjectName = &nameW;
609 attr.SecurityDescriptor = NULL;
610 attr.SecurityQualityOfService = NULL;
612 /* test NtDeleteFile on an empty directory */
613 ret = pNtDeleteFile(&attr);
614 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
615 ret = RemoveDirectoryW(pathW);
616 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
618 /* test NtDeleteFile on a non-empty directory */
619 ret = CreateDirectoryW(pathW, NULL);
620 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
621 ret = CreateDirectoryW(pathsubW, NULL);
622 ok(ret == TRUE, "couldn't create directory subdir\n");
623 ret = pNtDeleteFile(&attr);
624 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
625 ret = RemoveDirectoryW(pathsubW);
626 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
627 ret = RemoveDirectoryW(pathW);
628 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
630 pRtlFreeUnicodeString( &nameW );
633 static void read_file_test(void)
635 const char text[] = "foobar";
636 HANDLE handle, read, write;
637 NTSTATUS status;
638 IO_STATUS_BLOCK iosb, iosb2;
639 DWORD written;
640 int apc_count = 0;
641 char buffer[128];
642 LARGE_INTEGER offset;
643 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
644 BOOL ret;
646 buffer[0] = 1;
648 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
650 /* try read with no data */
651 U(iosb).Status = 0xdeadbabe;
652 iosb.Information = 0xdeadbeef;
653 ok( is_signaled( read ), "read handle is not signaled\n" );
654 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
655 ok( status == STATUS_PENDING, "wrong status %x\n", status );
656 ok( !is_signaled( read ), "read handle is signaled\n" );
657 ok( !is_signaled( event ), "event is signaled\n" );
658 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
659 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
660 ok( !apc_count, "apc was called\n" );
661 ret = WriteFile( write, buffer, 1, &written, NULL );
662 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
663 /* iosb updated here by async i/o */
664 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
665 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
666 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
667 ok( !is_signaled( read ), "read handle is signaled\n" );
668 ok( is_signaled( event ), "event is not signaled\n" );
669 ok( !apc_count, "apc was called\n" );
670 apc_count = 0;
671 SleepEx( 1, FALSE ); /* non-alertable sleep */
672 ok( !apc_count, "apc was called\n" );
673 SleepEx( 1, TRUE ); /* alertable sleep */
674 ok( apc_count == 1, "apc not called\n" );
676 /* with no event, the pipe handle itself gets signaled */
677 apc_count = 0;
678 U(iosb).Status = 0xdeadbabe;
679 iosb.Information = 0xdeadbeef;
680 ok( !is_signaled( read ), "read handle is signaled\n" );
681 status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
682 ok( status == STATUS_PENDING, "wrong status %x\n", status );
683 ok( !is_signaled( read ), "read handle is signaled\n" );
684 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
685 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
686 ok( !apc_count, "apc was called\n" );
687 ret = WriteFile( write, buffer, 1, &written, NULL );
688 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
689 /* iosb updated here by async i/o */
690 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
691 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
692 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
693 ok( is_signaled( read ), "read handle is not signaled\n" );
694 ok( !apc_count, "apc was called\n" );
695 apc_count = 0;
696 SleepEx( 1, FALSE ); /* non-alertable sleep */
697 ok( !apc_count, "apc was called\n" );
698 SleepEx( 1, TRUE ); /* alertable sleep */
699 ok( apc_count == 1, "apc not called\n" );
701 /* now read with data ready */
702 apc_count = 0;
703 U(iosb).Status = 0xdeadbabe;
704 iosb.Information = 0xdeadbeef;
705 ResetEvent( event );
706 ret = WriteFile( write, buffer, 1, &written, NULL );
707 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
708 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
709 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
710 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
711 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
712 ok( is_signaled( event ), "event is not signaled\n" );
713 ok( !apc_count, "apc was called\n" );
714 SleepEx( 1, FALSE ); /* non-alertable sleep */
715 ok( !apc_count, "apc was called\n" );
716 SleepEx( 1, TRUE ); /* alertable sleep */
717 ok( apc_count == 1, "apc not called\n" );
719 /* try read with no data */
720 apc_count = 0;
721 U(iosb).Status = 0xdeadbabe;
722 iosb.Information = 0xdeadbeef;
723 ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
724 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
725 ok( status == STATUS_PENDING, "wrong status %x\n", status );
726 ok( !is_signaled( event ), "event is signaled\n" );
727 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
728 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
729 ok( !apc_count, "apc was called\n" );
730 ret = WriteFile( write, buffer, 1, &written, NULL );
731 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
732 /* partial read is good enough */
733 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
734 ok( is_signaled( event ), "event is not signaled\n" );
735 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
736 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
737 ok( !apc_count, "apc was called\n" );
738 SleepEx( 1, TRUE ); /* alertable sleep */
739 ok( apc_count == 1, "apc was not called\n" );
741 /* read from disconnected pipe */
742 apc_count = 0;
743 U(iosb).Status = 0xdeadbabe;
744 iosb.Information = 0xdeadbeef;
745 CloseHandle( write );
746 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
747 ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
748 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
749 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
750 ok( !is_signaled( event ), "event is signaled\n" );
751 ok( !apc_count, "apc was called\n" );
752 SleepEx( 1, TRUE ); /* alertable sleep */
753 ok( !apc_count, "apc was called\n" );
754 CloseHandle( read );
756 /* read from closed handle */
757 apc_count = 0;
758 U(iosb).Status = 0xdeadbabe;
759 iosb.Information = 0xdeadbeef;
760 SetEvent( event );
761 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
762 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
763 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
764 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
765 ok( is_signaled( event ), "event is not signaled\n" ); /* not reset on invalid handle */
766 ok( !apc_count, "apc was called\n" );
767 SleepEx( 1, TRUE ); /* alertable sleep */
768 ok( !apc_count, "apc was called\n" );
770 /* disconnect while async read is in progress */
771 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
772 apc_count = 0;
773 U(iosb).Status = 0xdeadbabe;
774 iosb.Information = 0xdeadbeef;
775 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
776 ok( status == STATUS_PENDING, "wrong status %x\n", status );
777 ok( !is_signaled( event ), "event is signaled\n" );
778 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
779 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
780 ok( !apc_count, "apc was called\n" );
781 CloseHandle( write );
782 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
783 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
784 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
785 ok( is_signaled( event ), "event is not signaled\n" );
786 ok( !apc_count, "apc was called\n" );
787 SleepEx( 1, TRUE ); /* alertable sleep */
788 ok( apc_count == 1, "apc was not called\n" );
789 CloseHandle( read );
791 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
792 ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
793 ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
795 apc_count = 0;
796 U(iosb).Status = 0xdeadbabe;
797 iosb.Information = 0xdeadbeef;
798 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
799 ok( status == STATUS_PENDING, "wrong status %x\n", status );
800 ok( !is_signaled( event ), "event is signaled\n" );
801 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
802 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
803 ok( !apc_count, "apc was called\n" );
804 /* Cancel by other handle */
805 status = pNtCancelIoFile( read, &iosb2 );
806 ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
807 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
808 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
809 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
810 ok( is_signaled( event ), "event is not signaled\n" );
811 ok( !apc_count, "apc was called\n" );
812 SleepEx( 1, TRUE ); /* alertable sleep */
813 ok( apc_count == 1, "apc was not called\n" );
815 apc_count = 0;
816 U(iosb).Status = 0xdeadbabe;
817 iosb.Information = 0xdeadbeef;
818 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
819 ok( status == STATUS_PENDING, "wrong status %x\n", status );
820 ok( !is_signaled( event ), "event is signaled\n" );
821 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
822 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
823 ok( !apc_count, "apc was called\n" );
824 /* Close queued handle */
825 CloseHandle( read );
826 SleepEx( 1, TRUE ); /* alertable sleep */
827 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
828 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
829 status = pNtCancelIoFile( read, &iosb2 );
830 ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
831 status = pNtCancelIoFile( handle, &iosb2 );
832 ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
833 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
834 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
835 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
836 ok( is_signaled( event ), "event is not signaled\n" );
837 ok( !apc_count, "apc was called\n" );
838 SleepEx( 1, TRUE ); /* alertable sleep */
839 ok( apc_count == 1, "apc was not called\n" );
840 CloseHandle( handle );
841 CloseHandle( write );
843 if (pNtCancelIoFileEx)
845 /* Basic Cancel Ex */
846 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
848 apc_count = 0;
849 U(iosb).Status = 0xdeadbabe;
850 iosb.Information = 0xdeadbeef;
851 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
852 ok( status == STATUS_PENDING, "wrong status %x\n", status );
853 ok( !is_signaled( event ), "event is signaled\n" );
854 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
855 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
856 ok( !apc_count, "apc was called\n" );
857 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
858 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
859 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
860 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
861 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
862 ok( is_signaled( event ), "event is not signaled\n" );
863 ok( !apc_count, "apc was called\n" );
864 SleepEx( 1, TRUE ); /* alertable sleep */
865 ok( apc_count == 1, "apc was not called\n" );
867 /* Duplicate iosb */
868 apc_count = 0;
869 U(iosb).Status = 0xdeadbabe;
870 iosb.Information = 0xdeadbeef;
871 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
872 ok( status == STATUS_PENDING, "wrong status %x\n", status );
873 ok( !is_signaled( event ), "event is signaled\n" );
874 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
875 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
876 ok( !apc_count, "apc was called\n" );
877 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
878 ok( status == STATUS_PENDING, "wrong status %x\n", status );
879 ok( !is_signaled( event ), "event is signaled\n" );
880 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
881 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
882 ok( !apc_count, "apc was called\n" );
883 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
884 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
885 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
886 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
887 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
888 ok( is_signaled( event ), "event is not signaled\n" );
889 ok( !apc_count, "apc was called\n" );
890 SleepEx( 1, TRUE ); /* alertable sleep */
891 ok( apc_count == 2, "apc was not called\n" );
893 CloseHandle( read );
894 CloseHandle( write );
897 /* now try a real file */
898 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
899 apc_count = 0;
900 U(iosb).Status = 0xdeadbabe;
901 iosb.Information = 0xdeadbeef;
902 offset.QuadPart = 0;
903 ResetEvent( event );
904 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
905 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
906 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
907 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
908 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
909 ok( is_signaled( event ), "event is not signaled\n" );
910 ok( !apc_count, "apc was called\n" );
911 SleepEx( 1, TRUE ); /* alertable sleep */
912 ok( apc_count == 1, "apc was not called\n" );
914 apc_count = 0;
915 U(iosb).Status = 0xdeadbabe;
916 iosb.Information = 0xdeadbeef;
917 offset.QuadPart = 0;
918 ResetEvent( event );
919 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
920 ok( status == STATUS_SUCCESS ||
921 status == STATUS_PENDING, /* vista */
922 "wrong status %x\n", status );
923 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
924 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
925 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
926 ok( is_signaled( event ), "event is not signaled\n" );
927 ok( !apc_count, "apc was called\n" );
928 SleepEx( 1, TRUE ); /* alertable sleep */
929 ok( apc_count == 1, "apc was not called\n" );
931 /* read beyond eof */
932 apc_count = 0;
933 U(iosb).Status = 0xdeadbabe;
934 iosb.Information = 0xdeadbeef;
935 offset.QuadPart = strlen(text) + 2;
936 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
937 ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
938 if (status == STATUS_PENDING) /* vista */
940 WaitForSingleObject( event, 1000 );
941 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
942 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
943 ok( is_signaled( event ), "event is not signaled\n" );
944 ok( !apc_count, "apc was called\n" );
945 SleepEx( 1, TRUE ); /* alertable sleep */
946 ok( apc_count == 1, "apc was not called\n" );
948 CloseHandle( handle );
950 /* now a non-overlapped file */
951 if (!(handle = create_temp_file(0))) return;
952 apc_count = 0;
953 U(iosb).Status = 0xdeadbabe;
954 iosb.Information = 0xdeadbeef;
955 offset.QuadPart = 0;
956 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
957 ok( status == STATUS_END_OF_FILE ||
958 status == STATUS_SUCCESS ||
959 status == STATUS_PENDING, /* vista */
960 "wrong status %x\n", status );
961 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
962 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
963 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
964 ok( is_signaled( event ), "event is not signaled\n" );
965 ok( !apc_count, "apc was called\n" );
966 SleepEx( 1, TRUE ); /* alertable sleep */
967 ok( apc_count == 1, "apc was not called\n" );
969 apc_count = 0;
970 U(iosb).Status = 0xdeadbabe;
971 iosb.Information = 0xdeadbeef;
972 offset.QuadPart = 0;
973 ResetEvent( event );
974 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
975 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
976 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
977 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
978 ok( is_signaled( event ), "event is not signaled\n" );
979 ok( !apc_count, "apc was called\n" );
980 SleepEx( 1, TRUE ); /* alertable sleep */
981 todo_wine ok( !apc_count, "apc was called\n" );
983 /* read beyond eof */
984 apc_count = 0;
985 U(iosb).Status = 0xdeadbabe;
986 iosb.Information = 0xdeadbeef;
987 offset.QuadPart = strlen(text) + 2;
988 ResetEvent( event );
989 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
990 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
991 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
992 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
993 ok( is_signaled( event ), "event is not signaled\n" );
994 ok( !apc_count, "apc was called\n" );
995 SleepEx( 1, TRUE ); /* alertable sleep */
996 ok( !apc_count, "apc was called\n" );
998 CloseHandle( handle );
1000 CloseHandle( event );
1003 static void append_file_test(void)
1005 static const char text[6] = "foobar";
1006 HANDLE handle;
1007 NTSTATUS status;
1008 IO_STATUS_BLOCK iosb;
1009 LARGE_INTEGER offset;
1010 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
1011 DWORD ret;
1013 GetTempPathA( MAX_PATH, path );
1014 GetTempFileNameA( path, "foo", 0, buffer );
1016 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
1017 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1019 U(iosb).Status = -1;
1020 iosb.Information = -1;
1021 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
1022 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
1023 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1024 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
1026 CloseHandle(handle);
1028 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
1029 It matches the O_WRONLY|O_APPEND open() posix behavior */
1030 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
1031 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1033 U(iosb).Status = -1;
1034 iosb.Information = -1;
1035 offset.QuadPart = 1;
1036 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
1037 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
1038 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1039 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
1041 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
1042 ok(ret == 4, "expected 4, got %u\n", ret);
1044 U(iosb).Status = -1;
1045 iosb.Information = -1;
1046 offset.QuadPart = 3;
1047 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
1048 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
1049 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1050 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
1052 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
1053 ok(ret == 6, "expected 6, got %u\n", ret);
1055 CloseHandle(handle);
1057 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
1058 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1060 memset(buf, 0, sizeof(buf));
1061 U(iosb).Status = -1;
1062 iosb.Information = -1;
1063 offset.QuadPart = 0;
1064 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
1065 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
1066 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1067 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
1068 buf[6] = 0;
1069 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
1071 U(iosb).Status = -1;
1072 iosb.Information = -1;
1073 offset.QuadPart = 0;
1074 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
1075 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
1076 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1077 ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
1079 memset(buf, 0, sizeof(buf));
1080 U(iosb).Status = -1;
1081 iosb.Information = -1;
1082 offset.QuadPart = 0;
1083 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
1084 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
1085 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
1086 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
1087 buf[6] = 0;
1088 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
1090 CloseHandle(handle);
1091 DeleteFileA(buffer);
1094 static void nt_mailslot_test(void)
1096 HANDLE hslot;
1097 ACCESS_MASK DesiredAccess;
1098 OBJECT_ATTRIBUTES attr;
1100 ULONG CreateOptions;
1101 ULONG MailslotQuota;
1102 ULONG MaxMessageSize;
1103 LARGE_INTEGER TimeOut;
1104 IO_STATUS_BLOCK IoStatusBlock;
1105 NTSTATUS rc;
1106 UNICODE_STRING str;
1107 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
1108 'R',':','\\','F','R','E','D','\0' };
1110 TimeOut.QuadPart = -1;
1112 pRtlInitUnicodeString(&str, buffer1);
1113 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1114 CreateOptions = MailslotQuota = MaxMessageSize = 0;
1115 DesiredAccess = GENERIC_READ;
1118 * Check for NULL pointer handling
1120 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
1121 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1122 &TimeOut);
1123 ok( rc == STATUS_ACCESS_VIOLATION ||
1124 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
1125 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
1128 * Test to see if the Timeout can be NULL
1130 hslot = (HANDLE)0xdeadbeef;
1131 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1132 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1133 NULL);
1134 ok( rc == STATUS_SUCCESS ||
1135 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
1136 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
1137 ok( hslot != 0, "Handle is invalid\n");
1139 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
1142 * Test a valid call
1144 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1145 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1146 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1147 &TimeOut);
1148 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
1149 ok( hslot != 0, "Handle is invalid\n");
1151 rc = pNtClose(hslot);
1152 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
1155 static void test_iocp_setcompletion(HANDLE h)
1157 NTSTATUS res;
1158 ULONG count;
1159 SIZE_T size = 3;
1161 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
1163 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
1164 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
1166 count = get_pending_msgs(h);
1167 ok( count == 1, "Unexpected msg count: %d\n", count );
1169 if (get_msg(h))
1171 ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
1172 ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
1173 ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1174 ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
1177 count = get_pending_msgs(h);
1178 ok( !count, "Unexpected msg count: %d\n", count );
1181 static void test_iocp_fileio(HANDLE h)
1183 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1185 IO_STATUS_BLOCK iosb;
1186 FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
1187 HANDLE hPipeSrv, hPipeClt;
1188 NTSTATUS res;
1190 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1191 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1192 if (hPipeSrv != INVALID_HANDLE_VALUE )
1194 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1195 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1196 if (hPipeClt != INVALID_HANDLE_VALUE)
1198 U(iosb).Status = 0xdeadbeef;
1199 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1200 ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
1201 ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
1202 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
1203 CloseHandle(hPipeClt);
1205 CloseHandle( hPipeSrv );
1208 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1209 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1210 if (hPipeSrv == INVALID_HANDLE_VALUE )
1211 return;
1213 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1214 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1215 if (hPipeClt != INVALID_HANDLE_VALUE)
1217 OVERLAPPED o = {0,};
1218 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1219 DWORD read;
1220 long count;
1222 U(iosb).Status = 0xdeadbeef;
1223 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1224 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1225 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1227 memset( send_buf, 0, TEST_BUF_LEN );
1228 memset( recv_buf, 0xde, TEST_BUF_LEN );
1229 count = get_pending_msgs(h);
1230 ok( !count, "Unexpected msg count: %ld\n", count );
1231 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1232 count = get_pending_msgs(h);
1233 ok( !count, "Unexpected msg count: %ld\n", count );
1234 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1236 if (get_msg(h))
1238 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1239 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1240 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1241 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1242 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] );
1244 count = get_pending_msgs(h);
1245 ok( !count, "Unexpected msg count: %ld\n", count );
1247 memset( send_buf, 0, TEST_BUF_LEN );
1248 memset( recv_buf, 0xde, TEST_BUF_LEN );
1249 WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1250 count = get_pending_msgs(h);
1251 ok( !count, "Unexpected msg count: %ld\n", count );
1252 ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1253 count = get_pending_msgs(h);
1254 ok( count == 1, "Unexpected msg count: %ld\n", count );
1255 if (get_msg(h))
1257 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1258 ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1259 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1260 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1261 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] );
1264 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1265 CloseHandle( hPipeSrv );
1266 count = get_pending_msgs(h);
1267 ok( count == 1, "Unexpected msg count: %ld\n", count );
1268 if (get_msg(h))
1270 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1271 ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1272 /* wine sends wrong status here */
1273 todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1274 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1278 CloseHandle( hPipeClt );
1280 /* test associating a completion port with a handle after an async is queued */
1281 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1282 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1283 if (hPipeSrv == INVALID_HANDLE_VALUE )
1284 return;
1285 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1286 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1287 if (hPipeClt != INVALID_HANDLE_VALUE)
1289 OVERLAPPED o = {0,};
1290 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1291 DWORD read;
1292 long count;
1294 memset( send_buf, 0, TEST_BUF_LEN );
1295 memset( recv_buf, 0xde, TEST_BUF_LEN );
1296 count = get_pending_msgs(h);
1297 ok( !count, "Unexpected msg count: %ld\n", count );
1298 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1300 U(iosb).Status = 0xdeadbeef;
1301 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1302 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1303 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1304 count = get_pending_msgs(h);
1305 ok( !count, "Unexpected msg count: %ld\n", count );
1307 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1309 if (get_msg(h))
1311 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1312 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1313 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1314 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1315 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] );
1317 count = get_pending_msgs(h);
1318 ok( !count, "Unexpected msg count: %ld\n", count );
1321 CloseHandle( hPipeSrv );
1322 CloseHandle( hPipeClt );
1325 static void test_file_full_size_information(void)
1327 IO_STATUS_BLOCK io;
1328 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1329 FILE_FS_SIZE_INFORMATION fsi;
1330 HANDLE h;
1331 NTSTATUS res;
1333 if(!(h = create_temp_file(0))) return ;
1335 memset(&ffsi,0,sizeof(ffsi));
1336 memset(&fsi,0,sizeof(fsi));
1338 /* Assume No Quota Settings configured on Wine Testbot */
1339 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1340 todo_wine ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1341 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1342 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1344 /* Test for FileFsSizeInformation */
1345 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1346 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1347 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1348 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1349 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1350 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1352 /* Assume file system is NTFS */
1353 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1354 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1356 todo_wine
1358 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1359 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1360 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1361 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1362 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1363 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1364 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1365 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1366 debugstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1367 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1368 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1369 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1370 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1371 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1372 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1373 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1374 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1377 /* Assume file system is NTFS */
1378 todo_wine
1380 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1381 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1384 CloseHandle( h );
1387 static void test_file_basic_information(void)
1389 IO_STATUS_BLOCK io;
1390 FILE_BASIC_INFORMATION fbi;
1391 HANDLE h;
1392 int res;
1393 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1395 if (!(h = create_temp_file(0))) return;
1397 /* Check default first */
1398 memset(&fbi, 0, sizeof(fbi));
1399 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1400 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1401 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1402 "attribute %x not expected\n", fbi.FileAttributes );
1404 /* Then SYSTEM */
1405 /* Clear fbi to avoid setting times */
1406 memset(&fbi, 0, sizeof(fbi));
1407 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1408 U(io).Status = 0xdeadbeef;
1409 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1410 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1411 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1413 memset(&fbi, 0, sizeof(fbi));
1414 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1415 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1416 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1418 /* Then HIDDEN */
1419 memset(&fbi, 0, sizeof(fbi));
1420 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1421 U(io).Status = 0xdeadbeef;
1422 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1423 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1424 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1426 memset(&fbi, 0, sizeof(fbi));
1427 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1428 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1429 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1431 /* Check NORMAL last of all (to make sure we can clear attributes) */
1432 memset(&fbi, 0, sizeof(fbi));
1433 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1434 U(io).Status = 0xdeadbeef;
1435 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1436 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1437 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1439 memset(&fbi, 0, sizeof(fbi));
1440 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1441 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1442 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1444 CloseHandle( h );
1447 static void test_file_all_information(void)
1449 IO_STATUS_BLOCK io;
1450 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1451 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1452 * don't leave enough room there.
1454 struct {
1455 FILE_ALL_INFORMATION fai;
1456 WCHAR buf[256];
1457 } fai_buf;
1458 HANDLE h;
1459 int res;
1460 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1462 if (!(h = create_temp_file(0))) return;
1464 /* Check default first */
1465 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1466 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1467 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1468 "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1470 /* Then SYSTEM */
1471 /* Clear fbi to avoid setting times */
1472 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1473 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1474 U(io).Status = 0xdeadbeef;
1475 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1476 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1477 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1478 U(io).Status = 0xdeadbeef;
1479 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1480 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1481 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1483 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1484 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1485 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1486 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 );
1488 /* Then HIDDEN */
1489 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1490 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1491 U(io).Status = 0xdeadbeef;
1492 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1493 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1494 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1496 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1497 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1498 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1499 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 );
1501 /* Check NORMAL last of all (to make sure we can clear attributes) */
1502 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1503 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1504 U(io).Status = 0xdeadbeef;
1505 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1506 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1507 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1509 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1510 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1511 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1512 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 );
1514 CloseHandle( h );
1517 static void delete_object( WCHAR *path )
1519 BOOL ret = DeleteFileW( path );
1520 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1521 "DeleteFileW failed with %u\n", GetLastError() );
1522 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1524 ret = RemoveDirectoryW( path );
1525 ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
1529 static void test_file_rename_information(void)
1531 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1532 static const WCHAR fooW[] = {'f','o','o',0};
1533 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1534 FILE_RENAME_INFORMATION *fri;
1535 FILE_NAME_INFORMATION *fni;
1536 BOOL success, fileDeleted;
1537 UNICODE_STRING name_str;
1538 HANDLE handle, handle2;
1539 IO_STATUS_BLOCK io;
1540 NTSTATUS res;
1542 GetTempPathW( MAX_PATH, tmp_path );
1544 /* oldpath is a file, newpath doesn't exist */
1545 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1546 ok( res != 0, "failed to create temp file\n" );
1547 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1548 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1550 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1551 ok( res != 0, "failed to create temp file\n" );
1552 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1553 DeleteFileW( newpath );
1554 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1555 fri->Replace = FALSE;
1556 fri->RootDir = NULL;
1557 fri->FileNameLength = name_str.Length;
1558 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1559 pRtlFreeUnicodeString( &name_str );
1561 U(io).Status = 0xdeadbeef;
1562 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1563 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1564 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1565 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1566 ok( fileDeleted, "file should not exist\n" );
1567 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1568 ok( !fileDeleted, "file should exist\n" );
1570 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1571 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1572 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1573 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1574 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1575 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1576 HeapFree( GetProcessHeap(), 0, fni );
1578 CloseHandle( handle );
1579 HeapFree( GetProcessHeap(), 0, fri );
1580 delete_object( oldpath );
1581 delete_object( newpath );
1583 /* oldpath is a file, newpath is a file, Replace = FALSE */
1584 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1585 ok( res != 0, "failed to create temp file\n" );
1586 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1587 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1589 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1590 ok( res != 0, "failed to create temp file\n" );
1591 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1592 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1593 fri->Replace = FALSE;
1594 fri->RootDir = NULL;
1595 fri->FileNameLength = name_str.Length;
1596 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1597 pRtlFreeUnicodeString( &name_str );
1599 U(io).Status = 0xdeadbeef;
1600 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1601 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1602 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1603 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1604 ok( !fileDeleted, "file should exist\n" );
1605 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1606 ok( !fileDeleted, "file should exist\n" );
1608 CloseHandle( handle );
1609 HeapFree( GetProcessHeap(), 0, fri );
1610 delete_object( oldpath );
1611 delete_object( newpath );
1613 /* oldpath is a file, newpath is a file, Replace = TRUE */
1614 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1615 ok( res != 0, "failed to create temp file\n" );
1616 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1617 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1619 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1620 ok( res != 0, "failed to create temp file\n" );
1621 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1622 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1623 fri->Replace = TRUE;
1624 fri->RootDir = NULL;
1625 fri->FileNameLength = name_str.Length;
1626 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1627 pRtlFreeUnicodeString( &name_str );
1629 U(io).Status = 0xdeadbeef;
1630 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1631 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1632 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1633 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1634 ok( fileDeleted, "file should not exist\n" );
1635 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1636 ok( !fileDeleted, "file should exist\n" );
1638 CloseHandle( handle );
1639 HeapFree( GetProcessHeap(), 0, fri );
1640 delete_object( oldpath );
1641 delete_object( newpath );
1643 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1644 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1645 ok( res != 0, "failed to create temp file\n" );
1646 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1647 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1649 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1650 ok( res != 0, "failed to create temp file\n" );
1651 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1652 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1654 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1655 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1656 fri->Replace = FALSE;
1657 fri->RootDir = NULL;
1658 fri->FileNameLength = name_str.Length;
1659 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1660 pRtlFreeUnicodeString( &name_str );
1662 U(io).Status = 0xdeadbeef;
1663 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1664 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1665 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1666 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1667 ok( !fileDeleted, "file should exist\n" );
1668 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1669 ok( !fileDeleted, "file should exist\n" );
1671 CloseHandle( handle );
1672 CloseHandle( handle2 );
1673 HeapFree( GetProcessHeap(), 0, fri );
1674 delete_object( oldpath );
1675 delete_object( newpath );
1677 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1678 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1679 ok( res != 0, "failed to create temp file\n" );
1680 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1681 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1683 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1684 ok( res != 0, "failed to create temp file\n" );
1685 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1686 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1688 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1689 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1690 fri->Replace = TRUE;
1691 fri->RootDir = NULL;
1692 fri->FileNameLength = name_str.Length;
1693 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1694 pRtlFreeUnicodeString( &name_str );
1696 U(io).Status = 0xdeadbeef;
1697 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1698 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1699 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1700 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1701 ok( !fileDeleted, "file should exist\n" );
1702 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1703 ok( !fileDeleted, "file should exist\n" );
1705 CloseHandle( handle );
1706 CloseHandle( handle2 );
1707 HeapFree( GetProcessHeap(), 0, fri );
1708 delete_object( oldpath );
1709 delete_object( newpath );
1711 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1712 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1713 ok( res != 0, "failed to create temp file\n" );
1714 DeleteFileW( oldpath );
1715 success = CreateDirectoryW( oldpath, NULL );
1716 ok( success != 0, "failed to create temp directory\n" );
1717 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1718 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1720 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1721 ok( res != 0, "failed to create temp file\n" );
1722 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1723 DeleteFileW( newpath );
1724 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1725 fri->Replace = FALSE;
1726 fri->RootDir = NULL;
1727 fri->FileNameLength = name_str.Length;
1728 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1729 pRtlFreeUnicodeString( &name_str );
1731 U(io).Status = 0xdeadbeef;
1732 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1733 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1734 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1735 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1736 ok( fileDeleted, "file should not exist\n" );
1737 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1738 ok( !fileDeleted, "file should exist\n" );
1740 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1741 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1742 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1743 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1744 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1745 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1746 HeapFree( GetProcessHeap(), 0, fni );
1748 CloseHandle( handle );
1749 HeapFree( GetProcessHeap(), 0, fri );
1750 delete_object( oldpath );
1751 delete_object( newpath );
1753 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1754 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1755 ok( res != 0, "failed to create temp file\n" );
1756 DeleteFileW( oldpath );
1757 success = CreateDirectoryW( oldpath, NULL );
1758 ok( success != 0, "failed to create temp directory\n" );
1759 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1760 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1762 lstrcpyW( newpath, oldpath );
1763 lstrcatW( newpath, foo_txtW );
1764 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1765 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1767 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1768 ok( res != 0, "failed to create temp file\n" );
1769 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1770 DeleteFileW( newpath );
1771 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1772 fri->Replace = FALSE;
1773 fri->RootDir = NULL;
1774 fri->FileNameLength = name_str.Length;
1775 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1776 pRtlFreeUnicodeString( &name_str );
1778 U(io).Status = 0xdeadbeef;
1779 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1780 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1781 todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1782 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1783 todo_wine ok( !fileDeleted, "file should exist\n" );
1784 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1785 todo_wine ok( fileDeleted, "file should not exist\n" );
1787 CloseHandle( handle );
1788 CloseHandle( handle2 );
1789 HeapFree( GetProcessHeap(), 0, fri );
1790 delete_object( oldpath );
1791 if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1793 lstrcpyW( oldpath, newpath );
1794 lstrcatW( oldpath, foo_txtW );
1795 delete_object( oldpath );
1797 delete_object( newpath );
1799 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1800 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1801 ok( res != 0, "failed to create temp file\n" );
1802 DeleteFileW( oldpath );
1803 success = CreateDirectoryW( oldpath, NULL );
1804 ok( success != 0, "failed to create temp directory\n" );
1805 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1806 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1808 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1809 ok( res != 0, "failed to create temp file\n" );
1810 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1811 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1812 fri->Replace = FALSE;
1813 fri->RootDir = NULL;
1814 fri->FileNameLength = name_str.Length;
1815 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1816 pRtlFreeUnicodeString( &name_str );
1818 U(io).Status = 0xdeadbeef;
1819 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1820 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1821 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1822 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1823 ok( !fileDeleted, "file should exist\n" );
1824 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1825 ok( !fileDeleted, "file should exist\n" );
1827 CloseHandle( handle );
1828 HeapFree( GetProcessHeap(), 0, fri );
1829 delete_object( oldpath );
1830 delete_object( newpath );
1832 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1833 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1834 ok( res != 0, "failed to create temp file\n" );
1835 DeleteFileW( oldpath );
1836 success = CreateDirectoryW( oldpath, NULL );
1837 ok( success != 0, "failed to create temp directory\n" );
1838 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1839 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1841 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1842 ok( res != 0, "failed to create temp file\n" );
1843 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1844 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1846 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1847 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1848 fri->Replace = FALSE;
1849 fri->RootDir = NULL;
1850 fri->FileNameLength = name_str.Length;
1851 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1852 pRtlFreeUnicodeString( &name_str );
1854 U(io).Status = 0xdeadbeef;
1855 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1856 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1857 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1858 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1859 ok( !fileDeleted, "file should exist\n" );
1860 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1861 ok( !fileDeleted, "file should exist\n" );
1863 CloseHandle( handle );
1864 CloseHandle( handle2 );
1865 HeapFree( GetProcessHeap(), 0, fri );
1866 delete_object( oldpath );
1867 delete_object( newpath );
1869 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1870 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1871 ok( res != 0, "failed to create temp file\n" );
1872 DeleteFileW( oldpath );
1873 success = CreateDirectoryW( oldpath, NULL );
1874 ok( success != 0, "failed to create temp directory\n" );
1875 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1876 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1878 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1879 ok( res != 0, "failed to create temp file\n" );
1880 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1881 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1882 fri->Replace = TRUE;
1883 fri->RootDir = NULL;
1884 fri->FileNameLength = name_str.Length;
1885 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1886 pRtlFreeUnicodeString( &name_str );
1888 U(io).Status = 0xdeadbeef;
1889 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1890 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1891 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1892 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1893 ok( fileDeleted, "file should not exist\n" );
1894 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1895 ok( !fileDeleted, "file should exist\n" );
1897 CloseHandle( handle );
1898 HeapFree( GetProcessHeap(), 0, fri );
1899 delete_object( oldpath );
1900 delete_object( newpath );
1902 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1903 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1904 ok( res != 0, "failed to create temp file\n" );
1905 DeleteFileW( oldpath );
1906 success = CreateDirectoryW( oldpath, NULL );
1907 ok( success != 0, "failed to create temp directory\n" );
1908 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1909 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1911 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1912 ok( res != 0, "failed to create temp file\n" );
1913 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1914 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1916 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1917 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1918 fri->Replace = TRUE;
1919 fri->RootDir = NULL;
1920 fri->FileNameLength = name_str.Length;
1921 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1922 pRtlFreeUnicodeString( &name_str );
1924 U(io).Status = 0xdeadbeef;
1925 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1926 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1927 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1928 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1929 ok( !fileDeleted, "file should exist\n" );
1930 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1931 ok( !fileDeleted, "file should exist\n" );
1933 CloseHandle( handle );
1934 CloseHandle( handle2 );
1935 HeapFree( GetProcessHeap(), 0, fri );
1936 delete_object( oldpath );
1937 delete_object( newpath );
1939 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1940 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1941 ok( res != 0, "failed to create temp file\n" );
1942 DeleteFileW( oldpath );
1943 success = CreateDirectoryW( oldpath, NULL );
1944 ok( success != 0, "failed to create temp directory\n" );
1945 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1946 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1948 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1949 ok( res != 0, "failed to create temp file\n" );
1950 DeleteFileW( newpath );
1951 success = CreateDirectoryW( newpath, NULL );
1952 ok( success != 0, "failed to create temp directory\n" );
1953 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1954 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1955 fri->Replace = FALSE;
1956 fri->RootDir = NULL;
1957 fri->FileNameLength = name_str.Length;
1958 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1959 pRtlFreeUnicodeString( &name_str );
1961 U(io).Status = 0xdeadbeef;
1962 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1963 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1964 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1965 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1966 ok( !fileDeleted, "file should exist\n" );
1967 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1968 ok( !fileDeleted, "file should exist\n" );
1970 CloseHandle( handle );
1971 HeapFree( GetProcessHeap(), 0, fri );
1972 delete_object( oldpath );
1973 delete_object( newpath );
1975 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1976 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1977 ok( res != 0, "failed to create temp file\n" );
1978 DeleteFileW( oldpath );
1979 success = CreateDirectoryW( oldpath, NULL );
1980 ok( success != 0, "failed to create temp directory\n" );
1981 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1982 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1984 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1985 ok( res != 0, "failed to create temp file\n" );
1986 DeleteFileW( newpath );
1987 success = CreateDirectoryW( newpath, NULL );
1988 ok( success != 0, "failed to create temp directory\n" );
1989 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1990 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1991 fri->Replace = TRUE;
1992 fri->RootDir = NULL;
1993 fri->FileNameLength = name_str.Length;
1994 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1995 pRtlFreeUnicodeString( &name_str );
1997 U(io).Status = 0xdeadbeef;
1998 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1999 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2000 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2001 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2002 ok( !fileDeleted, "file should exist\n" );
2003 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2004 ok( !fileDeleted, "file should exist\n" );
2006 CloseHandle( handle );
2007 HeapFree( GetProcessHeap(), 0, fri );
2008 delete_object( oldpath );
2009 delete_object( newpath );
2011 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
2012 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2013 ok( res != 0, "failed to create temp file\n" );
2014 DeleteFileW( oldpath );
2015 success = CreateDirectoryW( oldpath, NULL );
2016 ok( success != 0, "failed to create temp directory\n" );
2017 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2018 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2020 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2021 ok( res != 0, "failed to create temp file\n" );
2022 DeleteFileW( newpath );
2023 success = CreateDirectoryW( newpath, NULL );
2024 ok( success != 0, "failed to create temp directory\n" );
2025 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2026 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2028 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2029 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2030 fri->Replace = TRUE;
2031 fri->RootDir = NULL;
2032 fri->FileNameLength = name_str.Length;
2033 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2034 pRtlFreeUnicodeString( &name_str );
2036 U(io).Status = 0xdeadbeef;
2037 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2038 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2039 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2040 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2041 ok( !fileDeleted, "file should exist\n" );
2042 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2043 ok( !fileDeleted, "file should exist\n" );
2045 CloseHandle( handle );
2046 CloseHandle( handle2 );
2047 HeapFree( GetProcessHeap(), 0, fri );
2048 delete_object( oldpath );
2049 delete_object( newpath );
2051 /* oldpath is a file, newpath is a directory, Replace = FALSE */
2052 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2053 ok( res != 0, "failed to create temp file\n" );
2054 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2055 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2057 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2058 ok( res != 0, "failed to create temp file\n" );
2059 DeleteFileW( newpath );
2060 success = CreateDirectoryW( newpath, NULL );
2061 ok( success != 0, "failed to create temp directory\n" );
2062 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2063 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2064 fri->Replace = FALSE;
2065 fri->RootDir = NULL;
2066 fri->FileNameLength = name_str.Length;
2067 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2068 pRtlFreeUnicodeString( &name_str );
2070 U(io).Status = 0xdeadbeef;
2071 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2072 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2073 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2074 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2075 ok( !fileDeleted, "file should exist\n" );
2076 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2077 ok( !fileDeleted, "file should exist\n" );
2079 CloseHandle( handle );
2080 HeapFree( GetProcessHeap(), 0, fri );
2081 delete_object( oldpath );
2082 delete_object( newpath );
2084 /* oldpath is a file, newpath is a directory, Replace = TRUE */
2085 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2086 ok( res != 0, "failed to create temp file\n" );
2087 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2088 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2090 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2091 ok( res != 0, "failed to create temp file\n" );
2092 DeleteFileW( newpath );
2093 success = CreateDirectoryW( newpath, NULL );
2094 ok( success != 0, "failed to create temp directory\n" );
2095 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2096 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
2097 fri->Replace = TRUE;
2098 fri->RootDir = NULL;
2099 fri->FileNameLength = name_str.Length;
2100 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
2101 pRtlFreeUnicodeString( &name_str );
2103 U(io).Status = 0xdeadbeef;
2104 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2105 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2106 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2107 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2108 ok( !fileDeleted, "file should exist\n" );
2109 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2110 ok( !fileDeleted, "file should exist\n" );
2112 CloseHandle( handle );
2113 HeapFree( GetProcessHeap(), 0, fri );
2114 delete_object( oldpath );
2115 delete_object( newpath );
2117 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
2118 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2119 ok( res != 0, "failed to create temp file\n" );
2120 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2121 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2123 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2124 ok( res != 0, "failed to create temp file\n" );
2125 DeleteFileW( newpath );
2126 for (filename = newpath, p = newpath; *p; p++)
2127 if (*p == '\\') filename = p + 1;
2128 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2129 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2131 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2132 fri->Replace = FALSE;
2133 fri->RootDir = handle2;
2134 fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2135 memcpy( fri->FileName, filename, fri->FileNameLength );
2137 U(io).Status = 0xdeadbeef;
2138 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
2139 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2140 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2141 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2142 ok( fileDeleted, "file should not exist\n" );
2143 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2144 ok( !fileDeleted, "file should exist\n" );
2146 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2147 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2148 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2149 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2150 todo_wine ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
2151 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
2152 HeapFree( GetProcessHeap(), 0, fni );
2154 CloseHandle( handle );
2155 CloseHandle( handle2 );
2156 HeapFree( GetProcessHeap(), 0, fri );
2157 delete_object( oldpath );
2158 delete_object( newpath );
2161 static void test_file_link_information(void)
2163 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
2164 static const WCHAR fooW[] = {'f','o','o',0};
2165 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
2166 FILE_LINK_INFORMATION *fli;
2167 FILE_NAME_INFORMATION *fni;
2168 BOOL success, fileDeleted;
2169 UNICODE_STRING name_str;
2170 HANDLE handle, handle2;
2171 IO_STATUS_BLOCK io;
2172 NTSTATUS res;
2174 GetTempPathW( MAX_PATH, tmp_path );
2176 /* oldpath is a file, newpath doesn't exist */
2177 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2178 ok( res != 0, "failed to create temp file\n" );
2179 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2180 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2182 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2183 ok( res != 0, "failed to create temp file\n" );
2184 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2185 DeleteFileW( newpath );
2186 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2187 fli->ReplaceIfExists = FALSE;
2188 fli->RootDirectory = NULL;
2189 fli->FileNameLength = name_str.Length;
2190 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2191 pRtlFreeUnicodeString( &name_str );
2193 U(io).Status = 0xdeadbeef;
2194 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2195 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2196 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2197 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2198 ok( !fileDeleted, "file should exist\n" );
2199 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2200 ok( !fileDeleted, "file should exist\n" );
2202 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2203 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2204 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2205 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2206 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2207 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2208 HeapFree( GetProcessHeap(), 0, fni );
2210 CloseHandle( handle );
2211 HeapFree( GetProcessHeap(), 0, fli );
2212 delete_object( oldpath );
2213 delete_object( newpath );
2215 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2216 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2217 ok( res != 0, "failed to create temp file\n" );
2218 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2219 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2221 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2222 ok( res != 0, "failed to create temp file\n" );
2223 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2224 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2225 fli->ReplaceIfExists = FALSE;
2226 fli->RootDirectory = NULL;
2227 fli->FileNameLength = name_str.Length;
2228 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2229 pRtlFreeUnicodeString( &name_str );
2231 U(io).Status = 0xdeadbeef;
2232 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2233 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2234 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2235 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2236 ok( !fileDeleted, "file should exist\n" );
2237 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2238 ok( !fileDeleted, "file should exist\n" );
2240 CloseHandle( handle );
2241 HeapFree( GetProcessHeap(), 0, fli );
2242 delete_object( oldpath );
2243 delete_object( newpath );
2245 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2246 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2247 ok( res != 0, "failed to create temp file\n" );
2248 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2249 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2251 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2252 ok( res != 0, "failed to create temp file\n" );
2253 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2254 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2255 fli->ReplaceIfExists = TRUE;
2256 fli->RootDirectory = NULL;
2257 fli->FileNameLength = name_str.Length;
2258 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2259 pRtlFreeUnicodeString( &name_str );
2261 U(io).Status = 0xdeadbeef;
2262 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2263 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2264 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2265 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2266 ok( !fileDeleted, "file should exist\n" );
2267 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2268 ok( !fileDeleted, "file should exist\n" );
2270 CloseHandle( handle );
2271 HeapFree( GetProcessHeap(), 0, fli );
2272 delete_object( oldpath );
2273 delete_object( newpath );
2275 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2276 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2277 ok( res != 0, "failed to create temp file\n" );
2278 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2279 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2281 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2282 ok( res != 0, "failed to create temp file\n" );
2283 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2284 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2286 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2287 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2288 fli->ReplaceIfExists = FALSE;
2289 fli->RootDirectory = NULL;
2290 fli->FileNameLength = name_str.Length;
2291 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2292 pRtlFreeUnicodeString( &name_str );
2294 U(io).Status = 0xdeadbeef;
2295 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2296 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2297 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2298 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2299 ok( !fileDeleted, "file should exist\n" );
2300 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2301 ok( !fileDeleted, "file should exist\n" );
2303 CloseHandle( handle );
2304 CloseHandle( handle2 );
2305 HeapFree( GetProcessHeap(), 0, fli );
2306 delete_object( oldpath );
2307 delete_object( newpath );
2309 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2310 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2311 ok( res != 0, "failed to create temp file\n" );
2312 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2313 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2315 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2316 ok( res != 0, "failed to create temp file\n" );
2317 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2318 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2320 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2321 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2322 fli->ReplaceIfExists = TRUE;
2323 fli->RootDirectory = NULL;
2324 fli->FileNameLength = name_str.Length;
2325 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2326 pRtlFreeUnicodeString( &name_str );
2328 U(io).Status = 0xdeadbeef;
2329 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2330 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2331 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2332 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2333 ok( !fileDeleted, "file should exist\n" );
2334 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2335 ok( !fileDeleted, "file should exist\n" );
2337 CloseHandle( handle );
2338 CloseHandle( handle2 );
2339 HeapFree( GetProcessHeap(), 0, fli );
2340 delete_object( oldpath );
2341 delete_object( newpath );
2343 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2344 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2345 ok( res != 0, "failed to create temp file\n" );
2346 DeleteFileW( oldpath );
2347 success = CreateDirectoryW( oldpath, NULL );
2348 ok( success != 0, "failed to create temp directory\n" );
2349 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2350 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2352 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2353 ok( res != 0, "failed to create temp file\n" );
2354 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2355 DeleteFileW( newpath );
2356 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2357 fli->ReplaceIfExists = FALSE;
2358 fli->RootDirectory = NULL;
2359 fli->FileNameLength = name_str.Length;
2360 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2361 pRtlFreeUnicodeString( &name_str );
2363 U(io).Status = 0xdeadbeef;
2364 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2365 todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2366 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2367 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2368 ok( !fileDeleted, "file should exist\n" );
2369 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2370 ok( fileDeleted, "file should not exist\n" );
2372 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2373 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2374 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2375 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2376 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2377 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2378 HeapFree( GetProcessHeap(), 0, fni );
2380 CloseHandle( handle );
2381 HeapFree( GetProcessHeap(), 0, fli );
2382 delete_object( oldpath );
2383 delete_object( newpath );
2385 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2386 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2387 ok( res != 0, "failed to create temp file\n" );
2388 DeleteFileW( oldpath );
2389 success = CreateDirectoryW( oldpath, NULL );
2390 ok( success != 0, "failed to create temp directory\n" );
2391 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2392 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2394 lstrcpyW( newpath, oldpath );
2395 lstrcatW( newpath, foo_txtW );
2396 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2397 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2399 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2400 ok( res != 0, "failed to create temp file\n" );
2401 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2402 DeleteFileW( newpath );
2403 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2404 fli->ReplaceIfExists = FALSE;
2405 fli->RootDirectory = NULL;
2406 fli->FileNameLength = name_str.Length;
2407 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2408 pRtlFreeUnicodeString( &name_str );
2410 U(io).Status = 0xdeadbeef;
2411 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2412 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2413 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2414 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2415 ok( !fileDeleted, "file should exist\n" );
2416 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2417 ok( fileDeleted, "file should not exist\n" );
2419 CloseHandle( handle );
2420 CloseHandle( handle2 );
2421 HeapFree( GetProcessHeap(), 0, fli );
2422 delete_object( oldpath );
2423 delete_object( newpath );
2425 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2426 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2427 ok( res != 0, "failed to create temp file\n" );
2428 DeleteFileW( oldpath );
2429 success = CreateDirectoryW( oldpath, NULL );
2430 ok( success != 0, "failed to create temp directory\n" );
2431 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2432 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2434 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2435 ok( res != 0, "failed to create temp file\n" );
2436 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2437 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2438 fli->ReplaceIfExists = FALSE;
2439 fli->RootDirectory = NULL;
2440 fli->FileNameLength = name_str.Length;
2441 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2442 pRtlFreeUnicodeString( &name_str );
2444 U(io).Status = 0xdeadbeef;
2445 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2446 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2447 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2448 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2449 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2450 ok( !fileDeleted, "file should exist\n" );
2451 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2452 ok( !fileDeleted, "file should exist\n" );
2454 CloseHandle( handle );
2455 HeapFree( GetProcessHeap(), 0, fli );
2456 delete_object( oldpath );
2457 delete_object( newpath );
2459 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2460 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2461 ok( res != 0, "failed to create temp file\n" );
2462 DeleteFileW( oldpath );
2463 success = CreateDirectoryW( oldpath, NULL );
2464 ok( success != 0, "failed to create temp directory\n" );
2465 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2466 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2468 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2469 ok( res != 0, "failed to create temp file\n" );
2470 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2471 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2473 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2474 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2475 fli->ReplaceIfExists = FALSE;
2476 fli->RootDirectory = NULL;
2477 fli->FileNameLength = name_str.Length;
2478 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2479 pRtlFreeUnicodeString( &name_str );
2481 U(io).Status = 0xdeadbeef;
2482 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2483 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2484 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2485 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2486 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2487 ok( !fileDeleted, "file should exist\n" );
2488 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2489 ok( !fileDeleted, "file should exist\n" );
2491 CloseHandle( handle );
2492 CloseHandle( handle2 );
2493 HeapFree( GetProcessHeap(), 0, fli );
2494 delete_object( oldpath );
2495 delete_object( newpath );
2497 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2498 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2499 ok( res != 0, "failed to create temp file\n" );
2500 DeleteFileW( oldpath );
2501 success = CreateDirectoryW( oldpath, NULL );
2502 ok( success != 0, "failed to create temp directory\n" );
2503 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2504 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2506 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2507 ok( res != 0, "failed to create temp file\n" );
2508 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2509 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2510 fli->ReplaceIfExists = TRUE;
2511 fli->RootDirectory = NULL;
2512 fli->FileNameLength = name_str.Length;
2513 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2514 pRtlFreeUnicodeString( &name_str );
2516 U(io).Status = 0xdeadbeef;
2517 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2518 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2519 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2520 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2521 ok( !fileDeleted, "file should exist\n" );
2522 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2523 ok( !fileDeleted, "file should exist\n" );
2525 CloseHandle( handle );
2526 HeapFree( GetProcessHeap(), 0, fli );
2527 delete_object( oldpath );
2528 delete_object( newpath );
2530 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2531 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2532 ok( res != 0, "failed to create temp file\n" );
2533 DeleteFileW( oldpath );
2534 success = CreateDirectoryW( oldpath, NULL );
2535 ok( success != 0, "failed to create temp directory\n" );
2536 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2537 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2539 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2540 ok( res != 0, "failed to create temp file\n" );
2541 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2542 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2544 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2545 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2546 fli->ReplaceIfExists = TRUE;
2547 fli->RootDirectory = NULL;
2548 fli->FileNameLength = name_str.Length;
2549 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2550 pRtlFreeUnicodeString( &name_str );
2552 U(io).Status = 0xdeadbeef;
2553 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2554 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2555 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2556 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2557 ok( !fileDeleted, "file should exist\n" );
2558 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2559 ok( !fileDeleted, "file should exist\n" );
2561 CloseHandle( handle );
2562 CloseHandle( handle2 );
2563 HeapFree( GetProcessHeap(), 0, fli );
2564 delete_object( oldpath );
2565 delete_object( newpath );
2567 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2568 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2569 ok( res != 0, "failed to create temp file\n" );
2570 DeleteFileW( oldpath );
2571 success = CreateDirectoryW( oldpath, NULL );
2572 ok( success != 0, "failed to create temp directory\n" );
2573 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2574 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2576 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2577 ok( res != 0, "failed to create temp file\n" );
2578 DeleteFileW( newpath );
2579 success = CreateDirectoryW( newpath, NULL );
2580 ok( success != 0, "failed to create temp directory\n" );
2581 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2582 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2583 fli->ReplaceIfExists = FALSE;
2584 fli->RootDirectory = NULL;
2585 fli->FileNameLength = name_str.Length;
2586 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2587 pRtlFreeUnicodeString( &name_str );
2589 U(io).Status = 0xdeadbeef;
2590 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2591 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2592 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2593 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2594 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2595 ok( !fileDeleted, "file should exist\n" );
2596 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2597 ok( !fileDeleted, "file should exist\n" );
2599 CloseHandle( handle );
2600 HeapFree( GetProcessHeap(), 0, fli );
2601 delete_object( oldpath );
2602 delete_object( newpath );
2604 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2605 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2606 ok( res != 0, "failed to create temp file\n" );
2607 DeleteFileW( oldpath );
2608 success = CreateDirectoryW( oldpath, NULL );
2609 ok( success != 0, "failed to create temp directory\n" );
2610 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2611 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2613 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2614 ok( res != 0, "failed to create temp file\n" );
2615 DeleteFileW( newpath );
2616 success = CreateDirectoryW( newpath, NULL );
2617 ok( success != 0, "failed to create temp directory\n" );
2618 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2619 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2620 fli->ReplaceIfExists = TRUE;
2621 fli->RootDirectory = NULL;
2622 fli->FileNameLength = name_str.Length;
2623 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2624 pRtlFreeUnicodeString( &name_str );
2626 U(io).Status = 0xdeadbeef;
2627 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2628 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2629 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2630 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2631 ok( !fileDeleted, "file should exist\n" );
2632 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2633 ok( !fileDeleted, "file should exist\n" );
2635 CloseHandle( handle );
2636 HeapFree( GetProcessHeap(), 0, fli );
2637 delete_object( oldpath );
2638 delete_object( newpath );
2640 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2641 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2642 ok( res != 0, "failed to create temp file\n" );
2643 DeleteFileW( oldpath );
2644 success = CreateDirectoryW( oldpath, NULL );
2645 ok( success != 0, "failed to create temp directory\n" );
2646 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2647 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2649 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2650 ok( res != 0, "failed to create temp file\n" );
2651 DeleteFileW( newpath );
2652 success = CreateDirectoryW( newpath, NULL );
2653 ok( success != 0, "failed to create temp directory\n" );
2654 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2655 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2657 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2658 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2659 fli->ReplaceIfExists = TRUE;
2660 fli->RootDirectory = NULL;
2661 fli->FileNameLength = name_str.Length;
2662 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2663 pRtlFreeUnicodeString( &name_str );
2665 U(io).Status = 0xdeadbeef;
2666 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2667 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2668 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2669 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2670 ok( !fileDeleted, "file should exist\n" );
2671 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2672 ok( !fileDeleted, "file should exist\n" );
2674 CloseHandle( handle );
2675 CloseHandle( handle2 );
2676 HeapFree( GetProcessHeap(), 0, fli );
2677 delete_object( oldpath );
2678 delete_object( newpath );
2680 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2681 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2682 ok( res != 0, "failed to create temp file\n" );
2683 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2684 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2686 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2687 ok( res != 0, "failed to create temp file\n" );
2688 DeleteFileW( newpath );
2689 success = CreateDirectoryW( newpath, NULL );
2690 ok( success != 0, "failed to create temp directory\n" );
2691 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2692 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2693 fli->ReplaceIfExists = FALSE;
2694 fli->RootDirectory = NULL;
2695 fli->FileNameLength = name_str.Length;
2696 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2697 pRtlFreeUnicodeString( &name_str );
2699 U(io).Status = 0xdeadbeef;
2700 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2701 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2702 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2703 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2704 ok( !fileDeleted, "file should exist\n" );
2705 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2706 ok( !fileDeleted, "file should exist\n" );
2708 CloseHandle( handle );
2709 HeapFree( GetProcessHeap(), 0, fli );
2710 delete_object( oldpath );
2711 delete_object( newpath );
2713 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2714 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2715 ok( res != 0, "failed to create temp file\n" );
2716 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2717 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2719 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2720 ok( res != 0, "failed to create temp file\n" );
2721 DeleteFileW( newpath );
2722 success = CreateDirectoryW( newpath, NULL );
2723 ok( success != 0, "failed to create temp directory\n" );
2724 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2725 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2726 fli->ReplaceIfExists = TRUE;
2727 fli->RootDirectory = NULL;
2728 fli->FileNameLength = name_str.Length;
2729 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2730 pRtlFreeUnicodeString( &name_str );
2732 U(io).Status = 0xdeadbeef;
2733 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2734 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2735 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2736 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2737 ok( !fileDeleted, "file should exist\n" );
2738 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2739 ok( !fileDeleted, "file should exist\n" );
2741 CloseHandle( handle );
2742 HeapFree( GetProcessHeap(), 0, fli );
2743 delete_object( oldpath );
2744 delete_object( newpath );
2746 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2747 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2748 ok( res != 0, "failed to create temp file\n" );
2749 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2750 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2752 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2753 ok( res != 0, "failed to create temp file\n" );
2754 DeleteFileW( newpath );
2755 for (filename = newpath, p = newpath; *p; p++)
2756 if (*p == '\\') filename = p + 1;
2757 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2758 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2760 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2761 fli->ReplaceIfExists = FALSE;
2762 fli->RootDirectory = handle2;
2763 fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2764 memcpy( fli->FileName, filename, fli->FileNameLength );
2766 U(io).Status = 0xdeadbeef;
2767 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2768 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2769 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2770 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2771 ok( !fileDeleted, "file should exist\n" );
2772 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2773 ok( !fileDeleted, "file should exist\n" );
2775 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2776 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2777 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2778 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2779 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2780 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2781 HeapFree( GetProcessHeap(), 0, fni );
2783 CloseHandle( handle );
2784 CloseHandle( handle2 );
2785 HeapFree( GetProcessHeap(), 0, fli );
2786 delete_object( oldpath );
2787 delete_object( newpath );
2790 static void test_file_both_information(void)
2792 IO_STATUS_BLOCK io;
2793 FILE_BOTH_DIR_INFORMATION fbi;
2794 HANDLE h;
2795 int res;
2797 if (!(h = create_temp_file(0))) return;
2799 memset(&fbi, 0, sizeof(fbi));
2800 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
2801 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
2803 CloseHandle( h );
2806 static void test_file_disposition_information(void)
2808 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
2809 DWORD dirpos;
2810 HANDLE handle, handle2;
2811 NTSTATUS res;
2812 IO_STATUS_BLOCK io;
2813 FILE_DISPOSITION_INFORMATION fdi;
2814 BOOL fileDeleted;
2815 DWORD fdi2;
2817 GetTempPathA( MAX_PATH, tmp_path );
2819 /* tests for info struct size */
2820 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2821 handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2822 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2823 res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
2824 todo_wine
2825 ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %x\n", res );
2826 fdi2 = 0x100;
2827 res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
2828 ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x\n", res );
2829 CloseHandle( handle );
2830 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2831 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2832 DeleteFileA( buffer );
2834 /* cannot set disposition on file not opened with delete access */
2835 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2836 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2837 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2838 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2839 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
2840 fdi.DoDeleteFile = TRUE;
2841 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2842 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
2843 CloseHandle( handle );
2844 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2845 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2846 DeleteFileA( buffer );
2848 /* can set disposition on file opened with proper access */
2849 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2850 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2851 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2852 fdi.DoDeleteFile = TRUE;
2853 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2854 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2855 CloseHandle( handle );
2856 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2857 ok( fileDeleted, "File should have been deleted\n" );
2858 DeleteFileA( buffer );
2860 /* cannot set disposition on readonly file */
2861 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2862 DeleteFileA( buffer );
2863 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2864 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2865 fdi.DoDeleteFile = TRUE;
2866 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2867 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2868 CloseHandle( handle );
2869 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2870 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2871 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2872 DeleteFileA( buffer );
2874 /* cannot set disposition on readonly file */
2875 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2876 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2877 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2878 fdi.DoDeleteFile = TRUE;
2879 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2880 todo_wine
2881 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2882 CloseHandle( handle );
2883 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2884 todo_wine
2885 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2886 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2887 DeleteFileA( buffer );
2889 /* can set disposition on file and then reset it */
2890 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2891 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2892 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2893 fdi.DoDeleteFile = TRUE;
2894 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2895 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2896 fdi.DoDeleteFile = FALSE;
2897 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2898 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2899 CloseHandle( handle );
2900 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2901 ok( !fileDeleted, "File shouldn't have been deleted\n" );
2902 DeleteFileA( buffer );
2904 /* Delete-on-close flag doesn't change file disposition until a handle is closed */
2905 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2906 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2907 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2908 fdi.DoDeleteFile = FALSE;
2909 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2910 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2911 CloseHandle( handle );
2912 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2913 ok( fileDeleted, "File should have been deleted\n" );
2914 DeleteFileA( buffer );
2916 /* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
2917 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2918 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2919 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2920 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
2921 CloseHandle( handle );
2922 fdi.DoDeleteFile = FALSE;
2923 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
2924 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2925 CloseHandle( handle2 );
2926 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2927 ok( fileDeleted, "File should have been deleted\n" );
2928 DeleteFileA( buffer );
2930 /* can set disposition on a directory opened with proper access */
2931 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2932 DeleteFileA( buffer );
2933 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2934 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2935 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2936 fdi.DoDeleteFile = TRUE;
2937 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2938 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2939 CloseHandle( handle );
2940 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2941 ok( fileDeleted, "Directory should have been deleted\n" );
2942 RemoveDirectoryA( buffer );
2944 /* RemoveDirectory sets directory disposition and it can be undone */
2945 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2946 DeleteFileA( buffer );
2947 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2948 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2949 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2950 RemoveDirectoryA( buffer );
2951 fdi.DoDeleteFile = FALSE;
2952 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2953 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2954 CloseHandle( handle );
2955 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2956 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2957 RemoveDirectoryA( buffer );
2959 /* cannot set disposition on a non-empty directory */
2960 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2961 DeleteFileA( buffer );
2962 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2963 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2964 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2965 dirpos = lstrlenA( buffer );
2966 lstrcpyA( buffer + dirpos, "\\tst" );
2967 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2968 CloseHandle( handle2 );
2969 fdi.DoDeleteFile = TRUE;
2970 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2971 todo_wine
2972 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
2973 DeleteFileA( buffer );
2974 buffer[dirpos] = '\0';
2975 CloseHandle( handle );
2976 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2977 todo_wine
2978 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2979 RemoveDirectoryA( buffer );
2982 static void test_iocompletion(void)
2984 HANDLE h = INVALID_HANDLE_VALUE;
2985 NTSTATUS res;
2987 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
2989 ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
2990 ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
2992 if ( h && h != INVALID_HANDLE_VALUE)
2994 test_iocp_setcompletion(h);
2995 test_iocp_fileio(h);
2996 pNtClose(h);
3000 static void test_file_name_information(void)
3002 WCHAR *file_name, *volume_prefix, *expected;
3003 FILE_NAME_INFORMATION *info;
3004 ULONG old_redir = 1, tmp;
3005 UINT file_name_size;
3006 IO_STATUS_BLOCK io;
3007 UINT info_size;
3008 HRESULT hr;
3009 HANDLE h;
3010 UINT len;
3012 /* GetVolumePathName is not present before w2k */
3013 if (!pGetVolumePathNameW) {
3014 win_skip("GetVolumePathNameW not found\n");
3015 return;
3018 file_name_size = GetSystemDirectoryW( NULL, 0 );
3019 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3020 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3021 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3023 len = GetSystemDirectoryW( file_name, file_name_size );
3024 ok(len == file_name_size - 1,
3025 "GetSystemDirectoryW returned %u, expected %u.\n",
3026 len, file_name_size - 1);
3028 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3029 ok(len, "GetVolumePathNameW failed.\n");
3031 len = lstrlenW( volume_prefix );
3032 if (len && volume_prefix[len - 1] == '\\') --len;
3033 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3034 expected[file_name_size - len - 1] = '\0';
3036 /* A bit more than we actually need, but it keeps the calculation simple. */
3037 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3038 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3040 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3041 h = CreateFileW( file_name, GENERIC_READ,
3042 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3043 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3044 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3045 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3047 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
3048 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
3050 memset( info, 0xcc, info_size );
3051 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
3052 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3053 hr, STATUS_BUFFER_OVERFLOW);
3054 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3055 U(io).Status, STATUS_BUFFER_OVERFLOW);
3056 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
3057 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
3058 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3059 "info->FileName[1] is %p, expected %p.\n",
3060 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3061 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3063 memset( info, 0xcc, info_size );
3064 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3065 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3066 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3067 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
3068 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
3069 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
3070 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3071 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3072 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3073 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
3074 "io.Information is %lu, expected %u.\n",
3075 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
3077 CloseHandle( h );
3078 HeapFree( GetProcessHeap(), 0, info );
3079 HeapFree( GetProcessHeap(), 0, expected );
3080 HeapFree( GetProcessHeap(), 0, volume_prefix );
3082 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3084 skip("Not running on WoW64, skipping test.\n");
3085 HeapFree( GetProcessHeap(), 0, file_name );
3086 return;
3089 h = CreateFileW( file_name, GENERIC_READ,
3090 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3091 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3092 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3093 HeapFree( GetProcessHeap(), 0, file_name );
3095 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3096 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3097 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3099 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3100 ok(len == file_name_size - 1,
3101 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3102 len, file_name_size - 1);
3104 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3105 ok(len, "GetVolumePathNameW failed.\n");
3107 len = lstrlenW( volume_prefix );
3108 if (len && volume_prefix[len - 1] == '\\') --len;
3109 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3110 expected[file_name_size - len - 1] = '\0';
3112 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3113 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3115 memset( info, 0xcc, info_size );
3116 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3117 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3118 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3119 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3120 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3122 CloseHandle( h );
3123 HeapFree( GetProcessHeap(), 0, info );
3124 HeapFree( GetProcessHeap(), 0, expected );
3125 HeapFree( GetProcessHeap(), 0, volume_prefix );
3126 HeapFree( GetProcessHeap(), 0, file_name );
3129 static void test_file_all_name_information(void)
3131 WCHAR *file_name, *volume_prefix, *expected;
3132 FILE_ALL_INFORMATION *info;
3133 ULONG old_redir = 1, tmp;
3134 UINT file_name_size;
3135 IO_STATUS_BLOCK io;
3136 UINT info_size;
3137 HRESULT hr;
3138 HANDLE h;
3139 UINT len;
3141 /* GetVolumePathName is not present before w2k */
3142 if (!pGetVolumePathNameW) {
3143 win_skip("GetVolumePathNameW not found\n");
3144 return;
3147 file_name_size = GetSystemDirectoryW( NULL, 0 );
3148 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3149 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3150 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3152 len = GetSystemDirectoryW( file_name, file_name_size );
3153 ok(len == file_name_size - 1,
3154 "GetSystemDirectoryW returned %u, expected %u.\n",
3155 len, file_name_size - 1);
3157 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3158 ok(len, "GetVolumePathNameW failed.\n");
3160 len = lstrlenW( volume_prefix );
3161 if (len && volume_prefix[len - 1] == '\\') --len;
3162 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3163 expected[file_name_size - len - 1] = '\0';
3165 /* A bit more than we actually need, but it keeps the calculation simple. */
3166 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3167 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3169 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3170 h = CreateFileW( file_name, GENERIC_READ,
3171 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3172 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3173 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3174 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3176 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
3177 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
3178 hr, STATUS_INFO_LENGTH_MISMATCH);
3180 memset( info, 0xcc, info_size );
3181 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
3182 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3183 hr, STATUS_BUFFER_OVERFLOW);
3184 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3185 U(io).Status, STATUS_BUFFER_OVERFLOW);
3186 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3187 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3188 ok(info->NameInformation.FileName[2] == 0xcccc,
3189 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
3190 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3191 "info->NameInformation.FileName[1] is %p, expected %p.\n",
3192 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3193 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3195 memset( info, 0xcc, info_size );
3196 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3197 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3198 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3199 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3200 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3201 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
3202 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3203 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
3204 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3205 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
3206 "info->NameInformation.FileName is %s, expected %s.\n",
3207 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3208 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
3209 + info->NameInformation.FileNameLength,
3210 "io.Information is %lu\n", io.Information );
3212 CloseHandle( h );
3213 HeapFree( GetProcessHeap(), 0, info );
3214 HeapFree( GetProcessHeap(), 0, expected );
3215 HeapFree( GetProcessHeap(), 0, volume_prefix );
3217 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3219 skip("Not running on WoW64, skipping test.\n");
3220 HeapFree( GetProcessHeap(), 0, file_name );
3221 return;
3224 h = CreateFileW( file_name, GENERIC_READ,
3225 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3226 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3227 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3228 HeapFree( GetProcessHeap(), 0, file_name );
3230 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3231 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3232 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3234 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3235 ok(len == file_name_size - 1,
3236 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3237 len, file_name_size - 1);
3239 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3240 ok(len, "GetVolumePathNameW failed.\n");
3242 len = lstrlenW( volume_prefix );
3243 if (len && volume_prefix[len - 1] == '\\') --len;
3244 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3245 expected[file_name_size - len - 1] = '\0';
3247 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3248 info = HeapAlloc( GetProcessHeap(), 0, info_size );
3250 memset( info, 0xcc, info_size );
3251 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3252 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3253 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3254 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
3255 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3257 CloseHandle( h );
3258 HeapFree( GetProcessHeap(), 0, info );
3259 HeapFree( GetProcessHeap(), 0, expected );
3260 HeapFree( GetProcessHeap(), 0, volume_prefix );
3261 HeapFree( GetProcessHeap(), 0, file_name );
3264 static void test_file_id_information(void)
3266 BY_HANDLE_FILE_INFORMATION info;
3267 FILE_ID_INFORMATION fid;
3268 IO_STATUS_BLOCK io;
3269 NTSTATUS status;
3270 DWORD *dwords;
3271 HANDLE h;
3272 BOOL ret;
3274 if (!(h = create_temp_file(0))) return;
3276 memset( &fid, 0x11, sizeof(fid) );
3277 status = pNtQueryInformationFile( h, &io, &fid, sizeof(fid), FileIdInformation );
3278 if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
3280 win_skip( "FileIdInformation not supported\n" );
3281 CloseHandle( h );
3282 return;
3285 memset( &info, 0x22, sizeof(info) );
3286 ret = GetFileInformationByHandle( h, &info );
3287 ok( ret, "GetFileInformationByHandle failed\n" );
3289 dwords = (DWORD *)&fid.VolumeSerialNumber;
3290 ok( dwords[0] == info.dwVolumeSerialNumber, "expected %08x, got %08x\n",
3291 info.dwVolumeSerialNumber, dwords[0] );
3292 ok( dwords[1] != 0x11111111, "expected != 0x11111111\n" );
3294 dwords = (DWORD *)&fid.FileId;
3295 ok( dwords[0] == info.nFileIndexLow, "expected %08x, got %08x\n", info.nFileIndexLow, dwords[0] );
3296 ok( dwords[1] == info.nFileIndexHigh, "expected %08x, got %08x\n", info.nFileIndexHigh, dwords[1] );
3297 ok( dwords[2] == 0, "expected 0, got %08x\n", dwords[2] );
3298 ok( dwords[3] == 0, "expected 0, got %08x\n", dwords[3] );
3300 CloseHandle( h );
3303 static void test_query_volume_information_file(void)
3305 NTSTATUS status;
3306 HANDLE dir;
3307 WCHAR path[MAX_PATH];
3308 OBJECT_ATTRIBUTES attr;
3309 IO_STATUS_BLOCK io;
3310 UNICODE_STRING nameW;
3311 FILE_FS_VOLUME_INFORMATION *ffvi;
3312 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3314 GetWindowsDirectoryW( path, MAX_PATH );
3315 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3316 attr.Length = sizeof(attr);
3317 attr.RootDirectory = 0;
3318 attr.ObjectName = &nameW;
3319 attr.Attributes = OBJ_CASE_INSENSITIVE;
3320 attr.SecurityDescriptor = NULL;
3321 attr.SecurityQualityOfService = NULL;
3323 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3324 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3325 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3326 pRtlFreeUnicodeString( &nameW );
3328 ZeroMemory( buf, sizeof(buf) );
3329 U(io).Status = 0xdadadada;
3330 io.Information = 0xcacacaca;
3332 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
3334 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
3336 todo_wine
3338 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3339 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3341 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3342 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3343 io.Information);
3345 ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
3346 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
3347 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
3349 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
3351 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
3353 CloseHandle( dir );
3356 static void test_query_attribute_information_file(void)
3358 NTSTATUS status;
3359 HANDLE dir;
3360 WCHAR path[MAX_PATH];
3361 OBJECT_ATTRIBUTES attr;
3362 IO_STATUS_BLOCK io;
3363 UNICODE_STRING nameW;
3364 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
3365 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3367 GetWindowsDirectoryW( path, MAX_PATH );
3368 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3369 attr.Length = sizeof(attr);
3370 attr.RootDirectory = 0;
3371 attr.ObjectName = &nameW;
3372 attr.Attributes = OBJ_CASE_INSENSITIVE;
3373 attr.SecurityDescriptor = NULL;
3374 attr.SecurityQualityOfService = NULL;
3376 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3377 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3378 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3379 pRtlFreeUnicodeString( &nameW );
3381 ZeroMemory( buf, sizeof(buf) );
3382 U(io).Status = 0xdadadada;
3383 io.Information = 0xcacacaca;
3385 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
3387 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
3389 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3390 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3391 ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
3392 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
3393 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
3395 trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
3396 ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
3397 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
3399 CloseHandle( dir );
3402 static void test_NtCreateFile(void)
3404 static const struct test_data
3406 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
3407 } td[] =
3409 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3410 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
3411 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3412 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3413 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3414 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3415 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3416 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3417 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3418 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3419 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3420 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3421 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3422 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3423 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3424 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3425 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3426 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
3427 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
3429 static const WCHAR fooW[] = {'f','o','o',0};
3430 NTSTATUS status;
3431 HANDLE handle;
3432 WCHAR path[MAX_PATH];
3433 OBJECT_ATTRIBUTES attr;
3434 IO_STATUS_BLOCK io;
3435 UNICODE_STRING nameW;
3436 DWORD ret, i;
3438 GetTempPathW(MAX_PATH, path);
3439 GetTempFileNameW(path, fooW, 0, path);
3440 DeleteFileW(path);
3441 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
3443 attr.Length = sizeof(attr);
3444 attr.RootDirectory = NULL;
3445 attr.ObjectName = &nameW;
3446 attr.Attributes = OBJ_CASE_INSENSITIVE;
3447 attr.SecurityDescriptor = NULL;
3448 attr.SecurityQualityOfService = NULL;
3450 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3452 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
3453 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
3454 td[i].disposition, 0, NULL, 0);
3456 ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
3458 if (!status)
3460 ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
3462 ret = GetFileAttributesW(path);
3463 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
3464 /* FIXME: leave only 'else' case below once Wine is fixed */
3465 if (ret != td[i].attrib_out)
3467 todo_wine
3468 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3469 SetFileAttributesW(path, td[i].attrib_out);
3471 else
3472 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3474 CloseHandle(handle);
3477 if (td[i].needs_cleanup)
3479 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3480 DeleteFileW(path);
3484 pRtlFreeUnicodeString( &nameW );
3485 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3486 DeleteFileW( path );
3489 static void test_read_write(void)
3491 static const char contents[14] = "1234567890abcd";
3492 char buf[256];
3493 HANDLE hfile, event;
3494 OVERLAPPED ovl;
3495 IO_STATUS_BLOCK iob;
3496 DWORD ret, bytes, status, off;
3497 LARGE_INTEGER offset;
3498 LONG i;
3500 event = CreateEventA( NULL, TRUE, FALSE, NULL );
3502 U(iob).Status = -1;
3503 iob.Information = -1;
3504 offset.QuadPart = 0;
3505 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3506 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3507 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3508 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3510 U(iob).Status = -1;
3511 iob.Information = -1;
3512 offset.QuadPart = 0;
3513 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, NULL, sizeof(buf), &offset, NULL);
3514 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3515 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3516 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3518 U(iob).Status = -1;
3519 iob.Information = -1;
3520 offset.QuadPart = 0;
3521 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3522 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3523 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3524 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3526 U(iob).Status = -1;
3527 iob.Information = -1;
3528 offset.QuadPart = 0;
3529 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3530 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3531 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3532 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3534 hfile = create_temp_file(0);
3535 if (!hfile) return;
3537 U(iob).Status = -1;
3538 iob.Information = -1;
3539 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3540 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3541 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3542 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3544 U(iob).Status = -1;
3545 iob.Information = -1;
3546 SetEvent(event);
3547 status = pNtWriteFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3548 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3549 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3550 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3551 ok(!is_signaled(event), "event is not signaled\n");
3553 U(iob).Status = -1;
3554 iob.Information = -1;
3555 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3556 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3557 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3558 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3560 U(iob).Status = -1;
3561 iob.Information = -1;
3562 SetEvent(event);
3563 status = pNtReadFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3564 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3565 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3566 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3567 ok(is_signaled(event), "event is not signaled\n");
3569 U(iob).Status = -1;
3570 iob.Information = -1;
3571 SetEvent(event);
3572 status = pNtReadFile(hfile, event, NULL, NULL, &iob, (void*)0xdeadbeef, sizeof(contents), NULL, NULL);
3573 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3574 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3575 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3576 ok(is_signaled(event), "event is not signaled\n");
3578 U(iob).Status = -1;
3579 iob.Information = -1;
3580 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
3581 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3582 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3583 ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
3585 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3587 U(iob).Status = -1;
3588 iob.Information = -1;
3589 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
3590 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
3591 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3592 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3593 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
3595 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3596 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3598 bytes = 0xdeadbeef;
3599 SetLastError(0xdeadbeef);
3600 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
3601 ok(!ret, "ReadFile should fail\n");
3602 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3603 ok(bytes == 0, "bytes %u\n", bytes);
3605 bytes = 0xdeadbeef;
3606 SetLastError(0xdeadbeef);
3607 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3608 ok(ret, "ReadFile error %d\n", GetLastError());
3609 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3610 ok(bytes == 0, "bytes %u\n", bytes);
3612 bytes = 0xdeadbeef;
3613 SetLastError(0xdeadbeef);
3614 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3615 ok(ret, "ReadFile error %d\n", GetLastError());
3616 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3617 ok(bytes == 0, "bytes %u\n", bytes);
3619 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3621 bytes = 0;
3622 SetLastError(0xdeadbeef);
3623 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3624 ok(ret, "ReadFile error %d\n", GetLastError());
3625 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3626 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3628 for (i = -20; i < -1; i++)
3630 if (i == -2) continue;
3632 U(iob).Status = -1;
3633 iob.Information = -1;
3634 offset.QuadPart = (LONGLONG)i;
3635 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3636 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3637 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3638 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3641 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
3643 U(iob).Status = -1;
3644 iob.Information = -1;
3645 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3646 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3647 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3648 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3649 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3651 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3652 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3654 U(iob).Status = -1;
3655 iob.Information = -1;
3656 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3657 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3658 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3659 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3661 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3663 bytes = 0;
3664 SetLastError(0xdeadbeef);
3665 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3666 ok(ret, "ReadFile error %d\n", GetLastError());
3667 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3668 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3669 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3671 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3672 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3674 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3676 bytes = 0;
3677 SetLastError(0xdeadbeef);
3678 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
3679 ok(ret, "WriteFile error %d\n", GetLastError());
3680 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3682 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3683 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3685 /* test reading beyond EOF */
3686 bytes = -1;
3687 SetLastError(0xdeadbeef);
3688 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3689 ok(ret, "ReadFile error %d\n", GetLastError());
3690 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3691 ok(bytes == 0, "bytes %u\n", bytes);
3693 bytes = -1;
3694 SetLastError(0xdeadbeef);
3695 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3696 ok(ret, "ReadFile error %d\n", GetLastError());
3697 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3698 ok(bytes == 0, "bytes %u\n", bytes);
3700 bytes = -1;
3701 SetLastError(0xdeadbeef);
3702 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
3703 ok(ret, "ReadFile error %d\n", GetLastError());
3704 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3705 ok(bytes == 0, "bytes %u\n", bytes);
3707 S(U(ovl)).Offset = sizeof(contents);
3708 S(U(ovl)).OffsetHigh = 0;
3709 ovl.Internal = -1;
3710 ovl.InternalHigh = -1;
3711 ovl.hEvent = 0;
3712 bytes = -1;
3713 SetLastError(0xdeadbeef);
3714 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3715 ok(!ret, "ReadFile should fail\n");
3716 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
3717 ok(bytes == 0, "bytes %u\n", bytes);
3718 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
3719 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3721 S(U(ovl)).Offset = sizeof(contents);
3722 S(U(ovl)).OffsetHigh = 0;
3723 ovl.Internal = -1;
3724 ovl.InternalHigh = -1;
3725 ovl.hEvent = 0;
3726 bytes = -1;
3727 SetLastError(0xdeadbeef);
3728 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
3729 ok(ret, "ReadFile error %d\n", GetLastError());
3730 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3731 ok(bytes == 0, "bytes %u\n", bytes);
3732 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3733 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3735 U(iob).Status = -1;
3736 iob.Information = -1;
3737 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3738 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3739 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3740 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3742 U(iob).Status = -1;
3743 iob.Information = -1;
3744 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
3745 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3746 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3747 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3749 U(iob).Status = -1;
3750 iob.Information = -1;
3751 offset.QuadPart = sizeof(contents);
3752 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3753 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3754 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3755 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3757 U(iob).Status = -1;
3758 iob.Information = -1;
3759 offset.QuadPart = sizeof(contents);
3760 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3761 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3762 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3763 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3765 U(iob).Status = -1;
3766 iob.Information = -1;
3767 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3768 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3769 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3770 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3771 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3773 U(iob).Status = -1;
3774 iob.Information = -1;
3775 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3776 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3777 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3778 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3779 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3781 for (i = -20; i < 0; i++)
3783 if (i == -2) continue;
3785 U(iob).Status = -1;
3786 iob.Information = -1;
3787 offset.QuadPart = (LONGLONG)i;
3788 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3789 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3790 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3791 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3794 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3796 bytes = 0;
3797 SetLastError(0xdeadbeef);
3798 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3799 ok(ret, "ReadFile error %d\n", GetLastError());
3800 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3801 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3803 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3804 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3806 U(iob).Status = -1;
3807 iob.Information = -1;
3808 offset.QuadPart = 0;
3809 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3810 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3811 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3812 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3813 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3815 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3816 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3818 U(iob).Status = -1;
3819 iob.Information = -1;
3820 offset.QuadPart = sizeof(contents) - 4;
3821 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3822 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3823 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3824 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3826 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3827 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3829 U(iob).Status = -1;
3830 iob.Information = -1;
3831 offset.QuadPart = 0;
3832 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3833 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3834 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3835 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3836 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3837 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3839 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3840 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3842 S(U(ovl)).Offset = sizeof(contents) - 4;
3843 S(U(ovl)).OffsetHigh = 0;
3844 ovl.hEvent = 0;
3845 bytes = 0;
3846 SetLastError(0xdeadbeef);
3847 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
3848 ok(ret, "WriteFile error %d\n", GetLastError());
3849 ok(bytes == 4, "bytes %u\n", bytes);
3851 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3852 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3854 S(U(ovl)).Offset = 0;
3855 S(U(ovl)).OffsetHigh = 0;
3856 ovl.Internal = -1;
3857 ovl.InternalHigh = -1;
3858 ovl.hEvent = 0;
3859 bytes = 0;
3860 SetLastError(0xdeadbeef);
3861 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3862 ok(ret, "ReadFile error %d\n", GetLastError());
3863 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3864 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3865 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
3866 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3867 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
3869 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3870 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3872 CloseHandle(hfile);
3874 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
3875 if (!hfile) return;
3877 bytes = 0xdeadbeef;
3878 SetLastError(0xdeadbeef);
3879 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
3880 ok(!ret, "ReadFile should fail\n");
3881 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3882 ok(bytes == 0, "bytes %u\n", bytes);
3884 S(U(ovl)).Offset = 0;
3885 S(U(ovl)).OffsetHigh = 0;
3886 ovl.Internal = -1;
3887 ovl.InternalHigh = -1;
3888 ovl.hEvent = 0;
3889 bytes = 0xdeadbeef;
3890 SetLastError(0xdeadbeef);
3891 /* ReadFile return value depends on Windows version and testing it is not practical */
3892 ReadFile(hfile, buf, 0, &bytes, &ovl);
3893 ok(bytes == 0, "bytes %u\n", bytes);
3894 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3895 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3897 bytes = 0xdeadbeef;
3898 SetLastError(0xdeadbeef);
3899 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
3900 ok(!ret, "WriteFile should fail\n");
3901 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3902 ok(bytes == 0, "bytes %u\n", bytes);
3904 U(iob).Status = -1;
3905 iob.Information = -1;
3906 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
3907 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
3908 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3909 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3911 for (i = -20; i < -1; i++)
3913 U(iob).Status = -1;
3914 iob.Information = -1;
3915 offset.QuadPart = (LONGLONG)i;
3916 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3917 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3918 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3919 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3922 U(iob).Status = -1;
3923 iob.Information = -1;
3924 offset.QuadPart = 0;
3925 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3926 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
3927 if (status == STATUS_PENDING)
3929 ret = WaitForSingleObject(hfile, 3000);
3930 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
3932 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3933 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3935 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3936 ok(off == 0, "expected 0, got %u\n", off);
3938 bytes = 0xdeadbeef;
3939 SetLastError(0xdeadbeef);
3940 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3941 ok(!ret, "ReadFile should fail\n");
3942 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3943 ok(bytes == 0, "bytes %u\n", bytes);
3945 U(iob).Status = -1;
3946 iob.Information = -1;
3947 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3948 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
3949 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3950 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3952 for (i = -20; i < 0; i++)
3954 U(iob).Status = -1;
3955 iob.Information = -1;
3956 offset.QuadPart = (LONGLONG)i;
3957 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3958 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3959 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3960 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3963 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3964 ok(off == 0, "expected 0, got %u\n", off);
3966 /* test reading beyond EOF */
3967 offset.QuadPart = sizeof(contents);
3968 S(U(ovl)).Offset = offset.u.LowPart;
3969 S(U(ovl)).OffsetHigh = offset.u.HighPart;
3970 ovl.Internal = -1;
3971 ovl.InternalHigh = -1;
3972 ovl.hEvent = 0;
3973 bytes = 0xdeadbeef;
3974 SetLastError(0xdeadbeef);
3975 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3976 ok(!ret, "ReadFile should fail\n");
3977 ret = GetLastError();
3978 ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
3979 ok(bytes == 0, "bytes %u\n", bytes);
3981 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3982 ok(off == 0, "expected 0, got %u\n", off);
3984 if (ret == ERROR_IO_PENDING)
3986 bytes = 0xdeadbeef;
3987 SetLastError(0xdeadbeef);
3988 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
3989 ok(!ret, "GetOverlappedResult should report FALSE\n");
3990 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
3991 ok(bytes == 0, "expected 0, read %u\n", bytes);
3992 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
3993 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3996 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3997 ok(off == 0, "expected 0, got %u\n", off);
3999 offset.QuadPart = sizeof(contents);
4000 S(U(ovl)).Offset = offset.u.LowPart;
4001 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4002 ovl.Internal = -1;
4003 ovl.InternalHigh = -1;
4004 ovl.hEvent = 0;
4005 bytes = 0xdeadbeef;
4006 SetLastError(0xdeadbeef);
4007 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
4008 /* ReadFile return value depends on Windows version and testing it is not practical */
4009 if (!ret)
4010 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4011 ret = GetLastError();
4012 ok(bytes == 0, "bytes %u\n", bytes);
4014 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4015 ok(off == 0, "expected 0, got %u\n", off);
4017 if (ret == ERROR_IO_PENDING)
4019 bytes = 0xdeadbeef;
4020 SetLastError(0xdeadbeef);
4021 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4022 ok(ret, "GetOverlappedResult should report TRUE\n");
4023 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4024 ok(bytes == 0, "expected 0, read %u\n", bytes);
4025 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4026 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4029 offset.QuadPart = sizeof(contents);
4030 S(U(ovl)).Offset = offset.u.LowPart;
4031 S(U(ovl)).OffsetHigh = offset.u.HighPart;
4032 ovl.Internal = -1;
4033 ovl.InternalHigh = -1;
4034 ovl.hEvent = 0;
4035 bytes = 0xdeadbeef;
4036 SetLastError(0xdeadbeef);
4037 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
4038 /* ReadFile return value depends on Windows version and testing it is not practical */
4039 if (!ret)
4040 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4041 ret = GetLastError();
4042 ok(bytes == 0, "bytes %u\n", bytes);
4044 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4045 ok(off == 0, "expected 0, got %u\n", off);
4047 if (ret == ERROR_IO_PENDING)
4049 bytes = 0xdeadbeef;
4050 SetLastError(0xdeadbeef);
4051 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4052 ok(ret, "GetOverlappedResult should report TRUE\n");
4053 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4054 ok(bytes == 0, "expected 0, read %u\n", bytes);
4055 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4056 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4059 U(iob).Status = -1;
4060 iob.Information = -1;
4061 offset.QuadPart = sizeof(contents);
4062 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4063 if (status == STATUS_PENDING)
4065 ret = WaitForSingleObject(hfile, 3000);
4066 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4067 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
4068 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4070 else
4072 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
4073 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4074 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
4077 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4078 ok(off == 0, "expected 0, got %u\n", off);
4080 U(iob).Status = -1;
4081 iob.Information = -1;
4082 offset.QuadPart = sizeof(contents);
4083 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4084 if (status == STATUS_PENDING)
4086 ret = WaitForSingleObject(hfile, 3000);
4087 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4088 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4089 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4091 else
4093 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
4094 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4095 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4098 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4099 ok(off == 0, "expected 0, got %u\n", off);
4101 S(U(ovl)).Offset = 0;
4102 S(U(ovl)).OffsetHigh = 0;
4103 ovl.Internal = -1;
4104 ovl.InternalHigh = -1;
4105 ovl.hEvent = 0;
4106 bytes = 0;
4107 SetLastError(0xdeadbeef);
4108 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4109 /* ReadFile return value depends on Windows version and testing it is not practical */
4110 if (!ret)
4112 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4113 ok(bytes == 0, "bytes %u\n", bytes);
4115 else ok(bytes == 14, "bytes %u\n", bytes);
4116 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4117 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4119 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4120 ok(off == 0, "expected 0, got %u\n", off);
4122 bytes = 0xdeadbeef;
4123 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4124 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4125 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4126 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4127 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4128 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4130 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4131 ok(off == 0, "expected 0, got %u\n", off);
4133 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4134 SetEndOfFile(hfile);
4135 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4137 U(iob).Status = -1;
4138 iob.Information = -1;
4139 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4140 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4141 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4142 if (status == STATUS_PENDING)
4144 ret = WaitForSingleObject(hfile, 3000);
4145 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4147 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4148 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
4150 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4151 ok(off == 0, "expected 0, got %u\n", off);
4153 U(iob).Status = -1;
4154 iob.Information = -1;
4155 offset.QuadPart = 0;
4156 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4157 ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4158 if (status == STATUS_PENDING)
4160 ret = WaitForSingleObject(hfile, 3000);
4161 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4163 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4164 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4166 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4167 ok(off == 0, "expected 0, got %u\n", off);
4169 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4170 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4172 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4173 ok(off == 0, "expected 0, got %u\n", off);
4175 S(U(ovl)).Offset = sizeof(contents) - 4;
4176 S(U(ovl)).OffsetHigh = 0;
4177 ovl.Internal = -1;
4178 ovl.InternalHigh = -1;
4179 ovl.hEvent = 0;
4180 bytes = 0;
4181 SetLastError(0xdeadbeef);
4182 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4183 /* WriteFile return value depends on Windows version and testing it is not practical */
4184 if (!ret)
4186 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4187 ok(bytes == 0, "bytes %u\n", bytes);
4188 ret = WaitForSingleObject(hfile, 3000);
4189 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4191 else ok(bytes == 4, "bytes %u\n", bytes);
4192 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4193 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4195 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4196 ok(off == 0, "expected 0, got %u\n", off);
4198 bytes = 0xdeadbeef;
4199 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4200 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4201 ok(bytes == 4, "bytes %u\n", bytes);
4202 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4203 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4205 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4206 ok(off == 0, "expected 0, got %u\n", off);
4208 S(U(ovl)).Offset = 0;
4209 S(U(ovl)).OffsetHigh = 0;
4210 ovl.Internal = -1;
4211 ovl.InternalHigh = -1;
4212 ovl.hEvent = 0;
4213 bytes = 0;
4214 SetLastError(0xdeadbeef);
4215 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4216 /* ReadFile return value depends on Windows version and testing it is not practical */
4217 if (!ret)
4219 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4220 ok(bytes == 0, "bytes %u\n", bytes);
4221 ret = WaitForSingleObject(hfile, 3000);
4222 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4224 else ok(bytes == 14, "bytes %u\n", bytes);
4225 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4226 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4228 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4229 ok(off == 0, "expected 0, got %u\n", off);
4231 bytes = 0xdeadbeef;
4232 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4233 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4234 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4235 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4236 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4237 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4238 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4240 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4241 ok(off == 0, "expected 0, got %u\n", off);
4243 CloseHandle(event);
4244 CloseHandle(hfile);
4247 START_TEST(file)
4249 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
4250 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
4251 if (!hntdll)
4253 skip("not running on NT, skipping test\n");
4254 return;
4257 pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
4258 pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
4260 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
4261 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
4262 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
4263 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
4264 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
4265 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
4266 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
4267 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
4268 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
4269 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
4270 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
4271 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
4272 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
4273 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
4274 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
4275 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
4276 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
4277 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
4278 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
4279 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
4280 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
4281 pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
4282 pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
4284 test_read_write();
4285 test_NtCreateFile();
4286 create_file_test();
4287 open_file_test();
4288 delete_file_test();
4289 read_file_test();
4290 append_file_test();
4291 nt_mailslot_test();
4292 test_iocompletion();
4293 test_file_basic_information();
4294 test_file_all_information();
4295 test_file_both_information();
4296 test_file_name_information();
4297 test_file_full_size_information();
4298 test_file_all_name_information();
4299 test_file_rename_information();
4300 test_file_link_information();
4301 test_file_disposition_information();
4302 test_file_id_information();
4303 test_query_volume_information_file();
4304 test_query_attribute_information_file();