ntdll: Don't run user APCs in NtCancelIoFile.
[wine.git] / dlls / ntdll / tests / file.c
blob19a886af06d7187c5a0ad944bd1b7e8045822490
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);
82 static inline BOOL is_signaled( HANDLE obj )
84 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
87 static const char* debugstr_longlong(ULONGLONG ll)
89 static char str[17];
90 if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
91 sprintf(str, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
92 else
93 sprintf(str, "%lx", (unsigned long)ll);
94 return str;
97 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
98 #define TEST_BUF_LEN 3
100 static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
102 *read = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
103 1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
104 ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
106 *write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
107 ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
109 return TRUE;
112 static HANDLE create_temp_file( ULONG flags )
114 char path[MAX_PATH], buffer[MAX_PATH];
115 HANDLE handle;
117 GetTempPathA( MAX_PATH, path );
118 GetTempFileNameA( path, "foo", 0, buffer );
119 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
120 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
121 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
122 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
125 #define CVALUE_FIRST 0xfffabbcc
126 #define CKEY_FIRST 0x1030341
127 #define CKEY_SECOND 0x132E46
129 static ULONG_PTR completionKey;
130 static IO_STATUS_BLOCK ioSb;
131 static ULONG_PTR completionValue;
133 static ULONG get_pending_msgs(HANDLE h)
135 NTSTATUS res;
136 ULONG a, req;
138 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
139 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
140 if (res != STATUS_SUCCESS) return -1;
141 ok( req == sizeof(a), "Unexpected response size: %x\n", req );
142 return a;
145 static BOOL get_msg(HANDLE h)
147 LARGE_INTEGER timeout = {{-10000000*3}};
148 DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
149 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
150 if (res != STATUS_SUCCESS)
152 completionKey = completionValue = 0;
153 memset(&ioSb, 0, sizeof(ioSb));
154 return FALSE;
156 return TRUE;
160 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
162 int *count = arg;
164 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
165 iosb, U(*iosb).Status, iosb->Information );
166 (*count)++;
167 ok( !reserved, "reserved is not 0: %x\n", reserved );
170 static void create_file_test(void)
172 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
173 '\\','f','a','i','l','i','n','g',0};
174 static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
175 static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
176 NTSTATUS status;
177 HANDLE dir, file;
178 WCHAR path[MAX_PATH];
179 OBJECT_ATTRIBUTES attr;
180 IO_STATUS_BLOCK io;
181 UNICODE_STRING nameW;
183 GetCurrentDirectoryW( MAX_PATH, path );
184 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
185 attr.Length = sizeof(attr);
186 attr.RootDirectory = 0;
187 attr.ObjectName = &nameW;
188 attr.Attributes = OBJ_CASE_INSENSITIVE;
189 attr.SecurityDescriptor = NULL;
190 attr.SecurityQualityOfService = NULL;
192 /* try various open modes and options on directories */
193 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
194 FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
195 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
196 CloseHandle( dir );
198 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
199 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
200 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
201 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
203 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
204 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
205 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
206 CloseHandle( dir );
208 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
209 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
210 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
212 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
213 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
214 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
216 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
217 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
218 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
220 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
221 FILE_OPEN, 0, NULL, 0 );
222 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
223 CloseHandle( dir );
225 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
226 FILE_CREATE, 0, NULL, 0 );
227 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
228 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
230 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
231 FILE_OPEN_IF, 0, NULL, 0 );
232 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
233 CloseHandle( dir );
235 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
236 FILE_SUPERSEDE, 0, NULL, 0 );
237 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
238 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
240 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
241 FILE_OVERWRITE, 0, NULL, 0 );
242 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
243 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
245 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
246 FILE_OVERWRITE_IF, 0, NULL, 0 );
247 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
248 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
250 pRtlFreeUnicodeString( &nameW );
252 pRtlInitUnicodeString( &nameW, systemrootW );
253 attr.Length = sizeof(attr);
254 attr.RootDirectory = NULL;
255 attr.ObjectName = &nameW;
256 attr.Attributes = OBJ_CASE_INSENSITIVE;
257 attr.SecurityDescriptor = NULL;
258 attr.SecurityQualityOfService = NULL;
259 dir = NULL;
260 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
261 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
262 todo_wine
263 ok( status == STATUS_INVALID_PARAMETER,
264 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
266 /* Invalid chars in file/dirnames */
267 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
268 attr.ObjectName = &nameW;
269 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
270 FILE_SHARE_READ, FILE_CREATE,
271 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
272 ok(status == STATUS_OBJECT_NAME_INVALID,
273 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
275 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
276 0, FILE_CREATE,
277 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
278 ok(status == STATUS_OBJECT_NAME_INVALID,
279 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
280 pRtlFreeUnicodeString(&nameW);
282 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
283 attr.ObjectName = &nameW;
284 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
285 FILE_SHARE_READ, FILE_CREATE,
286 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
287 ok(status == STATUS_OBJECT_NAME_INVALID,
288 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
290 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
291 0, FILE_CREATE,
292 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
293 ok(status == STATUS_OBJECT_NAME_INVALID,
294 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
295 pRtlFreeUnicodeString(&nameW);
298 static void open_file_test(void)
300 NTSTATUS status;
301 HANDLE dir, root, handle;
302 WCHAR path[MAX_PATH];
303 BYTE data[1024];
304 OBJECT_ATTRIBUTES attr;
305 IO_STATUS_BLOCK io;
306 UNICODE_STRING nameW;
307 UINT i, len;
308 BOOL restart = TRUE;
310 len = GetWindowsDirectoryW( path, MAX_PATH );
311 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
312 attr.Length = sizeof(attr);
313 attr.RootDirectory = 0;
314 attr.ObjectName = &nameW;
315 attr.Attributes = OBJ_CASE_INSENSITIVE;
316 attr.SecurityDescriptor = NULL;
317 attr.SecurityQualityOfService = NULL;
318 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
319 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
320 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
321 pRtlFreeUnicodeString( &nameW );
323 path[3] = 0; /* root of the drive */
324 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
325 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
326 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
327 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
328 pRtlFreeUnicodeString( &nameW );
330 /* test opening system dir with RootDirectory set to windows dir */
331 GetSystemDirectoryW( path, MAX_PATH );
332 while (path[len] == '\\') len++;
333 nameW.Buffer = path + len;
334 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
335 attr.RootDirectory = dir;
336 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
337 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
338 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
339 CloseHandle( handle );
341 /* try uppercase name */
342 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
343 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
344 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
345 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
346 CloseHandle( handle );
348 /* try with leading backslash */
349 nameW.Buffer--;
350 nameW.Length += sizeof(WCHAR);
351 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
352 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
353 ok( status == STATUS_INVALID_PARAMETER ||
354 status == STATUS_OBJECT_NAME_INVALID ||
355 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
356 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
357 if (!status) CloseHandle( handle );
359 /* try with empty name */
360 nameW.Length = 0;
361 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
362 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
363 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
364 CloseHandle( handle );
366 /* try open by file id */
368 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
369 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
371 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
373 restart = FALSE;
375 if (!info->FileId.QuadPart) continue;
377 nameW.Buffer = (WCHAR *)&info->FileId;
378 nameW.Length = sizeof(info->FileId);
379 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
380 attr.RootDirectory = dir;
381 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
382 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
383 FILE_SHARE_READ,
384 FILE_OPEN_BY_FILE_ID |
385 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
386 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
387 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
388 if (status == STATUS_NOT_IMPLEMENTED)
390 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
391 break;
393 if (status == STATUS_SHARING_VIOLATION)
394 trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
395 if (!status)
397 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
399 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
401 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
403 /* check that it's the same file/directory */
405 /* don't check the size for directories */
406 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
407 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
408 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
410 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
411 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
413 CloseHandle( handle );
415 /* try same thing from drive root */
416 attr.RootDirectory = root;
417 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
418 FILE_SHARE_READ|FILE_SHARE_WRITE,
419 FILE_OPEN_BY_FILE_ID |
420 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
421 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
422 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
423 if (!status) CloseHandle( handle );
427 CloseHandle( dir );
428 CloseHandle( root );
431 static void delete_file_test(void)
433 NTSTATUS ret;
434 OBJECT_ATTRIBUTES attr;
435 UNICODE_STRING nameW;
436 WCHAR pathW[MAX_PATH];
437 WCHAR pathsubW[MAX_PATH];
438 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
439 static const WCHAR subdirW[] = {'\\','s','u','b',0};
441 ret = GetTempPathW(MAX_PATH, pathW);
442 if (!ret)
444 ok(0, "couldn't get temp dir\n");
445 return;
447 if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
449 ok(0, "MAX_PATH exceeded in constructing paths\n");
450 return;
453 lstrcatW(pathW, testdirW);
454 lstrcpyW(pathsubW, pathW);
455 lstrcatW(pathsubW, subdirW);
457 ret = CreateDirectoryW(pathW, NULL);
458 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
459 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
461 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
462 return;
465 attr.Length = sizeof(attr);
466 attr.RootDirectory = 0;
467 attr.Attributes = OBJ_CASE_INSENSITIVE;
468 attr.ObjectName = &nameW;
469 attr.SecurityDescriptor = NULL;
470 attr.SecurityQualityOfService = NULL;
472 /* test NtDeleteFile on an empty directory */
473 ret = pNtDeleteFile(&attr);
474 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
475 ret = RemoveDirectoryW(pathW);
476 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
478 /* test NtDeleteFile on a non-empty directory */
479 ret = CreateDirectoryW(pathW, NULL);
480 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
481 ret = CreateDirectoryW(pathsubW, NULL);
482 ok(ret == TRUE, "couldn't create directory subdir\n");
483 ret = pNtDeleteFile(&attr);
484 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
485 ret = RemoveDirectoryW(pathsubW);
486 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
487 ret = RemoveDirectoryW(pathW);
488 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
490 pRtlFreeUnicodeString( &nameW );
493 static void read_file_test(void)
495 const char text[] = "foobar";
496 HANDLE handle, read, write;
497 NTSTATUS status;
498 IO_STATUS_BLOCK iosb, iosb2;
499 DWORD written;
500 int apc_count = 0;
501 char buffer[128];
502 LARGE_INTEGER offset;
503 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
504 BOOL ret;
506 buffer[0] = 1;
508 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
510 /* try read with no data */
511 U(iosb).Status = 0xdeadbabe;
512 iosb.Information = 0xdeadbeef;
513 ok( is_signaled( read ), "read handle is not signaled\n" );
514 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
515 ok( status == STATUS_PENDING, "wrong status %x\n", status );
516 ok( !is_signaled( read ), "read handle is signaled\n" );
517 ok( !is_signaled( event ), "event is signaled\n" );
518 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
519 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
520 ok( !apc_count, "apc was called\n" );
521 ret = WriteFile( write, buffer, 1, &written, NULL );
522 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
523 /* iosb updated here by async i/o */
524 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
525 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
526 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
527 ok( !is_signaled( read ), "read handle is signaled\n" );
528 ok( is_signaled( event ), "event is not signaled\n" );
529 ok( !apc_count, "apc was called\n" );
530 apc_count = 0;
531 SleepEx( 1, FALSE ); /* non-alertable sleep */
532 ok( !apc_count, "apc was called\n" );
533 SleepEx( 1, TRUE ); /* alertable sleep */
534 ok( apc_count == 1, "apc not called\n" );
536 /* with no event, the pipe handle itself gets signaled */
537 apc_count = 0;
538 U(iosb).Status = 0xdeadbabe;
539 iosb.Information = 0xdeadbeef;
540 ok( !is_signaled( read ), "read handle is not signaled\n" );
541 status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
542 ok( status == STATUS_PENDING, "wrong status %x\n", status );
543 ok( !is_signaled( read ), "read handle is signaled\n" );
544 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
545 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
546 ok( !apc_count, "apc was called\n" );
547 ret = WriteFile( write, buffer, 1, &written, NULL );
548 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
549 /* iosb updated here by async i/o */
550 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
551 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
552 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
553 ok( is_signaled( read ), "read handle is signaled\n" );
554 ok( !apc_count, "apc was called\n" );
555 apc_count = 0;
556 SleepEx( 1, FALSE ); /* non-alertable sleep */
557 ok( !apc_count, "apc was called\n" );
558 SleepEx( 1, TRUE ); /* alertable sleep */
559 ok( apc_count == 1, "apc not called\n" );
561 /* now read with data ready */
562 apc_count = 0;
563 U(iosb).Status = 0xdeadbabe;
564 iosb.Information = 0xdeadbeef;
565 ResetEvent( event );
566 ret = WriteFile( write, buffer, 1, &written, NULL );
567 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
568 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
569 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
570 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
571 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
572 ok( is_signaled( event ), "event is not signaled\n" );
573 ok( !apc_count, "apc was called\n" );
574 SleepEx( 1, FALSE ); /* non-alertable sleep */
575 ok( !apc_count, "apc was called\n" );
576 SleepEx( 1, TRUE ); /* alertable sleep */
577 ok( apc_count == 1, "apc not called\n" );
579 /* try read with no data */
580 apc_count = 0;
581 U(iosb).Status = 0xdeadbabe;
582 iosb.Information = 0xdeadbeef;
583 ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
584 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
585 ok( status == STATUS_PENDING, "wrong status %x\n", status );
586 ok( !is_signaled( event ), "event is signaled\n" );
587 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
588 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
589 ok( !apc_count, "apc was called\n" );
590 ret = WriteFile( write, buffer, 1, &written, NULL );
591 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
592 /* partial read is good enough */
593 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
594 ok( is_signaled( event ), "event is signaled\n" );
595 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
596 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
597 ok( !apc_count, "apc was called\n" );
598 SleepEx( 1, TRUE ); /* alertable sleep */
599 ok( apc_count == 1, "apc was not called\n" );
601 /* read from disconnected pipe */
602 apc_count = 0;
603 U(iosb).Status = 0xdeadbabe;
604 iosb.Information = 0xdeadbeef;
605 CloseHandle( write );
606 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
607 ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
608 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
609 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
610 ok( !is_signaled( event ), "event is signaled\n" );
611 ok( !apc_count, "apc was called\n" );
612 SleepEx( 1, TRUE ); /* alertable sleep */
613 ok( !apc_count, "apc was called\n" );
614 CloseHandle( read );
616 /* read from closed handle */
617 apc_count = 0;
618 U(iosb).Status = 0xdeadbabe;
619 iosb.Information = 0xdeadbeef;
620 SetEvent( event );
621 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
622 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
623 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
624 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
625 ok( is_signaled( event ), "event is signaled\n" ); /* not reset on invalid handle */
626 ok( !apc_count, "apc was called\n" );
627 SleepEx( 1, TRUE ); /* alertable sleep */
628 ok( !apc_count, "apc was called\n" );
630 /* disconnect while async read is in progress */
631 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
632 apc_count = 0;
633 U(iosb).Status = 0xdeadbabe;
634 iosb.Information = 0xdeadbeef;
635 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
636 ok( status == STATUS_PENDING, "wrong status %x\n", status );
637 ok( !is_signaled( event ), "event is signaled\n" );
638 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
639 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
640 ok( !apc_count, "apc was called\n" );
641 CloseHandle( write );
642 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
643 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
644 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
645 ok( is_signaled( event ), "event is signaled\n" );
646 ok( !apc_count, "apc was called\n" );
647 SleepEx( 1, TRUE ); /* alertable sleep */
648 ok( apc_count == 1, "apc was not called\n" );
649 CloseHandle( read );
651 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
652 ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
653 ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
655 apc_count = 0;
656 U(iosb).Status = 0xdeadbabe;
657 iosb.Information = 0xdeadbeef;
658 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
659 ok( status == STATUS_PENDING, "wrong status %x\n", status );
660 ok( !is_signaled( event ), "event is signaled\n" );
661 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
662 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
663 ok( !apc_count, "apc was called\n" );
664 /* Cancel by other handle */
665 status = pNtCancelIoFile( read, &iosb2 );
666 ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
667 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
668 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
669 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
670 ok( is_signaled( event ), "event is signaled\n" );
671 ok( !apc_count, "apc was called\n" );
672 SleepEx( 1, TRUE ); /* alertable sleep */
673 ok( apc_count == 1, "apc was not called\n" );
675 apc_count = 0;
676 U(iosb).Status = 0xdeadbabe;
677 iosb.Information = 0xdeadbeef;
678 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
679 ok( status == STATUS_PENDING, "wrong status %x\n", status );
680 ok( !is_signaled( event ), "event is signaled\n" );
681 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
682 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
683 ok( !apc_count, "apc was called\n" );
684 /* Close queued handle */
685 CloseHandle( read );
686 SleepEx( 1, TRUE ); /* alertable sleep */
687 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
688 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
689 status = pNtCancelIoFile( read, &iosb2 );
690 ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
691 status = pNtCancelIoFile( handle, &iosb2 );
692 ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
693 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
694 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
695 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
696 ok( is_signaled( event ), "event is signaled\n" );
697 ok( !apc_count, "apc was called\n" );
698 SleepEx( 1, TRUE ); /* alertable sleep */
699 ok( apc_count == 1, "apc was not called\n" );
700 CloseHandle( handle );
701 CloseHandle( write );
703 if (pNtCancelIoFileEx)
705 /* Basic Cancel Ex */
706 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
708 apc_count = 0;
709 U(iosb).Status = 0xdeadbabe;
710 iosb.Information = 0xdeadbeef;
711 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
712 ok( status == STATUS_PENDING, "wrong status %x\n", status );
713 ok( !is_signaled( event ), "event is signaled\n" );
714 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
715 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
716 ok( !apc_count, "apc was called\n" );
717 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
718 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
719 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
720 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
721 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
722 ok( is_signaled( event ), "event is signaled\n" );
723 ok( !apc_count, "apc was called\n" );
724 SleepEx( 1, TRUE ); /* alertable sleep */
725 ok( apc_count == 1, "apc was not called\n" );
727 /* Duplicate iosb */
728 apc_count = 0;
729 U(iosb).Status = 0xdeadbabe;
730 iosb.Information = 0xdeadbeef;
731 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
732 ok( status == STATUS_PENDING, "wrong status %x\n", status );
733 ok( !is_signaled( event ), "event is signaled\n" );
734 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
735 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
736 ok( !apc_count, "apc was called\n" );
737 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
738 ok( status == STATUS_PENDING, "wrong status %x\n", status );
739 ok( !is_signaled( event ), "event is signaled\n" );
740 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
741 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
742 ok( !apc_count, "apc was called\n" );
743 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
744 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
745 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
746 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
747 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
748 ok( is_signaled( event ), "event is signaled\n" );
749 ok( !apc_count, "apc was called\n" );
750 SleepEx( 1, TRUE ); /* alertable sleep */
751 ok( apc_count == 2, "apc was not called\n" );
753 CloseHandle( read );
754 CloseHandle( write );
757 /* now try a real file */
758 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
759 apc_count = 0;
760 U(iosb).Status = 0xdeadbabe;
761 iosb.Information = 0xdeadbeef;
762 offset.QuadPart = 0;
763 ResetEvent( event );
764 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
765 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
766 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
767 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
768 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
769 ok( is_signaled( event ), "event is signaled\n" );
770 ok( !apc_count, "apc was called\n" );
771 SleepEx( 1, TRUE ); /* alertable sleep */
772 ok( apc_count == 1, "apc was not called\n" );
774 apc_count = 0;
775 U(iosb).Status = 0xdeadbabe;
776 iosb.Information = 0xdeadbeef;
777 offset.QuadPart = 0;
778 ResetEvent( event );
779 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
780 ok( status == STATUS_SUCCESS ||
781 status == STATUS_PENDING, /* vista */
782 "wrong status %x\n", status );
783 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
784 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
785 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
786 ok( is_signaled( event ), "event is signaled\n" );
787 ok( !apc_count, "apc was called\n" );
788 SleepEx( 1, TRUE ); /* alertable sleep */
789 ok( apc_count == 1, "apc was not called\n" );
791 /* read beyond eof */
792 apc_count = 0;
793 U(iosb).Status = 0xdeadbabe;
794 iosb.Information = 0xdeadbeef;
795 offset.QuadPart = strlen(text) + 2;
796 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
797 ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
798 if (status == STATUS_PENDING) /* vista */
800 WaitForSingleObject( event, 1000 );
801 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
802 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
803 ok( is_signaled( event ), "event is signaled\n" );
804 ok( !apc_count, "apc was called\n" );
805 SleepEx( 1, TRUE ); /* alertable sleep */
806 ok( apc_count == 1, "apc was not called\n" );
808 CloseHandle( handle );
810 /* now a non-overlapped file */
811 if (!(handle = create_temp_file(0))) return;
812 apc_count = 0;
813 U(iosb).Status = 0xdeadbabe;
814 iosb.Information = 0xdeadbeef;
815 offset.QuadPart = 0;
816 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
817 ok( status == STATUS_END_OF_FILE ||
818 status == STATUS_SUCCESS ||
819 status == STATUS_PENDING, /* vista */
820 "wrong status %x\n", status );
821 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
822 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
823 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
824 ok( is_signaled( event ), "event is signaled\n" );
825 ok( !apc_count, "apc was called\n" );
826 SleepEx( 1, TRUE ); /* alertable sleep */
827 ok( apc_count == 1, "apc was not called\n" );
829 apc_count = 0;
830 U(iosb).Status = 0xdeadbabe;
831 iosb.Information = 0xdeadbeef;
832 offset.QuadPart = 0;
833 ResetEvent( event );
834 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
835 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
836 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
837 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
838 ok( is_signaled( event ), "event is signaled\n" );
839 ok( !apc_count, "apc was called\n" );
840 SleepEx( 1, TRUE ); /* alertable sleep */
841 todo_wine ok( !apc_count, "apc was called\n" );
843 /* read beyond eof */
844 apc_count = 0;
845 U(iosb).Status = 0xdeadbabe;
846 iosb.Information = 0xdeadbeef;
847 offset.QuadPart = strlen(text) + 2;
848 ResetEvent( event );
849 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
850 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
851 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
852 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
853 ok( is_signaled( event ), "event is not signaled\n" );
854 ok( !apc_count, "apc was called\n" );
855 SleepEx( 1, TRUE ); /* alertable sleep */
856 ok( !apc_count, "apc was called\n" );
858 CloseHandle( handle );
860 CloseHandle( event );
863 static void append_file_test(void)
865 static const char text[6] = "foobar";
866 HANDLE handle;
867 NTSTATUS status;
868 IO_STATUS_BLOCK iosb;
869 LARGE_INTEGER offset;
870 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
871 DWORD ret;
873 GetTempPathA( MAX_PATH, path );
874 GetTempFileNameA( path, "foo", 0, buffer );
876 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
877 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
879 U(iosb).Status = -1;
880 iosb.Information = -1;
881 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
882 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
883 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
884 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
886 CloseHandle(handle);
888 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
889 It matches the O_WRONLY|O_APPEND open() posix behavior */
890 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
891 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
893 U(iosb).Status = -1;
894 iosb.Information = -1;
895 offset.QuadPart = 1;
896 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
897 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
898 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
899 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
901 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
902 ok(ret == 4, "expected 4, got %u\n", ret);
904 U(iosb).Status = -1;
905 iosb.Information = -1;
906 offset.QuadPart = 3;
907 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
908 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
909 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
910 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
912 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
913 ok(ret == 6, "expected 6, got %u\n", ret);
915 CloseHandle(handle);
917 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
918 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
920 memset(buf, 0, sizeof(buf));
921 U(iosb).Status = -1;
922 iosb.Information = -1;
923 offset.QuadPart = 0;
924 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
925 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
926 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
927 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
928 buf[6] = 0;
929 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
931 U(iosb).Status = -1;
932 iosb.Information = -1;
933 offset.QuadPart = 0;
934 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
935 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
936 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
937 ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
939 memset(buf, 0, sizeof(buf));
940 U(iosb).Status = -1;
941 iosb.Information = -1;
942 offset.QuadPart = 0;
943 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
944 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
945 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
946 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
947 buf[6] = 0;
948 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
950 CloseHandle(handle);
951 DeleteFileA(buffer);
954 static void nt_mailslot_test(void)
956 HANDLE hslot;
957 ACCESS_MASK DesiredAccess;
958 OBJECT_ATTRIBUTES attr;
960 ULONG CreateOptions;
961 ULONG MailslotQuota;
962 ULONG MaxMessageSize;
963 LARGE_INTEGER TimeOut;
964 IO_STATUS_BLOCK IoStatusBlock;
965 NTSTATUS rc;
966 UNICODE_STRING str;
967 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
968 'R',':','\\','F','R','E','D','\0' };
970 TimeOut.QuadPart = -1;
972 pRtlInitUnicodeString(&str, buffer1);
973 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
974 CreateOptions = MailslotQuota = MaxMessageSize = 0;
975 DesiredAccess = GENERIC_READ;
978 * Check for NULL pointer handling
980 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
981 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
982 &TimeOut);
983 ok( rc == STATUS_ACCESS_VIOLATION ||
984 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
985 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
988 * Test to see if the Timeout can be NULL
990 hslot = (HANDLE)0xdeadbeef;
991 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
992 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
993 NULL);
994 ok( rc == STATUS_SUCCESS ||
995 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
996 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
997 ok( hslot != 0, "Handle is invalid\n");
999 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
1002 * Test that the length field is checked properly
1004 attr.Length = 0;
1005 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1006 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1007 &TimeOut);
1008 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
1010 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1012 attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
1013 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1014 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1015 &TimeOut);
1016 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
1018 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1021 * Test handling of a NULL unicode string in ObjectName
1023 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1024 attr.ObjectName = NULL;
1025 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1026 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1027 &TimeOut);
1028 ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
1029 rc == STATUS_INVALID_PARAMETER,
1030 "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
1032 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1035 * Test a valid call
1037 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1038 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1039 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1040 &TimeOut);
1041 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
1042 ok( hslot != 0, "Handle is invalid\n");
1044 rc = pNtClose(hslot);
1045 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
1048 static void test_iocp_setcompletion(HANDLE h)
1050 NTSTATUS res;
1051 ULONG count;
1052 SIZE_T size = 3;
1054 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
1056 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
1057 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
1059 count = get_pending_msgs(h);
1060 ok( count == 1, "Unexpected msg count: %d\n", count );
1062 if (get_msg(h))
1064 ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
1065 ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
1066 ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1067 ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
1070 count = get_pending_msgs(h);
1071 ok( !count, "Unexpected msg count: %d\n", count );
1074 static void test_iocp_fileio(HANDLE h)
1076 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1078 IO_STATUS_BLOCK iosb;
1079 FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
1080 HANDLE hPipeSrv, hPipeClt;
1081 NTSTATUS res;
1083 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1084 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1085 if (hPipeSrv != INVALID_HANDLE_VALUE )
1087 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1088 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1089 if (hPipeClt != INVALID_HANDLE_VALUE)
1091 U(iosb).Status = 0xdeadbeef;
1092 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1093 ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
1094 ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
1095 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
1096 CloseHandle(hPipeClt);
1098 CloseHandle( hPipeSrv );
1101 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1102 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1103 if (hPipeSrv == INVALID_HANDLE_VALUE )
1104 return;
1106 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1107 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1108 if (hPipeClt != INVALID_HANDLE_VALUE)
1110 OVERLAPPED o = {0,};
1111 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1112 DWORD read;
1113 long count;
1115 U(iosb).Status = 0xdeadbeef;
1116 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1117 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1118 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1120 memset( send_buf, 0, TEST_BUF_LEN );
1121 memset( recv_buf, 0xde, TEST_BUF_LEN );
1122 count = get_pending_msgs(h);
1123 ok( !count, "Unexpected msg count: %ld\n", count );
1124 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1125 count = get_pending_msgs(h);
1126 ok( !count, "Unexpected msg count: %ld\n", count );
1127 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1129 if (get_msg(h))
1131 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1132 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1133 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1134 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1135 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] );
1137 count = get_pending_msgs(h);
1138 ok( !count, "Unexpected msg count: %ld\n", count );
1140 memset( send_buf, 0, TEST_BUF_LEN );
1141 memset( recv_buf, 0xde, TEST_BUF_LEN );
1142 WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1143 count = get_pending_msgs(h);
1144 ok( !count, "Unexpected msg count: %ld\n", count );
1145 ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1146 count = get_pending_msgs(h);
1147 ok( count == 1, "Unexpected msg count: %ld\n", count );
1148 if (get_msg(h))
1150 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1151 ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1152 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1153 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1154 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] );
1157 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1158 CloseHandle( hPipeSrv );
1159 count = get_pending_msgs(h);
1160 ok( count == 1, "Unexpected msg count: %ld\n", count );
1161 if (get_msg(h))
1163 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1164 ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1165 /* wine sends wrong status here */
1166 todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1167 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1171 CloseHandle( hPipeClt );
1173 /* test associating a completion port with a handle after an async is queued */
1174 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1175 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1176 if (hPipeSrv == INVALID_HANDLE_VALUE )
1177 return;
1178 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1179 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1180 if (hPipeClt != INVALID_HANDLE_VALUE)
1182 OVERLAPPED o = {0,};
1183 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1184 DWORD read;
1185 long count;
1187 memset( send_buf, 0, TEST_BUF_LEN );
1188 memset( recv_buf, 0xde, TEST_BUF_LEN );
1189 count = get_pending_msgs(h);
1190 ok( !count, "Unexpected msg count: %ld\n", count );
1191 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1193 U(iosb).Status = 0xdeadbeef;
1194 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1195 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1196 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1197 count = get_pending_msgs(h);
1198 ok( !count, "Unexpected msg count: %ld\n", count );
1200 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1202 if (get_msg(h))
1204 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1205 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1206 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1207 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1208 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] );
1210 count = get_pending_msgs(h);
1211 ok( !count, "Unexpected msg count: %ld\n", count );
1214 CloseHandle( hPipeSrv );
1215 CloseHandle( hPipeClt );
1218 static void test_file_full_size_information(void)
1220 IO_STATUS_BLOCK io;
1221 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1222 FILE_FS_SIZE_INFORMATION fsi;
1223 HANDLE h;
1224 NTSTATUS res;
1226 if(!(h = create_temp_file(0))) return ;
1228 memset(&ffsi,0,sizeof(ffsi));
1229 memset(&fsi,0,sizeof(fsi));
1231 /* Assume No Quota Settings configured on Wine Testbot */
1232 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1233 todo_wine ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1234 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1235 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1237 /* Test for FileFsSizeInformation */
1238 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1239 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1240 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1241 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1242 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1243 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1245 /* Assume file system is NTFS */
1246 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1247 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1249 todo_wine
1251 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1252 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1253 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1254 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1255 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1256 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1257 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1258 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1259 debugstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1260 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1261 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1262 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1263 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1264 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1265 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1266 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1267 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1270 /* Assume file system is NTFS */
1271 todo_wine
1273 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1274 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1277 CloseHandle( h );
1280 static void test_file_basic_information(void)
1282 IO_STATUS_BLOCK io;
1283 FILE_BASIC_INFORMATION fbi;
1284 HANDLE h;
1285 int res;
1286 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1288 if (!(h = create_temp_file(0))) return;
1290 /* Check default first */
1291 memset(&fbi, 0, sizeof(fbi));
1292 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1293 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1294 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1295 "attribute %x not expected\n", fbi.FileAttributes );
1297 /* Then SYSTEM */
1298 /* Clear fbi to avoid setting times */
1299 memset(&fbi, 0, sizeof(fbi));
1300 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1301 U(io).Status = 0xdeadbeef;
1302 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1303 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1304 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1306 memset(&fbi, 0, sizeof(fbi));
1307 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1308 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1309 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1311 /* Then HIDDEN */
1312 memset(&fbi, 0, sizeof(fbi));
1313 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1314 U(io).Status = 0xdeadbeef;
1315 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1316 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1317 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1319 memset(&fbi, 0, sizeof(fbi));
1320 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1321 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1322 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1324 /* Check NORMAL last of all (to make sure we can clear attributes) */
1325 memset(&fbi, 0, sizeof(fbi));
1326 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1327 U(io).Status = 0xdeadbeef;
1328 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1329 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1330 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1332 memset(&fbi, 0, sizeof(fbi));
1333 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1334 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1335 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1337 CloseHandle( h );
1340 static void test_file_all_information(void)
1342 IO_STATUS_BLOCK io;
1343 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1344 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1345 * don't leave enough room there.
1347 struct {
1348 FILE_ALL_INFORMATION fai;
1349 WCHAR buf[256];
1350 } fai_buf;
1351 HANDLE h;
1352 int res;
1353 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1355 if (!(h = create_temp_file(0))) return;
1357 /* Check default first */
1358 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1359 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1360 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1361 "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1363 /* Then SYSTEM */
1364 /* Clear fbi to avoid setting times */
1365 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1366 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1367 U(io).Status = 0xdeadbeef;
1368 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1369 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1370 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1371 U(io).Status = 0xdeadbeef;
1372 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1373 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1374 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1376 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1377 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1378 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1379 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 );
1381 /* Then HIDDEN */
1382 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1383 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1384 U(io).Status = 0xdeadbeef;
1385 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1386 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1387 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1389 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1390 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1391 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1392 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 );
1394 /* Check NORMAL last of all (to make sure we can clear attributes) */
1395 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1396 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1397 U(io).Status = 0xdeadbeef;
1398 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1399 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1400 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1402 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1403 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1404 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1405 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 );
1407 CloseHandle( h );
1410 static void test_file_both_information(void)
1412 IO_STATUS_BLOCK io;
1413 FILE_BOTH_DIR_INFORMATION fbi;
1414 HANDLE h;
1415 int res;
1417 if (!(h = create_temp_file(0))) return;
1419 memset(&fbi, 0, sizeof(fbi));
1420 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
1421 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
1423 CloseHandle( h );
1426 static void test_file_disposition_information(void)
1428 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
1429 DWORD dirpos;
1430 HANDLE handle, handle2;
1431 NTSTATUS res;
1432 IO_STATUS_BLOCK io;
1433 FILE_DISPOSITION_INFORMATION fdi;
1434 BOOL fileDeleted;
1436 GetTempPathA( MAX_PATH, tmp_path );
1438 /* cannot set disposition on file not opened with delete access */
1439 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1440 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1441 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1442 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1443 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
1444 fdi.DoDeleteFile = TRUE;
1445 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1446 todo_wine
1447 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
1448 CloseHandle( handle );
1449 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1450 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1451 DeleteFileA( buffer );
1453 /* can set disposition on file opened with proper access */
1454 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1455 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1456 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1457 fdi.DoDeleteFile = TRUE;
1458 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1459 todo_wine
1460 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1461 CloseHandle( handle );
1462 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1463 todo_wine
1464 ok( fileDeleted, "File should have been deleted\n" );
1465 DeleteFileA( buffer );
1467 /* cannot set disposition on readonly file */
1468 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1469 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1470 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1471 fdi.DoDeleteFile = TRUE;
1472 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1473 todo_wine
1474 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
1475 CloseHandle( handle );
1476 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1477 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1478 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
1479 DeleteFileA( buffer );
1481 /* can set disposition on file and then reset it */
1482 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1483 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1484 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1485 fdi.DoDeleteFile = TRUE;
1486 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1487 todo_wine
1488 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1489 fdi.DoDeleteFile = FALSE;
1490 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1491 todo_wine
1492 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1493 CloseHandle( handle );
1494 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1495 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1496 DeleteFileA( buffer );
1498 /* Delete-on-close flag doesn't change file disposition until a handle is closed */
1499 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1500 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
1501 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1502 fdi.DoDeleteFile = FALSE;
1503 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1504 todo_wine
1505 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1506 CloseHandle( handle );
1507 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1508 ok( fileDeleted, "File should have been deleted\n" );
1509 DeleteFileA( buffer );
1511 /* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
1512 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1513 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
1514 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1515 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
1516 CloseHandle( handle );
1517 fdi.DoDeleteFile = FALSE;
1518 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
1519 todo_wine
1520 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1521 CloseHandle( handle2 );
1522 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1523 ok( fileDeleted, "File should have been deleted\n" );
1524 DeleteFileA( buffer );
1526 /* can set disposition on a directory opened with proper access */
1527 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1528 DeleteFileA( buffer );
1529 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
1530 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
1531 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
1532 fdi.DoDeleteFile = TRUE;
1533 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1534 todo_wine
1535 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1536 CloseHandle( handle );
1537 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1538 todo_wine
1539 ok( fileDeleted, "Directory should have been deleted\n" );
1540 RemoveDirectoryA( buffer );
1542 /* RemoveDirectory sets directory disposition and it can be undone */
1543 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1544 DeleteFileA( buffer );
1545 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
1546 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
1547 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
1548 RemoveDirectoryA( buffer );
1549 fdi.DoDeleteFile = FALSE;
1550 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1551 todo_wine
1552 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1553 CloseHandle( handle );
1554 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1555 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
1556 RemoveDirectoryA( buffer );
1558 /* cannot set disposition on a non-empty directory */
1559 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1560 DeleteFileA( buffer );
1561 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
1562 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
1563 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
1564 dirpos = lstrlenA( buffer );
1565 lstrcpyA( buffer + dirpos, "\\tst" );
1566 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1567 CloseHandle( handle2 );
1568 fdi.DoDeleteFile = TRUE;
1569 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1570 todo_wine
1571 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
1572 DeleteFileA( buffer );
1573 buffer[dirpos] = '\0';
1574 CloseHandle( handle );
1575 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1576 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
1577 RemoveDirectoryA( buffer );
1580 static void test_iocompletion(void)
1582 HANDLE h = INVALID_HANDLE_VALUE;
1583 NTSTATUS res;
1585 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
1587 ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
1588 ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
1590 if ( h && h != INVALID_HANDLE_VALUE)
1592 test_iocp_setcompletion(h);
1593 test_iocp_fileio(h);
1594 pNtClose(h);
1598 static void test_file_name_information(void)
1600 WCHAR *file_name, *volume_prefix, *expected;
1601 FILE_NAME_INFORMATION *info;
1602 ULONG old_redir = 1, tmp;
1603 UINT file_name_size;
1604 IO_STATUS_BLOCK io;
1605 UINT info_size;
1606 HRESULT hr;
1607 HANDLE h;
1608 UINT len;
1610 /* GetVolumePathName is not present before w2k */
1611 if (!pGetVolumePathNameW) {
1612 win_skip("GetVolumePathNameW not found\n");
1613 return;
1616 file_name_size = GetSystemDirectoryW( NULL, 0 );
1617 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1618 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1619 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1621 len = GetSystemDirectoryW( file_name, file_name_size );
1622 ok(len == file_name_size - 1,
1623 "GetSystemDirectoryW returned %u, expected %u.\n",
1624 len, file_name_size - 1);
1626 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1627 ok(len, "GetVolumePathNameW failed.\n");
1629 len = lstrlenW( volume_prefix );
1630 if (len && volume_prefix[len - 1] == '\\') --len;
1631 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1632 expected[file_name_size - len - 1] = '\0';
1634 /* A bit more than we actually need, but it keeps the calculation simple. */
1635 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1636 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1638 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1639 h = CreateFileW( file_name, GENERIC_READ,
1640 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1641 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1642 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1643 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1645 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
1646 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
1648 memset( info, 0xcc, info_size );
1649 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
1650 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1651 hr, STATUS_BUFFER_OVERFLOW);
1652 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1653 U(io).Status, STATUS_BUFFER_OVERFLOW);
1654 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1655 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
1656 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1657 "info->FileName[1] is %p, expected %p.\n",
1658 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1659 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1661 memset( info, 0xcc, info_size );
1662 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1663 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1664 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1665 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1666 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
1667 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
1668 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1669 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1670 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1671 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
1672 "io.Information is %lu, expected %u.\n",
1673 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
1675 CloseHandle( h );
1676 HeapFree( GetProcessHeap(), 0, info );
1677 HeapFree( GetProcessHeap(), 0, expected );
1678 HeapFree( GetProcessHeap(), 0, volume_prefix );
1680 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1682 skip("Not running on WoW64, skipping test.\n");
1683 HeapFree( GetProcessHeap(), 0, file_name );
1684 return;
1687 h = CreateFileW( file_name, GENERIC_READ,
1688 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1689 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1690 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1691 HeapFree( GetProcessHeap(), 0, file_name );
1693 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1694 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1695 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1697 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1698 ok(len == file_name_size - 1,
1699 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1700 len, file_name_size - 1);
1702 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1703 ok(len, "GetVolumePathNameW failed.\n");
1705 len = lstrlenW( volume_prefix );
1706 if (len && volume_prefix[len - 1] == '\\') --len;
1707 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1708 expected[file_name_size - len - 1] = '\0';
1710 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1711 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1713 memset( info, 0xcc, info_size );
1714 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1715 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1716 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1717 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1718 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1720 CloseHandle( h );
1721 HeapFree( GetProcessHeap(), 0, info );
1722 HeapFree( GetProcessHeap(), 0, expected );
1723 HeapFree( GetProcessHeap(), 0, volume_prefix );
1724 HeapFree( GetProcessHeap(), 0, file_name );
1727 static void test_file_all_name_information(void)
1729 WCHAR *file_name, *volume_prefix, *expected;
1730 FILE_ALL_INFORMATION *info;
1731 ULONG old_redir = 1, tmp;
1732 UINT file_name_size;
1733 IO_STATUS_BLOCK io;
1734 UINT info_size;
1735 HRESULT hr;
1736 HANDLE h;
1737 UINT len;
1739 /* GetVolumePathName is not present before w2k */
1740 if (!pGetVolumePathNameW) {
1741 win_skip("GetVolumePathNameW not found\n");
1742 return;
1745 file_name_size = GetSystemDirectoryW( NULL, 0 );
1746 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1747 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1748 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1750 len = GetSystemDirectoryW( file_name, file_name_size );
1751 ok(len == file_name_size - 1,
1752 "GetSystemDirectoryW returned %u, expected %u.\n",
1753 len, file_name_size - 1);
1755 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1756 ok(len, "GetVolumePathNameW failed.\n");
1758 len = lstrlenW( volume_prefix );
1759 if (len && volume_prefix[len - 1] == '\\') --len;
1760 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1761 expected[file_name_size - len - 1] = '\0';
1763 /* A bit more than we actually need, but it keeps the calculation simple. */
1764 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1765 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1767 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1768 h = CreateFileW( file_name, GENERIC_READ,
1769 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1770 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1771 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1772 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1774 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
1775 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
1776 hr, STATUS_INFO_LENGTH_MISMATCH);
1778 memset( info, 0xcc, info_size );
1779 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
1780 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1781 hr, STATUS_BUFFER_OVERFLOW);
1782 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1783 U(io).Status, STATUS_BUFFER_OVERFLOW);
1784 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1785 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1786 ok(info->NameInformation.FileName[2] == 0xcccc,
1787 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
1788 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1789 "info->NameInformation.FileName[1] is %p, expected %p.\n",
1790 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1791 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1793 memset( info, 0xcc, info_size );
1794 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1795 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1796 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1797 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1798 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1799 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
1800 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
1801 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
1802 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1803 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
1804 "info->NameInformation.FileName is %s, expected %s.\n",
1805 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1806 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
1807 + info->NameInformation.FileNameLength,
1808 "io.Information is %lu\n", io.Information );
1810 CloseHandle( h );
1811 HeapFree( GetProcessHeap(), 0, info );
1812 HeapFree( GetProcessHeap(), 0, expected );
1813 HeapFree( GetProcessHeap(), 0, volume_prefix );
1815 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1817 skip("Not running on WoW64, skipping test.\n");
1818 HeapFree( GetProcessHeap(), 0, file_name );
1819 return;
1822 h = CreateFileW( file_name, GENERIC_READ,
1823 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1824 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1825 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1826 HeapFree( GetProcessHeap(), 0, file_name );
1828 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1829 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1830 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1832 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1833 ok(len == file_name_size - 1,
1834 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1835 len, file_name_size - 1);
1837 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1838 ok(len, "GetVolumePathNameW failed.\n");
1840 len = lstrlenW( volume_prefix );
1841 if (len && volume_prefix[len - 1] == '\\') --len;
1842 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1843 expected[file_name_size - len - 1] = '\0';
1845 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1846 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1848 memset( info, 0xcc, info_size );
1849 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1850 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1851 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1852 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
1853 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1855 CloseHandle( h );
1856 HeapFree( GetProcessHeap(), 0, info );
1857 HeapFree( GetProcessHeap(), 0, expected );
1858 HeapFree( GetProcessHeap(), 0, volume_prefix );
1859 HeapFree( GetProcessHeap(), 0, file_name );
1862 static void test_query_volume_information_file(void)
1864 NTSTATUS status;
1865 HANDLE dir;
1866 WCHAR path[MAX_PATH];
1867 OBJECT_ATTRIBUTES attr;
1868 IO_STATUS_BLOCK io;
1869 UNICODE_STRING nameW;
1870 FILE_FS_VOLUME_INFORMATION *ffvi;
1871 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
1873 GetWindowsDirectoryW( path, MAX_PATH );
1874 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
1875 attr.Length = sizeof(attr);
1876 attr.RootDirectory = 0;
1877 attr.ObjectName = &nameW;
1878 attr.Attributes = OBJ_CASE_INSENSITIVE;
1879 attr.SecurityDescriptor = NULL;
1880 attr.SecurityQualityOfService = NULL;
1882 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
1883 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
1884 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
1885 pRtlFreeUnicodeString( &nameW );
1887 ZeroMemory( buf, sizeof(buf) );
1888 U(io).Status = 0xdadadada;
1889 io.Information = 0xcacacaca;
1891 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
1893 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
1895 todo_wine
1897 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
1898 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
1900 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1901 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1902 io.Information);
1904 ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
1905 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
1906 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
1908 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
1910 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
1912 CloseHandle( dir );
1915 static void test_query_attribute_information_file(void)
1917 NTSTATUS status;
1918 HANDLE dir;
1919 WCHAR path[MAX_PATH];
1920 OBJECT_ATTRIBUTES attr;
1921 IO_STATUS_BLOCK io;
1922 UNICODE_STRING nameW;
1923 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
1924 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
1926 GetWindowsDirectoryW( path, MAX_PATH );
1927 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
1928 attr.Length = sizeof(attr);
1929 attr.RootDirectory = 0;
1930 attr.ObjectName = &nameW;
1931 attr.Attributes = OBJ_CASE_INSENSITIVE;
1932 attr.SecurityDescriptor = NULL;
1933 attr.SecurityQualityOfService = NULL;
1935 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
1936 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
1937 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
1938 pRtlFreeUnicodeString( &nameW );
1940 ZeroMemory( buf, sizeof(buf) );
1941 U(io).Status = 0xdadadada;
1942 io.Information = 0xcacacaca;
1944 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
1946 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
1948 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
1949 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
1950 ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
1951 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
1952 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
1954 trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
1955 ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
1956 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
1958 CloseHandle( dir );
1961 static void test_NtCreateFile(void)
1963 static const struct test_data
1965 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
1966 } td[] =
1968 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1969 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
1970 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1971 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
1972 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
1973 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1974 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
1975 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1976 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1977 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
1978 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
1979 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1980 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1981 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
1982 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1983 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1984 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1985 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
1986 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
1988 static const WCHAR fooW[] = {'f','o','o',0};
1989 NTSTATUS status;
1990 HANDLE handle;
1991 WCHAR path[MAX_PATH];
1992 OBJECT_ATTRIBUTES attr;
1993 IO_STATUS_BLOCK io;
1994 UNICODE_STRING nameW;
1995 DWORD ret, i;
1997 GetTempPathW(MAX_PATH, path);
1998 GetTempFileNameW(path, fooW, 0, path);
1999 DeleteFileW(path);
2000 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
2002 attr.Length = sizeof(attr);
2003 attr.RootDirectory = NULL;
2004 attr.ObjectName = &nameW;
2005 attr.Attributes = OBJ_CASE_INSENSITIVE;
2006 attr.SecurityDescriptor = NULL;
2007 attr.SecurityQualityOfService = NULL;
2009 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2011 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
2012 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
2013 td[i].disposition, 0, NULL, 0);
2015 ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
2017 if (!status)
2019 ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
2021 ret = GetFileAttributesW(path);
2022 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
2023 /* FIXME: leave only 'else' case below once Wine is fixed */
2024 if (ret != td[i].attrib_out)
2026 todo_wine
2027 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
2028 SetFileAttributesW(path, td[i].attrib_out);
2030 else
2031 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
2033 CloseHandle(handle);
2036 if (td[i].needs_cleanup)
2038 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
2039 DeleteFileW(path);
2043 pRtlFreeUnicodeString( &nameW );
2044 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
2045 DeleteFileW( path );
2048 static void test_read_write(void)
2050 static const char contents[14] = "1234567890abcd";
2051 char buf[256];
2052 HANDLE hfile;
2053 OVERLAPPED ovl;
2054 IO_STATUS_BLOCK iob;
2055 DWORD ret, bytes, status, off;
2056 LARGE_INTEGER offset;
2057 LONG i;
2059 U(iob).Status = -1;
2060 iob.Information = -1;
2061 offset.QuadPart = 0;
2062 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2063 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
2064 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2065 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2067 U(iob).Status = -1;
2068 iob.Information = -1;
2069 offset.QuadPart = 0;
2070 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2071 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
2072 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2073 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2075 hfile = create_temp_file(0);
2076 if (!hfile) return;
2078 U(iob).Status = -1;
2079 iob.Information = -1;
2080 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
2081 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
2082 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2083 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2085 U(iob).Status = -1;
2086 iob.Information = -1;
2087 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
2088 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
2089 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2090 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2092 U(iob).Status = -1;
2093 iob.Information = -1;
2094 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
2095 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2096 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2097 ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
2099 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2101 U(iob).Status = -1;
2102 iob.Information = -1;
2103 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
2104 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
2105 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2106 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2107 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
2109 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2110 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2112 bytes = 0xdeadbeef;
2113 SetLastError(0xdeadbeef);
2114 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
2115 ok(!ret, "ReadFile should fail\n");
2116 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2117 ok(bytes == 0, "bytes %u\n", bytes);
2119 bytes = 0xdeadbeef;
2120 SetLastError(0xdeadbeef);
2121 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
2122 ok(ret, "ReadFile error %d\n", GetLastError());
2123 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2124 ok(bytes == 0, "bytes %u\n", bytes);
2126 bytes = 0xdeadbeef;
2127 SetLastError(0xdeadbeef);
2128 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2129 ok(ret, "ReadFile error %d\n", GetLastError());
2130 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2131 ok(bytes == 0, "bytes %u\n", bytes);
2133 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2135 bytes = 0;
2136 SetLastError(0xdeadbeef);
2137 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2138 ok(ret, "ReadFile error %d\n", GetLastError());
2139 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2140 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
2142 for (i = -20; i < -1; i++)
2144 if (i == -2) continue;
2146 U(iob).Status = -1;
2147 iob.Information = -1;
2148 offset.QuadPart = (LONGLONG)i;
2149 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
2150 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2151 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2152 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2155 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
2157 U(iob).Status = -1;
2158 iob.Information = -1;
2159 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2160 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
2161 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2162 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2163 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
2165 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2166 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2168 U(iob).Status = -1;
2169 iob.Information = -1;
2170 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
2171 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2172 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2173 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2175 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2177 bytes = 0;
2178 SetLastError(0xdeadbeef);
2179 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2180 ok(ret, "ReadFile error %d\n", GetLastError());
2181 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2182 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2183 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
2185 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2186 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2188 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2190 bytes = 0;
2191 SetLastError(0xdeadbeef);
2192 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
2193 ok(ret, "WriteFile error %d\n", GetLastError());
2194 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2196 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2197 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2199 /* test reading beyond EOF */
2200 bytes = -1;
2201 SetLastError(0xdeadbeef);
2202 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2203 ok(ret, "ReadFile error %d\n", GetLastError());
2204 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2205 ok(bytes == 0, "bytes %u\n", bytes);
2207 bytes = -1;
2208 SetLastError(0xdeadbeef);
2209 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
2210 ok(ret, "ReadFile error %d\n", GetLastError());
2211 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2212 ok(bytes == 0, "bytes %u\n", bytes);
2214 bytes = -1;
2215 SetLastError(0xdeadbeef);
2216 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
2217 ok(ret, "ReadFile error %d\n", GetLastError());
2218 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2219 ok(bytes == 0, "bytes %u\n", bytes);
2221 S(U(ovl)).Offset = sizeof(contents);
2222 S(U(ovl)).OffsetHigh = 0;
2223 ovl.Internal = -1;
2224 ovl.InternalHigh = -1;
2225 ovl.hEvent = 0;
2226 bytes = -1;
2227 SetLastError(0xdeadbeef);
2228 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2229 ok(!ret, "ReadFile should fail\n");
2230 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
2231 ok(bytes == 0, "bytes %u\n", bytes);
2232 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
2233 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2235 S(U(ovl)).Offset = sizeof(contents);
2236 S(U(ovl)).OffsetHigh = 0;
2237 ovl.Internal = -1;
2238 ovl.InternalHigh = -1;
2239 ovl.hEvent = 0;
2240 bytes = -1;
2241 SetLastError(0xdeadbeef);
2242 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
2243 ok(ret, "ReadFile error %d\n", GetLastError());
2244 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2245 ok(bytes == 0, "bytes %u\n", bytes);
2246 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2247 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2249 U(iob).Status = -1;
2250 iob.Information = -1;
2251 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
2252 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2253 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2254 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2256 U(iob).Status = -1;
2257 iob.Information = -1;
2258 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
2259 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2260 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2261 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2263 U(iob).Status = -1;
2264 iob.Information = -1;
2265 offset.QuadPart = sizeof(contents);
2266 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2267 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2268 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2269 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2271 U(iob).Status = -1;
2272 iob.Information = -1;
2273 offset.QuadPart = sizeof(contents);
2274 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
2275 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2276 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2277 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2279 U(iob).Status = -1;
2280 iob.Information = -1;
2281 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2282 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2283 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2284 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2285 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2287 U(iob).Status = -1;
2288 iob.Information = -1;
2289 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2290 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
2291 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2292 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2293 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2295 for (i = -20; i < 0; i++)
2297 if (i == -2) continue;
2299 U(iob).Status = -1;
2300 iob.Information = -1;
2301 offset.QuadPart = (LONGLONG)i;
2302 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2303 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2304 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2305 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2308 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2310 bytes = 0;
2311 SetLastError(0xdeadbeef);
2312 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2313 ok(ret, "ReadFile error %d\n", GetLastError());
2314 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2315 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
2317 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2318 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2320 U(iob).Status = -1;
2321 iob.Information = -1;
2322 offset.QuadPart = 0;
2323 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2324 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2325 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2326 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
2327 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
2329 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2330 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2332 U(iob).Status = -1;
2333 iob.Information = -1;
2334 offset.QuadPart = sizeof(contents) - 4;
2335 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
2336 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2337 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2338 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
2340 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2341 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2343 U(iob).Status = -1;
2344 iob.Information = -1;
2345 offset.QuadPart = 0;
2346 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2347 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2348 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2349 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
2350 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2351 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
2353 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2354 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2356 S(U(ovl)).Offset = sizeof(contents) - 4;
2357 S(U(ovl)).OffsetHigh = 0;
2358 ovl.hEvent = 0;
2359 bytes = 0;
2360 SetLastError(0xdeadbeef);
2361 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
2362 ok(ret, "WriteFile error %d\n", GetLastError());
2363 ok(bytes == 4, "bytes %u\n", bytes);
2365 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2366 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2368 S(U(ovl)).Offset = 0;
2369 S(U(ovl)).OffsetHigh = 0;
2370 ovl.Internal = -1;
2371 ovl.InternalHigh = -1;
2372 ovl.hEvent = 0;
2373 bytes = 0;
2374 SetLastError(0xdeadbeef);
2375 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2376 ok(ret, "ReadFile error %d\n", GetLastError());
2377 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2378 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2379 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
2380 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2381 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
2383 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2384 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2386 CloseHandle(hfile);
2388 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
2389 if (!hfile) return;
2391 bytes = 0xdeadbeef;
2392 SetLastError(0xdeadbeef);
2393 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
2394 ok(!ret, "ReadFile should fail\n");
2395 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2396 ok(bytes == 0, "bytes %u\n", bytes);
2398 S(U(ovl)).Offset = 0;
2399 S(U(ovl)).OffsetHigh = 0;
2400 ovl.Internal = -1;
2401 ovl.InternalHigh = -1;
2402 ovl.hEvent = 0;
2403 bytes = 0xdeadbeef;
2404 SetLastError(0xdeadbeef);
2405 /* ReadFile return value depends on Windows version and testing it is not practical */
2406 ReadFile(hfile, buf, 0, &bytes, &ovl);
2407 ok(bytes == 0, "bytes %u\n", bytes);
2408 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2409 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2411 bytes = 0xdeadbeef;
2412 SetLastError(0xdeadbeef);
2413 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
2414 ok(!ret, "WriteFile should fail\n");
2415 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2416 ok(bytes == 0, "bytes %u\n", bytes);
2418 U(iob).Status = -1;
2419 iob.Information = -1;
2420 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
2421 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
2422 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2423 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2425 for (i = -20; i < -1; i++)
2427 U(iob).Status = -1;
2428 iob.Information = -1;
2429 offset.QuadPart = (LONGLONG)i;
2430 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
2431 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2432 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2433 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2436 U(iob).Status = -1;
2437 iob.Information = -1;
2438 offset.QuadPart = 0;
2439 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
2440 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
2441 if (status == STATUS_PENDING)
2443 ret = WaitForSingleObject(hfile, 3000);
2444 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2446 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2447 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
2449 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2450 ok(off == 0, "expected 0, got %u\n", off);
2452 bytes = 0xdeadbeef;
2453 SetLastError(0xdeadbeef);
2454 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2455 ok(!ret, "ReadFile should fail\n");
2456 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2457 ok(bytes == 0, "bytes %u\n", bytes);
2459 U(iob).Status = -1;
2460 iob.Information = -1;
2461 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
2462 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
2463 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2464 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2466 for (i = -20; i < 0; i++)
2468 U(iob).Status = -1;
2469 iob.Information = -1;
2470 offset.QuadPart = (LONGLONG)i;
2471 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2472 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2473 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2474 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2477 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2478 ok(off == 0, "expected 0, got %u\n", off);
2480 /* test reading beyond EOF */
2481 offset.QuadPart = sizeof(contents);
2482 S(U(ovl)).Offset = offset.u.LowPart;
2483 S(U(ovl)).OffsetHigh = offset.u.HighPart;
2484 ovl.Internal = -1;
2485 ovl.InternalHigh = -1;
2486 ovl.hEvent = 0;
2487 bytes = 0xdeadbeef;
2488 SetLastError(0xdeadbeef);
2489 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2490 ok(!ret, "ReadFile should fail\n");
2491 ret = GetLastError();
2492 ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
2493 ok(bytes == 0, "bytes %u\n", bytes);
2495 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2496 ok(off == 0, "expected 0, got %u\n", off);
2498 if (ret == ERROR_IO_PENDING)
2500 bytes = 0xdeadbeef;
2501 SetLastError(0xdeadbeef);
2502 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2503 ok(!ret, "GetOverlappedResult should report FALSE\n");
2504 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
2505 ok(bytes == 0, "expected 0, read %u\n", bytes);
2506 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
2507 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2510 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2511 ok(off == 0, "expected 0, got %u\n", off);
2513 offset.QuadPart = sizeof(contents);
2514 S(U(ovl)).Offset = offset.u.LowPart;
2515 S(U(ovl)).OffsetHigh = offset.u.HighPart;
2516 ovl.Internal = -1;
2517 ovl.InternalHigh = -1;
2518 ovl.hEvent = 0;
2519 bytes = 0xdeadbeef;
2520 SetLastError(0xdeadbeef);
2521 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
2522 /* ReadFile return value depends on Windows version and testing it is not practical */
2523 if (!ret)
2524 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2525 ret = GetLastError();
2526 ok(bytes == 0, "bytes %u\n", bytes);
2528 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2529 ok(off == 0, "expected 0, got %u\n", off);
2531 if (ret == ERROR_IO_PENDING)
2533 bytes = 0xdeadbeef;
2534 SetLastError(0xdeadbeef);
2535 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2536 ok(ret, "GetOverlappedResult should report TRUE\n");
2537 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2538 ok(bytes == 0, "expected 0, read %u\n", bytes);
2539 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2540 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2543 offset.QuadPart = sizeof(contents);
2544 S(U(ovl)).Offset = offset.u.LowPart;
2545 S(U(ovl)).OffsetHigh = offset.u.HighPart;
2546 ovl.Internal = -1;
2547 ovl.InternalHigh = -1;
2548 ovl.hEvent = 0;
2549 bytes = 0xdeadbeef;
2550 SetLastError(0xdeadbeef);
2551 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
2552 /* ReadFile return value depends on Windows version and testing it is not practical */
2553 if (!ret)
2554 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2555 ret = GetLastError();
2556 ok(bytes == 0, "bytes %u\n", bytes);
2558 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2559 ok(off == 0, "expected 0, got %u\n", off);
2561 if (ret == ERROR_IO_PENDING)
2563 bytes = 0xdeadbeef;
2564 SetLastError(0xdeadbeef);
2565 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2566 ok(ret, "GetOverlappedResult should report TRUE\n");
2567 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2568 ok(bytes == 0, "expected 0, read %u\n", bytes);
2569 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2570 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2573 U(iob).Status = -1;
2574 iob.Information = -1;
2575 offset.QuadPart = sizeof(contents);
2576 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2577 if (status == STATUS_PENDING)
2579 ret = WaitForSingleObject(hfile, 3000);
2580 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2581 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2582 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2584 else
2586 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2587 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2588 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2591 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2592 ok(off == 0, "expected 0, got %u\n", off);
2594 U(iob).Status = -1;
2595 iob.Information = -1;
2596 offset.QuadPart = sizeof(contents);
2597 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
2598 if (status == STATUS_PENDING)
2600 ret = WaitForSingleObject(hfile, 3000);
2601 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2602 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2603 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2605 else
2607 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
2608 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2609 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2612 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2613 ok(off == 0, "expected 0, got %u\n", off);
2615 S(U(ovl)).Offset = 0;
2616 S(U(ovl)).OffsetHigh = 0;
2617 ovl.Internal = -1;
2618 ovl.InternalHigh = -1;
2619 ovl.hEvent = 0;
2620 bytes = 0;
2621 SetLastError(0xdeadbeef);
2622 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2623 /* ReadFile return value depends on Windows version and testing it is not practical */
2624 if (!ret)
2626 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2627 ok(bytes == 0, "bytes %u\n", bytes);
2629 else ok(bytes == 14, "bytes %u\n", bytes);
2630 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2631 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
2633 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2634 ok(off == 0, "expected 0, got %u\n", off);
2636 bytes = 0xdeadbeef;
2637 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2638 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
2639 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2640 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2641 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
2642 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
2644 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2645 ok(off == 0, "expected 0, got %u\n", off);
2647 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
2648 SetEndOfFile(hfile);
2649 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2651 U(iob).Status = -1;
2652 iob.Information = -1;
2653 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
2654 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
2655 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
2656 if (status == STATUS_PENDING)
2658 ret = WaitForSingleObject(hfile, 3000);
2659 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2661 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2662 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
2664 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2665 ok(off == 0, "expected 0, got %u\n", off);
2667 U(iob).Status = -1;
2668 iob.Information = -1;
2669 offset.QuadPart = 0;
2670 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2671 ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
2672 if (status == STATUS_PENDING)
2674 ret = WaitForSingleObject(hfile, 3000);
2675 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2677 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2678 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
2680 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2681 ok(off == 0, "expected 0, got %u\n", off);
2683 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2684 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
2686 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2687 ok(off == 0, "expected 0, got %u\n", off);
2689 S(U(ovl)).Offset = sizeof(contents) - 4;
2690 S(U(ovl)).OffsetHigh = 0;
2691 ovl.Internal = -1;
2692 ovl.InternalHigh = -1;
2693 ovl.hEvent = 0;
2694 bytes = 0;
2695 SetLastError(0xdeadbeef);
2696 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
2697 /* WriteFile return value depends on Windows version and testing it is not practical */
2698 if (!ret)
2700 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2701 ok(bytes == 0, "bytes %u\n", bytes);
2703 else ok(bytes == 4, "bytes %u\n", bytes);
2704 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2705 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
2707 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2708 ok(off == 0, "expected 0, got %u\n", off);
2710 bytes = 0xdeadbeef;
2711 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2712 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
2713 ok(bytes == 4, "bytes %u\n", bytes);
2714 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2715 ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
2717 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2718 ok(off == 0, "expected 0, got %u\n", off);
2720 S(U(ovl)).Offset = 0;
2721 S(U(ovl)).OffsetHigh = 0;
2722 ovl.Internal = -1;
2723 ovl.InternalHigh = -1;
2724 ovl.hEvent = 0;
2725 bytes = 0;
2726 SetLastError(0xdeadbeef);
2727 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2728 /* ReadFile return value depends on Windows version and testing it is not practical */
2729 if (!ret)
2731 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2732 ok(bytes == 0, "bytes %u\n", bytes);
2734 else ok(bytes == 14, "bytes %u\n", bytes);
2735 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2736 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
2738 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2739 ok(off == 0, "expected 0, got %u\n", off);
2741 bytes = 0xdeadbeef;
2742 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2743 ok(ret, "GetOverlappedResult error %d\n", GetLastError());
2744 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2745 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2746 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
2747 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2748 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
2750 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2751 ok(off == 0, "expected 0, got %u\n", off);
2753 CloseHandle(hfile);
2756 START_TEST(file)
2758 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
2759 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
2760 if (!hntdll)
2762 skip("not running on NT, skipping test\n");
2763 return;
2766 pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
2767 pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
2769 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
2770 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
2771 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
2772 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
2773 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
2774 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
2775 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
2776 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
2777 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
2778 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
2779 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
2780 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
2781 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
2782 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
2783 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
2784 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
2785 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
2786 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
2787 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
2788 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
2789 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
2790 pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
2792 test_read_write();
2793 test_NtCreateFile();
2794 create_file_test();
2795 open_file_test();
2796 delete_file_test();
2797 read_file_test();
2798 append_file_test();
2799 nt_mailslot_test();
2800 test_iocompletion();
2801 test_file_basic_information();
2802 test_file_all_information();
2803 test_file_both_information();
2804 test_file_name_information();
2805 test_file_full_size_information();
2806 test_file_all_name_information();
2807 test_file_disposition_information();
2808 test_query_volume_information_file();
2809 test_query_attribute_information_file();