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
23 * We use function pointers here as there is no import library for NTDLL on
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 "wine/winternl.h"
39 #include "wine/winioctl.h"
42 typedef struct _REPARSE_DATA_BUFFER
{
44 USHORT ReparseDataLength
;
46 _ANONYMOUS_UNION
union {
48 USHORT SubstituteNameOffset
;
49 USHORT SubstituteNameLength
;
50 USHORT PrintNameOffset
;
51 USHORT PrintNameLength
;
54 } SymbolicLinkReparseBuffer
;
56 USHORT SubstituteNameOffset
;
57 USHORT SubstituteNameLength
;
58 USHORT PrintNameOffset
;
59 USHORT PrintNameLength
;
61 } MountPointReparseBuffer
;
64 } GenericReparseBuffer
;
66 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
68 #ifndef IO_COMPLETION_ALL_ACCESS
69 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
72 static BOOL (WINAPI
* pGetVolumePathNameW
)(LPCWSTR
, LPWSTR
, DWORD
);
73 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)( LPWSTR
, UINT
);
75 static VOID (WINAPI
*pRtlFreeUnicodeString
)( PUNICODE_STRING
);
76 static VOID (WINAPI
*pRtlInitUnicodeString
)( PUNICODE_STRING
, LPCWSTR
);
77 static BOOL (WINAPI
*pRtlDosPathNameToNtPathName_U
)( LPCWSTR
, PUNICODE_STRING
, PWSTR
*, CURDIR
* );
78 static NTSTATUS (WINAPI
*pRtlWow64EnableFsRedirectionEx
)( ULONG
, ULONG
* );
80 static NTSTATUS (WINAPI
*pNtCreateMailslotFile
)( PHANDLE
, ULONG
, POBJECT_ATTRIBUTES
, PIO_STATUS_BLOCK
,
81 ULONG
, ULONG
, ULONG
, PLARGE_INTEGER
);
82 static NTSTATUS (WINAPI
*pNtCreateFile
)(PHANDLE
,ACCESS_MASK
,POBJECT_ATTRIBUTES
,PIO_STATUS_BLOCK
,PLARGE_INTEGER
,ULONG
,ULONG
,ULONG
,ULONG
,PVOID
,ULONG
);
83 static NTSTATUS (WINAPI
*pNtOpenFile
)(PHANDLE
,ACCESS_MASK
,POBJECT_ATTRIBUTES
,PIO_STATUS_BLOCK
,ULONG
,ULONG
);
84 static NTSTATUS (WINAPI
*pNtDeleteFile
)(POBJECT_ATTRIBUTES ObjectAttributes
);
85 static NTSTATUS (WINAPI
*pNtReadFile
)(HANDLE hFile
, HANDLE hEvent
,
86 PIO_APC_ROUTINE apc
, void* apc_user
,
87 PIO_STATUS_BLOCK io_status
, void* buffer
, ULONG length
,
88 PLARGE_INTEGER offset
, PULONG key
);
89 static NTSTATUS (WINAPI
*pNtWriteFile
)(HANDLE hFile
, HANDLE hEvent
,
90 PIO_APC_ROUTINE apc
, void* apc_user
,
91 PIO_STATUS_BLOCK io_status
,
92 const void* buffer
, ULONG length
,
93 PLARGE_INTEGER offset
, PULONG key
);
94 static NTSTATUS (WINAPI
*pNtCancelIoFile
)(HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
95 static NTSTATUS (WINAPI
*pNtCancelIoFileEx
)(HANDLE hFile
, PIO_STATUS_BLOCK iosb
, PIO_STATUS_BLOCK io_status
);
96 static NTSTATUS (WINAPI
*pNtClose
)( PHANDLE
);
98 static NTSTATUS (WINAPI
*pNtCreateIoCompletion
)(PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
, ULONG
);
99 static NTSTATUS (WINAPI
*pNtOpenIoCompletion
)(PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
);
100 static NTSTATUS (WINAPI
*pNtQueryIoCompletion
)(HANDLE
, IO_COMPLETION_INFORMATION_CLASS
, PVOID
, ULONG
, PULONG
);
101 static NTSTATUS (WINAPI
*pNtRemoveIoCompletion
)(HANDLE
, PULONG_PTR
, PULONG_PTR
, PIO_STATUS_BLOCK
, PLARGE_INTEGER
);
102 static NTSTATUS (WINAPI
*pNtSetIoCompletion
)(HANDLE
, ULONG_PTR
, ULONG_PTR
, NTSTATUS
, SIZE_T
);
103 static NTSTATUS (WINAPI
*pNtSetInformationFile
)(HANDLE
, PIO_STATUS_BLOCK
, PVOID
, ULONG
, FILE_INFORMATION_CLASS
);
104 static NTSTATUS (WINAPI
*pNtQueryInformationFile
)(HANDLE
, PIO_STATUS_BLOCK
, PVOID
, ULONG
, FILE_INFORMATION_CLASS
);
105 static NTSTATUS (WINAPI
*pNtQueryDirectoryFile
)(HANDLE
,HANDLE
,PIO_APC_ROUTINE
,PVOID
,PIO_STATUS_BLOCK
,
106 PVOID
,ULONG
,FILE_INFORMATION_CLASS
,BOOLEAN
,PUNICODE_STRING
,BOOLEAN
);
107 static NTSTATUS (WINAPI
*pNtQueryVolumeInformationFile
)(HANDLE
,PIO_STATUS_BLOCK
,PVOID
,ULONG
,FS_INFORMATION_CLASS
);
109 static inline BOOL
is_signaled( HANDLE obj
)
111 return WaitForSingleObject( obj
, 0 ) == WAIT_OBJECT_0
;
114 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
115 #define TEST_BUF_LEN 3
117 static BOOL
create_pipe( HANDLE
*read
, HANDLE
*write
, ULONG flags
, ULONG size
)
119 *read
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_INBOUND
| flags
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
120 1, size
, size
, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
121 ok(*read
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
123 *write
= CreateFileA(PIPENAME
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
124 ok(*write
!= INVALID_HANDLE_VALUE
, "CreateFile failed (%d)\n", GetLastError());
129 static HANDLE
create_temp_file( ULONG flags
)
131 char path
[MAX_PATH
], buffer
[MAX_PATH
];
134 GetTempPathA( MAX_PATH
, path
);
135 GetTempFileNameA( path
, "foo", 0, buffer
);
136 handle
= CreateFileA(buffer
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
137 flags
| FILE_FLAG_DELETE_ON_CLOSE
, 0);
138 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
139 return (handle
== INVALID_HANDLE_VALUE
) ? 0 : handle
;
142 #define CVALUE_FIRST 0xfffabbcc
143 #define CKEY_FIRST 0x1030341
144 #define CKEY_SECOND 0x132E46
146 static ULONG_PTR completionKey
;
147 static IO_STATUS_BLOCK ioSb
;
148 static ULONG_PTR completionValue
;
150 static ULONG
get_pending_msgs(HANDLE h
)
155 res
= pNtQueryIoCompletion( h
, IoCompletionBasicInformation
, &a
, sizeof(a
), &req
);
156 ok( res
== STATUS_SUCCESS
, "NtQueryIoCompletion failed: %x\n", res
);
157 if (res
!= STATUS_SUCCESS
) return -1;
158 ok( req
== sizeof(a
), "Unexpected response size: %x\n", req
);
162 static BOOL
get_msg(HANDLE h
)
164 LARGE_INTEGER timeout
= {{-10000000*3}};
165 DWORD res
= pNtRemoveIoCompletion( h
, &completionKey
, &completionValue
, &ioSb
, &timeout
);
166 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletion failed: %x\n", res
);
167 if (res
!= STATUS_SUCCESS
)
169 completionKey
= completionValue
= 0;
170 memset(&ioSb
, 0, sizeof(ioSb
));
177 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
181 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
182 iosb
, U(*iosb
).Status
, iosb
->Information
);
184 ok( !reserved
, "reserved is not 0: %x\n", reserved
);
187 static void create_file_test(void)
189 static const WCHAR systemrootW
[] = {'\\','S','y','s','t','e','m','R','o','o','t',
190 '\\','f','a','i','l','i','n','g',0};
191 static const WCHAR questionmarkInvalidNameW
[] = {'a','f','i','l','e','?',0};
192 static const WCHAR pipeInvalidNameW
[] = {'a','|','b',0};
195 WCHAR path
[MAX_PATH
];
196 OBJECT_ATTRIBUTES attr
;
198 UNICODE_STRING nameW
;
200 GetCurrentDirectoryW( MAX_PATH
, path
);
201 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
202 attr
.Length
= sizeof(attr
);
203 attr
.RootDirectory
= 0;
204 attr
.ObjectName
= &nameW
;
205 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
206 attr
.SecurityDescriptor
= NULL
;
207 attr
.SecurityQualityOfService
= NULL
;
209 /* try various open modes and options on directories */
210 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
211 FILE_OPEN
, FILE_DIRECTORY_FILE
, NULL
, 0 );
212 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
215 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
216 FILE_CREATE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
217 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
218 "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_IF
, FILE_DIRECTORY_FILE
, NULL
, 0 );
222 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
225 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
226 FILE_SUPERSEDE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
227 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
229 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
230 FILE_OVERWRITE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
231 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
233 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
234 FILE_OVERWRITE_IF
, FILE_DIRECTORY_FILE
, NULL
, 0 );
235 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
237 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
238 FILE_OPEN
, 0, NULL
, 0 );
239 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
242 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
243 FILE_CREATE
, 0, NULL
, 0 );
244 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
245 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
247 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
248 FILE_OPEN_IF
, 0, NULL
, 0 );
249 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
252 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
253 FILE_SUPERSEDE
, 0, NULL
, 0 );
254 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
255 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
257 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
258 FILE_OVERWRITE
, 0, NULL
, 0 );
259 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
260 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
262 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
263 FILE_OVERWRITE_IF
, 0, NULL
, 0 );
264 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
265 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
267 pRtlFreeUnicodeString( &nameW
);
269 pRtlInitUnicodeString( &nameW
, systemrootW
);
270 attr
.Length
= sizeof(attr
);
271 attr
.RootDirectory
= NULL
;
272 attr
.ObjectName
= &nameW
;
273 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
274 attr
.SecurityDescriptor
= NULL
;
275 attr
.SecurityQualityOfService
= NULL
;
277 status
= pNtCreateFile( &dir
, FILE_APPEND_DATA
, &attr
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0,
278 FILE_OPEN_IF
, FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
280 ok( status
== STATUS_INVALID_PARAMETER
,
281 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
283 /* Invalid chars in file/dirnames */
284 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW
, &nameW
, NULL
, NULL
);
285 attr
.ObjectName
= &nameW
;
286 status
= pNtCreateFile(&dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
287 FILE_SHARE_READ
, FILE_CREATE
,
288 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
289 ok(status
== STATUS_OBJECT_NAME_INVALID
,
290 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
292 status
= pNtCreateFile(&file
, GENERIC_WRITE
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
294 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
295 ok(status
== STATUS_OBJECT_NAME_INVALID
,
296 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
297 pRtlFreeUnicodeString(&nameW
);
299 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW
, &nameW
, NULL
, NULL
);
300 attr
.ObjectName
= &nameW
;
301 status
= pNtCreateFile(&dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
302 FILE_SHARE_READ
, FILE_CREATE
,
303 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
304 ok(status
== STATUS_OBJECT_NAME_INVALID
,
305 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
307 status
= pNtCreateFile(&file
, GENERIC_WRITE
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
309 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
310 ok(status
== STATUS_OBJECT_NAME_INVALID
,
311 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
312 pRtlFreeUnicodeString(&nameW
);
315 static void open_file_test(void)
318 HANDLE dir
, root
, handle
;
319 WCHAR path
[MAX_PATH
];
321 OBJECT_ATTRIBUTES attr
;
323 UNICODE_STRING nameW
;
327 len
= GetWindowsDirectoryW( path
, MAX_PATH
);
328 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
329 attr
.Length
= sizeof(attr
);
330 attr
.RootDirectory
= 0;
331 attr
.ObjectName
= &nameW
;
332 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
333 attr
.SecurityDescriptor
= NULL
;
334 attr
.SecurityQualityOfService
= NULL
;
335 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
336 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
337 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
338 pRtlFreeUnicodeString( &nameW
);
340 path
[3] = 0; /* root of the drive */
341 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
342 status
= pNtOpenFile( &root
, GENERIC_READ
, &attr
, &io
,
343 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
344 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
345 pRtlFreeUnicodeString( &nameW
);
347 /* test opening system dir with RootDirectory set to windows dir */
348 GetSystemDirectoryW( path
, MAX_PATH
);
349 while (path
[len
] == '\\') len
++;
350 nameW
.Buffer
= path
+ len
;
351 nameW
.Length
= lstrlenW(path
+ len
) * sizeof(WCHAR
);
352 attr
.RootDirectory
= dir
;
353 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
354 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
355 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
356 CloseHandle( handle
);
358 /* try uppercase name */
359 for (i
= len
; path
[i
]; i
++) if (path
[i
] >= 'a' && path
[i
] <= 'z') path
[i
] -= 'a' - 'A';
360 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
361 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
362 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
363 CloseHandle( handle
);
365 /* try with leading backslash */
367 nameW
.Length
+= sizeof(WCHAR
);
368 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
369 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
370 ok( status
== STATUS_INVALID_PARAMETER
||
371 status
== STATUS_OBJECT_NAME_INVALID
||
372 status
== STATUS_OBJECT_PATH_SYNTAX_BAD
,
373 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
374 if (!status
) CloseHandle( handle
);
376 /* try with empty name */
378 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
379 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
380 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
381 CloseHandle( handle
);
383 /* try open by file id */
385 while (!pNtQueryDirectoryFile( dir
, NULL
, NULL
, NULL
, &io
, data
, sizeof(data
),
386 FileIdBothDirectoryInformation
, TRUE
, NULL
, restart
))
388 FILE_ID_BOTH_DIRECTORY_INFORMATION
*info
= (FILE_ID_BOTH_DIRECTORY_INFORMATION
*)data
;
392 if (!info
->FileId
.QuadPart
) continue;
394 nameW
.Buffer
= (WCHAR
*)&info
->FileId
;
395 nameW
.Length
= sizeof(info
->FileId
);
396 info
->FileName
[info
->FileNameLength
/sizeof(WCHAR
)] = 0;
397 attr
.RootDirectory
= dir
;
398 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
399 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
401 FILE_OPEN_BY_FILE_ID
|
402 ((info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ? FILE_DIRECTORY_FILE
: 0) );
403 ok( status
== STATUS_SUCCESS
|| status
== STATUS_ACCESS_DENIED
|| status
== STATUS_NOT_IMPLEMENTED
|| status
== STATUS_SHARING_VIOLATION
,
404 "open %s failed %x\n", wine_dbgstr_w(info
->FileName
), status
);
405 if (status
== STATUS_NOT_IMPLEMENTED
)
407 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
410 if (status
== STATUS_SHARING_VIOLATION
)
411 trace( "%s is currently open\n", wine_dbgstr_w(info
->FileName
) );
414 BYTE buf
[sizeof(FILE_ALL_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
416 if (!pNtQueryInformationFile( handle
, &io
, buf
, sizeof(buf
), FileAllInformation
))
418 FILE_ALL_INFORMATION
*fai
= (FILE_ALL_INFORMATION
*)buf
;
420 /* check that it's the same file/directory */
422 /* don't check the size for directories */
423 if (!(info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
424 ok( info
->EndOfFile
.QuadPart
== fai
->StandardInformation
.EndOfFile
.QuadPart
,
425 "mismatched file size for %s\n", wine_dbgstr_w(info
->FileName
));
427 ok( info
->CreationTime
.QuadPart
== fai
->BasicInformation
.CreationTime
.QuadPart
,
428 "mismatched creation time for %s\n", wine_dbgstr_w(info
->FileName
));
430 CloseHandle( handle
);
432 /* try same thing from drive root */
433 attr
.RootDirectory
= root
;
434 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
435 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
436 FILE_OPEN_BY_FILE_ID
|
437 ((info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ? FILE_DIRECTORY_FILE
: 0) );
438 ok( status
== STATUS_SUCCESS
|| status
== STATUS_NOT_IMPLEMENTED
,
439 "open %s failed %x\n", wine_dbgstr_w(info
->FileName
), status
);
440 if (!status
) CloseHandle( handle
);
448 static void delete_file_test(void)
451 OBJECT_ATTRIBUTES attr
;
452 UNICODE_STRING nameW
;
453 WCHAR pathW
[MAX_PATH
];
454 WCHAR pathsubW
[MAX_PATH
];
455 static const WCHAR testdirW
[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
456 static const WCHAR subdirW
[] = {'\\','s','u','b',0};
458 ret
= GetTempPathW(MAX_PATH
, pathW
);
461 ok(0, "couldn't get temp dir\n");
464 if (ret
+ sizeof(testdirW
)/sizeof(WCHAR
)-1 + sizeof(subdirW
)/sizeof(WCHAR
)-1 >= MAX_PATH
)
466 ok(0, "MAX_PATH exceeded in constructing paths\n");
470 lstrcatW(pathW
, testdirW
);
471 lstrcpyW(pathsubW
, pathW
);
472 lstrcatW(pathsubW
, subdirW
);
474 ret
= CreateDirectoryW(pathW
, NULL
);
475 ok(ret
== TRUE
, "couldn't create directory ntdeletefile\n");
476 if (!pRtlDosPathNameToNtPathName_U(pathW
, &nameW
, NULL
, NULL
))
478 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
482 attr
.Length
= sizeof(attr
);
483 attr
.RootDirectory
= 0;
484 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
485 attr
.ObjectName
= &nameW
;
486 attr
.SecurityDescriptor
= NULL
;
487 attr
.SecurityQualityOfService
= NULL
;
489 /* test NtDeleteFile on an empty directory */
490 ret
= pNtDeleteFile(&attr
);
491 ok(ret
== STATUS_SUCCESS
, "NtDeleteFile should succeed in removing an empty directory\n");
492 ret
= RemoveDirectoryW(pathW
);
493 ok(ret
== FALSE
, "expected to fail removing directory, NtDeleteFile should have removed it\n");
495 /* test NtDeleteFile on a non-empty directory */
496 ret
= CreateDirectoryW(pathW
, NULL
);
497 ok(ret
== TRUE
, "couldn't create directory ntdeletefile ?!\n");
498 ret
= CreateDirectoryW(pathsubW
, NULL
);
499 ok(ret
== TRUE
, "couldn't create directory subdir\n");
500 ret
= pNtDeleteFile(&attr
);
501 ok(ret
== STATUS_SUCCESS
, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
502 ret
= RemoveDirectoryW(pathsubW
);
503 ok(ret
== TRUE
, "expected to remove directory ntdeletefile\\sub\n");
504 ret
= RemoveDirectoryW(pathW
);
505 ok(ret
== TRUE
, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
507 pRtlFreeUnicodeString( &nameW
);
510 static void read_file_test(void)
512 const char text
[] = "foobar";
513 HANDLE handle
, read
, write
;
515 IO_STATUS_BLOCK iosb
, iosb2
;
519 LARGE_INTEGER offset
;
520 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
525 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
527 /* try read with no data */
528 U(iosb
).Status
= 0xdeadbabe;
529 iosb
.Information
= 0xdeadbeef;
530 ok( is_signaled( read
), "read handle is not signaled\n" );
531 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
532 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
533 ok( !is_signaled( read
), "read handle is signaled\n" );
534 ok( !is_signaled( event
), "event is signaled\n" );
535 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
536 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
537 ok( !apc_count
, "apc was called\n" );
538 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
539 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
540 /* iosb updated here by async i/o */
541 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
542 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
543 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
544 ok( !is_signaled( read
), "read handle is signaled\n" );
545 ok( is_signaled( event
), "event is not signaled\n" );
546 ok( !apc_count
, "apc was called\n" );
548 SleepEx( 1, FALSE
); /* non-alertable sleep */
549 ok( !apc_count
, "apc was called\n" );
550 SleepEx( 1, TRUE
); /* alertable sleep */
551 ok( apc_count
== 1, "apc not called\n" );
553 /* with no event, the pipe handle itself gets signaled */
555 U(iosb
).Status
= 0xdeadbabe;
556 iosb
.Information
= 0xdeadbeef;
557 ok( !is_signaled( read
), "read handle is not signaled\n" );
558 status
= pNtReadFile( read
, 0, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
559 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
560 ok( !is_signaled( read
), "read handle is signaled\n" );
561 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
562 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
563 ok( !apc_count
, "apc was called\n" );
564 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
565 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
566 /* iosb updated here by async i/o */
567 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
568 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
569 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
570 ok( is_signaled( read
), "read handle is signaled\n" );
571 ok( !apc_count
, "apc was called\n" );
573 SleepEx( 1, FALSE
); /* non-alertable sleep */
574 ok( !apc_count
, "apc was called\n" );
575 SleepEx( 1, TRUE
); /* alertable sleep */
576 ok( apc_count
== 1, "apc not called\n" );
578 /* now read with data ready */
580 U(iosb
).Status
= 0xdeadbabe;
581 iosb
.Information
= 0xdeadbeef;
583 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
584 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
585 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
586 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
587 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
588 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
589 ok( is_signaled( event
), "event is not signaled\n" );
590 ok( !apc_count
, "apc was called\n" );
591 SleepEx( 1, FALSE
); /* non-alertable sleep */
592 ok( !apc_count
, "apc was called\n" );
593 SleepEx( 1, TRUE
); /* alertable sleep */
594 ok( apc_count
== 1, "apc not called\n" );
596 /* try read with no data */
598 U(iosb
).Status
= 0xdeadbabe;
599 iosb
.Information
= 0xdeadbeef;
600 ok( is_signaled( event
), "event is not signaled\n" ); /* check that read resets the event */
601 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
602 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
603 ok( !is_signaled( event
), "event is signaled\n" );
604 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
605 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
606 ok( !apc_count
, "apc was called\n" );
607 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
608 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
609 /* partial read is good enough */
610 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
611 ok( is_signaled( event
), "event is signaled\n" );
612 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
613 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
614 ok( !apc_count
, "apc was called\n" );
615 SleepEx( 1, TRUE
); /* alertable sleep */
616 ok( apc_count
== 1, "apc was not called\n" );
618 /* read from disconnected pipe */
620 U(iosb
).Status
= 0xdeadbabe;
621 iosb
.Information
= 0xdeadbeef;
622 CloseHandle( write
);
623 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
624 ok( status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", status
);
625 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
626 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
627 ok( !is_signaled( event
), "event is signaled\n" );
628 ok( !apc_count
, "apc was called\n" );
629 SleepEx( 1, TRUE
); /* alertable sleep */
630 ok( !apc_count
, "apc was called\n" );
633 /* read from closed handle */
635 U(iosb
).Status
= 0xdeadbabe;
636 iosb
.Information
= 0xdeadbeef;
638 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
639 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
640 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
641 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
642 ok( is_signaled( event
), "event is signaled\n" ); /* not reset on invalid handle */
643 ok( !apc_count
, "apc was called\n" );
644 SleepEx( 1, TRUE
); /* alertable sleep */
645 ok( !apc_count
, "apc was called\n" );
647 /* disconnect while async read is in progress */
648 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
650 U(iosb
).Status
= 0xdeadbabe;
651 iosb
.Information
= 0xdeadbeef;
652 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
653 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
654 ok( !is_signaled( event
), "event is signaled\n" );
655 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
656 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
657 ok( !apc_count
, "apc was called\n" );
658 CloseHandle( write
);
659 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
660 ok( U(iosb
).Status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", U(iosb
).Status
);
661 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
662 ok( is_signaled( event
), "event is signaled\n" );
663 ok( !apc_count
, "apc was called\n" );
664 SleepEx( 1, TRUE
); /* alertable sleep */
665 ok( apc_count
== 1, "apc was not called\n" );
668 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
669 ret
= DuplicateHandle(GetCurrentProcess(), read
, GetCurrentProcess(), &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
670 ok(ret
, "Failed to duplicate handle: %d\n", GetLastError());
673 U(iosb
).Status
= 0xdeadbabe;
674 iosb
.Information
= 0xdeadbeef;
675 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
676 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
677 ok( !is_signaled( event
), "event is signaled\n" );
678 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
679 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
680 ok( !apc_count
, "apc was called\n" );
681 /* Cancel by other handle */
682 status
= pNtCancelIoFile( read
, &iosb2
);
683 ok(status
== STATUS_SUCCESS
, "failed to cancel by different handle: %x\n", status
);
684 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
685 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
686 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
687 ok( is_signaled( event
), "event is signaled\n" );
688 todo_wine
ok( !apc_count
, "apc was called\n" );
689 SleepEx( 1, TRUE
); /* alertable sleep */
690 ok( apc_count
== 1, "apc was not called\n" );
693 U(iosb
).Status
= 0xdeadbabe;
694 iosb
.Information
= 0xdeadbeef;
695 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
696 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
697 ok( !is_signaled( event
), "event is signaled\n" );
698 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
699 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
700 ok( !apc_count
, "apc was called\n" );
701 /* Close queued handle */
703 SleepEx( 1, TRUE
); /* alertable sleep */
704 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
705 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
706 status
= pNtCancelIoFile( read
, &iosb2
);
707 ok(status
== STATUS_INVALID_HANDLE
, "cancelled by closed handle?\n");
708 status
= pNtCancelIoFile( handle
, &iosb2
);
709 ok(status
== STATUS_SUCCESS
, "failed to cancel: %x\n", status
);
710 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
711 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
712 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
713 ok( is_signaled( event
), "event is signaled\n" );
714 todo_wine
ok( !apc_count
, "apc was called\n" );
715 SleepEx( 1, TRUE
); /* alertable sleep */
716 ok( apc_count
== 1, "apc was not called\n" );
717 CloseHandle( handle
);
718 CloseHandle( write
);
720 if (pNtCancelIoFileEx
)
722 /* Basic Cancel Ex */
723 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
726 U(iosb
).Status
= 0xdeadbabe;
727 iosb
.Information
= 0xdeadbeef;
728 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
729 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
730 ok( !is_signaled( event
), "event is signaled\n" );
731 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
732 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
733 ok( !apc_count
, "apc was called\n" );
734 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
735 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
736 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
737 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
738 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
739 ok( is_signaled( event
), "event is signaled\n" );
740 todo_wine
ok( !apc_count
, "apc was called\n" );
741 SleepEx( 1, TRUE
); /* alertable sleep */
742 ok( apc_count
== 1, "apc was not called\n" );
746 U(iosb
).Status
= 0xdeadbabe;
747 iosb
.Information
= 0xdeadbeef;
748 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
749 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
750 ok( !is_signaled( event
), "event is signaled\n" );
751 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
752 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
753 ok( !apc_count
, "apc was called\n" );
754 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
755 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
756 ok( !is_signaled( event
), "event is signaled\n" );
757 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
758 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
759 ok( !apc_count
, "apc was called\n" );
760 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
761 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
762 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
763 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
764 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
765 ok( is_signaled( event
), "event is signaled\n" );
766 todo_wine
ok( !apc_count
, "apc was called\n" );
767 SleepEx( 1, TRUE
); /* alertable sleep */
768 ok( apc_count
== 2, "apc was not called\n" );
771 CloseHandle( write
);
774 /* now try a real file */
775 if (!(handle
= create_temp_file( FILE_FLAG_OVERLAPPED
))) return;
777 U(iosb
).Status
= 0xdeadbabe;
778 iosb
.Information
= 0xdeadbeef;
781 status
= pNtWriteFile( handle
, event
, apc
, &apc_count
, &iosb
, text
, strlen(text
), &offset
, NULL
);
782 ok( status
== STATUS_SUCCESS
|| status
== STATUS_PENDING
, "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" );
792 U(iosb
).Status
= 0xdeadbabe;
793 iosb
.Information
= 0xdeadbeef;
796 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, strlen(text
) + 10, &offset
, NULL
);
797 ok( status
== STATUS_SUCCESS
||
798 status
== STATUS_PENDING
, /* vista */
799 "wrong status %x\n", status
);
800 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
801 ok( U(iosb
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(iosb
).Status
);
802 ok( iosb
.Information
== strlen(text
), "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 /* read beyond eof */
810 U(iosb
).Status
= 0xdeadbabe;
811 iosb
.Information
= 0xdeadbeef;
812 offset
.QuadPart
= strlen(text
) + 2;
813 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, &offset
, NULL
);
814 ok(status
== STATUS_PENDING
|| status
== STATUS_END_OF_FILE
/* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status
);
815 if (status
== STATUS_PENDING
) /* vista */
817 WaitForSingleObject( event
, 1000 );
818 ok( U(iosb
).Status
== STATUS_END_OF_FILE
, "wrong status %x\n", U(iosb
).Status
);
819 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
820 ok( is_signaled( event
), "event is signaled\n" );
821 ok( !apc_count
, "apc was called\n" );
822 SleepEx( 1, TRUE
); /* alertable sleep */
823 ok( apc_count
== 1, "apc was not called\n" );
825 CloseHandle( handle
);
827 /* now a non-overlapped file */
828 if (!(handle
= create_temp_file(0))) return;
830 U(iosb
).Status
= 0xdeadbabe;
831 iosb
.Information
= 0xdeadbeef;
833 status
= pNtWriteFile( handle
, event
, apc
, &apc_count
, &iosb
, text
, strlen(text
), &offset
, NULL
);
834 ok( status
== STATUS_END_OF_FILE
||
835 status
== STATUS_SUCCESS
||
836 status
== STATUS_PENDING
, /* vista */
837 "wrong status %x\n", status
);
838 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
839 ok( U(iosb
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(iosb
).Status
);
840 ok( iosb
.Information
== strlen(text
), "wrong info %lu\n", iosb
.Information
);
841 ok( is_signaled( event
), "event is signaled\n" );
842 ok( !apc_count
, "apc was called\n" );
843 SleepEx( 1, TRUE
); /* alertable sleep */
844 ok( apc_count
== 1, "apc was not called\n" );
847 U(iosb
).Status
= 0xdeadbabe;
848 iosb
.Information
= 0xdeadbeef;
851 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, strlen(text
) + 10, &offset
, NULL
);
852 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
853 ok( U(iosb
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(iosb
).Status
);
854 ok( iosb
.Information
== strlen(text
), "wrong info %lu\n", iosb
.Information
);
855 ok( is_signaled( event
), "event is signaled\n" );
856 ok( !apc_count
, "apc was called\n" );
857 SleepEx( 1, TRUE
); /* alertable sleep */
858 todo_wine
ok( !apc_count
, "apc was called\n" );
860 /* read beyond eof */
862 U(iosb
).Status
= 0xdeadbabe;
863 iosb
.Information
= 0xdeadbeef;
864 offset
.QuadPart
= strlen(text
) + 2;
866 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, &offset
, NULL
);
867 ok( status
== STATUS_END_OF_FILE
, "wrong status %x\n", status
);
868 ok( U(iosb
).Status
== STATUS_END_OF_FILE
, "wrong status %x\n", U(iosb
).Status
);
869 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
870 ok( is_signaled( event
), "event is not signaled\n" );
871 ok( !apc_count
, "apc was called\n" );
872 SleepEx( 1, TRUE
); /* alertable sleep */
873 ok( !apc_count
, "apc was called\n" );
875 CloseHandle( handle
);
877 CloseHandle( event
);
880 static void append_file_test(void)
882 static const char text
[6] = "foobar";
885 IO_STATUS_BLOCK iosb
;
886 LARGE_INTEGER offset
;
887 char path
[MAX_PATH
], buffer
[MAX_PATH
], buf
[16];
890 GetTempPathA( MAX_PATH
, path
);
891 GetTempFileNameA( path
, "foo", 0, buffer
);
893 handle
= CreateFileA(buffer
, FILE_WRITE_DATA
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
894 ok(handle
!= INVALID_HANDLE_VALUE
, "CreateFile error %d\n", GetLastError());
897 iosb
.Information
= -1;
898 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
, 2, NULL
, NULL
);
899 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
900 ok(U(iosb
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iosb
).Status
);
901 ok(iosb
.Information
== 2, "expected 2, got %lu\n", iosb
.Information
);
905 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
906 It matches the O_WRONLY|O_APPEND open() posix behavior */
907 handle
= CreateFileA(buffer
, FILE_APPEND_DATA
, 0, NULL
, OPEN_EXISTING
, 0, 0);
908 ok(handle
!= INVALID_HANDLE_VALUE
, "CreateFile error %d\n", GetLastError());
911 iosb
.Information
= -1;
913 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
+ 2, 2, &offset
, NULL
);
914 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
915 ok(U(iosb
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iosb
).Status
);
916 ok(iosb
.Information
== 2, "expected 2, got %lu\n", iosb
.Information
);
918 ret
= SetFilePointer(handle
, 0, NULL
, FILE_CURRENT
);
919 ok(ret
== 4, "expected 4, got %u\n", ret
);
922 iosb
.Information
= -1;
924 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
+ 4, 2, &offset
, NULL
);
925 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
926 ok(U(iosb
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iosb
).Status
);
927 ok(iosb
.Information
== 2, "expected 2, got %lu\n", iosb
.Information
);
929 ret
= SetFilePointer(handle
, 0, NULL
, FILE_CURRENT
);
930 ok(ret
== 6, "expected 6, got %u\n", ret
);
934 handle
= CreateFileA(buffer
, FILE_READ_DATA
| FILE_WRITE_DATA
| FILE_APPEND_DATA
, 0, NULL
, OPEN_EXISTING
, 0, 0);
935 ok(handle
!= INVALID_HANDLE_VALUE
, "CreateFile error %d\n", GetLastError());
937 memset(buf
, 0, sizeof(buf
));
939 iosb
.Information
= -1;
941 status
= pNtReadFile(handle
, 0, NULL
, NULL
, &iosb
, buf
, sizeof(buf
), &offset
, NULL
);
942 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#x\n", status
);
943 ok(U(iosb
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iosb
).Status
);
944 ok(iosb
.Information
== 6, "expected 6, got %lu\n", iosb
.Information
);
946 ok(memcmp(buf
, text
, 6) == 0, "wrong file contents: %s\n", buf
);
949 iosb
.Information
= -1;
951 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
+ 3, 3, &offset
, NULL
);
952 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
953 ok(U(iosb
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iosb
).Status
);
954 ok(iosb
.Information
== 3, "expected 3, got %lu\n", iosb
.Information
);
956 memset(buf
, 0, sizeof(buf
));
958 iosb
.Information
= -1;
960 status
= pNtReadFile(handle
, 0, NULL
, NULL
, &iosb
, buf
, sizeof(buf
), &offset
, NULL
);
961 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#x\n", status
);
962 ok(U(iosb
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iosb
).Status
);
963 ok(iosb
.Information
== 6, "expected 6, got %lu\n", iosb
.Information
);
965 ok(memcmp(buf
, "barbar", 6) == 0, "wrong file contents: %s\n", buf
);
971 static void nt_mailslot_test(void)
974 ACCESS_MASK DesiredAccess
;
975 OBJECT_ATTRIBUTES attr
;
979 ULONG MaxMessageSize
;
980 LARGE_INTEGER TimeOut
;
981 IO_STATUS_BLOCK IoStatusBlock
;
984 WCHAR buffer1
[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
985 'R',':','\\','F','R','E','D','\0' };
987 TimeOut
.QuadPart
= -1;
989 pRtlInitUnicodeString(&str
, buffer1
);
990 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
991 CreateOptions
= MailslotQuota
= MaxMessageSize
= 0;
992 DesiredAccess
= GENERIC_READ
;
995 * Check for NULL pointer handling
997 rc
= pNtCreateMailslotFile(NULL
, DesiredAccess
,
998 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
1000 ok( rc
== STATUS_ACCESS_VIOLATION
||
1001 rc
== STATUS_INVALID_PARAMETER
, /* win2k3 */
1002 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc
);
1005 * Test to see if the Timeout can be NULL
1007 hslot
= (HANDLE
)0xdeadbeef;
1008 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
1009 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
1011 ok( rc
== STATUS_SUCCESS
||
1012 rc
== STATUS_INVALID_PARAMETER
, /* win2k3 */
1013 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc
);
1014 ok( hslot
!= 0, "Handle is invalid\n");
1016 if ( rc
== STATUS_SUCCESS
) pNtClose(hslot
);
1019 * Test that the length field is checked properly
1022 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
1023 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
1025 todo_wine
ok( rc
== STATUS_INVALID_PARAMETER
, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc
);
1027 if (rc
== STATUS_SUCCESS
) pNtClose(hslot
);
1029 attr
.Length
= sizeof(OBJECT_ATTRIBUTES
)+1;
1030 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
1031 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
1033 todo_wine
ok( rc
== STATUS_INVALID_PARAMETER
, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc
);
1035 if (rc
== STATUS_SUCCESS
) pNtClose(hslot
);
1038 * Test handling of a NULL unicode string in ObjectName
1040 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1041 attr
.ObjectName
= NULL
;
1042 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
1043 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
1045 ok( rc
== STATUS_OBJECT_PATH_SYNTAX_BAD
||
1046 rc
== STATUS_INVALID_PARAMETER
,
1047 "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc
);
1049 if (rc
== STATUS_SUCCESS
) pNtClose(hslot
);
1054 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1055 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
1056 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
1058 ok( rc
== STATUS_SUCCESS
, "Create MailslotFile failed rc = %x\n", rc
);
1059 ok( hslot
!= 0, "Handle is invalid\n");
1061 rc
= pNtClose(hslot
);
1062 ok( rc
== STATUS_SUCCESS
, "NtClose failed\n");
1065 static void test_iocp_setcompletion(HANDLE h
)
1071 if (sizeof(size
) > 4) size
|= (ULONGLONG
)0x12345678 << 32;
1073 res
= pNtSetIoCompletion( h
, CKEY_FIRST
, CVALUE_FIRST
, STATUS_INVALID_DEVICE_REQUEST
, size
);
1074 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %x\n", res
);
1076 count
= get_pending_msgs(h
);
1077 ok( count
== 1, "Unexpected msg count: %d\n", count
);
1081 ok( completionKey
== CKEY_FIRST
, "Invalid completion key: %lx\n", completionKey
);
1082 ok( ioSb
.Information
== size
, "Invalid ioSb.Information: %lu\n", ioSb
.Information
);
1083 ok( U(ioSb
).Status
== STATUS_INVALID_DEVICE_REQUEST
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1084 ok( completionValue
== CVALUE_FIRST
, "Invalid completion value: %lx\n", completionValue
);
1087 count
= get_pending_msgs(h
);
1088 ok( !count
, "Unexpected msg count: %d\n", count
);
1091 static void test_iocp_fileio(HANDLE h
)
1093 static const char pipe_name
[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1095 IO_STATUS_BLOCK iosb
;
1096 FILE_COMPLETION_INFORMATION fci
= {h
, CKEY_SECOND
};
1097 HANDLE hPipeSrv
, hPipeClt
;
1100 hPipeSrv
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
, 4, 1024, 1024, 1000, NULL
);
1101 ok( hPipeSrv
!= INVALID_HANDLE_VALUE
, "Cannot create named pipe\n" );
1102 if (hPipeSrv
!= INVALID_HANDLE_VALUE
)
1104 hPipeClt
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1105 ok( hPipeClt
!= INVALID_HANDLE_VALUE
, "Cannot connect to pipe\n" );
1106 if (hPipeClt
!= INVALID_HANDLE_VALUE
)
1108 U(iosb
).Status
= 0xdeadbeef;
1109 res
= pNtSetInformationFile( hPipeSrv
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1110 ok( res
== STATUS_INVALID_PARAMETER
, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res
);
1111 ok( U(iosb
).Status
== STATUS_INVALID_PARAMETER
/* 98 */ || U(iosb
).Status
== 0xdeadbeef /* NT4+ */,
1112 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb
).Status
);
1113 CloseHandle(hPipeClt
);
1115 CloseHandle( hPipeSrv
);
1118 hPipeSrv
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
, 4, 1024, 1024, 1000, NULL
);
1119 ok( hPipeSrv
!= INVALID_HANDLE_VALUE
, "Cannot create named pipe\n" );
1120 if (hPipeSrv
== INVALID_HANDLE_VALUE
)
1123 hPipeClt
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1124 ok( hPipeClt
!= INVALID_HANDLE_VALUE
, "Cannot connect to pipe\n" );
1125 if (hPipeClt
!= INVALID_HANDLE_VALUE
)
1127 OVERLAPPED o
= {0,};
1128 BYTE send_buf
[TEST_BUF_LEN
], recv_buf
[TEST_BUF_LEN
];
1132 U(iosb
).Status
= 0xdeadbeef;
1133 res
= pNtSetInformationFile( hPipeSrv
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1134 ok( res
== STATUS_SUCCESS
, "NtSetInformationFile failed: %x\n", res
);
1135 ok( U(iosb
).Status
== STATUS_SUCCESS
, "iosb.Status invalid: %x\n", U(iosb
).Status
);
1137 memset( send_buf
, 0, TEST_BUF_LEN
);
1138 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1139 count
= get_pending_msgs(h
);
1140 ok( !count
, "Unexpected msg count: %ld\n", count
);
1141 ReadFile( hPipeSrv
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1142 count
= get_pending_msgs(h
);
1143 ok( !count
, "Unexpected msg count: %ld\n", count
);
1144 WriteFile( hPipeClt
, send_buf
, TEST_BUF_LEN
, &read
, NULL
);
1148 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1149 ok( ioSb
.Information
== 3, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1150 ok( U(ioSb
).Status
== STATUS_SUCCESS
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1151 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1152 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] );
1154 count
= get_pending_msgs(h
);
1155 ok( !count
, "Unexpected msg count: %ld\n", count
);
1157 memset( send_buf
, 0, TEST_BUF_LEN
);
1158 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1159 WriteFile( hPipeClt
, send_buf
, 2, &read
, NULL
);
1160 count
= get_pending_msgs(h
);
1161 ok( !count
, "Unexpected msg count: %ld\n", count
);
1162 ReadFile( hPipeSrv
, recv_buf
, 2, &read
, &o
);
1163 count
= get_pending_msgs(h
);
1164 ok( count
== 1, "Unexpected msg count: %ld\n", count
);
1167 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1168 ok( ioSb
.Information
== 2, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1169 ok( U(ioSb
).Status
== STATUS_SUCCESS
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1170 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1171 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] );
1174 ReadFile( hPipeSrv
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1175 CloseHandle( hPipeSrv
);
1176 count
= get_pending_msgs(h
);
1177 ok( count
== 1, "Unexpected msg count: %ld\n", count
);
1180 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1181 ok( ioSb
.Information
== 0, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1182 /* wine sends wrong status here */
1183 todo_wine
ok( U(ioSb
).Status
== STATUS_PIPE_BROKEN
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1184 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1188 CloseHandle( hPipeClt
);
1190 /* test associating a completion port with a handle after an async is queued */
1191 hPipeSrv
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
, 4, 1024, 1024, 1000, NULL
);
1192 ok( hPipeSrv
!= INVALID_HANDLE_VALUE
, "Cannot create named pipe\n" );
1193 if (hPipeSrv
== INVALID_HANDLE_VALUE
)
1195 hPipeClt
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1196 ok( hPipeClt
!= INVALID_HANDLE_VALUE
, "Cannot connect to pipe\n" );
1197 if (hPipeClt
!= INVALID_HANDLE_VALUE
)
1199 OVERLAPPED o
= {0,};
1200 BYTE send_buf
[TEST_BUF_LEN
], recv_buf
[TEST_BUF_LEN
];
1204 memset( send_buf
, 0, TEST_BUF_LEN
);
1205 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1206 count
= get_pending_msgs(h
);
1207 ok( !count
, "Unexpected msg count: %ld\n", count
);
1208 ReadFile( hPipeSrv
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1210 U(iosb
).Status
= 0xdeadbeef;
1211 res
= pNtSetInformationFile( hPipeSrv
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1212 ok( res
== STATUS_SUCCESS
, "NtSetInformationFile failed: %x\n", res
);
1213 ok( U(iosb
).Status
== STATUS_SUCCESS
, "iosb.Status invalid: %x\n", U(iosb
).Status
);
1214 count
= get_pending_msgs(h
);
1215 ok( !count
, "Unexpected msg count: %ld\n", count
);
1217 WriteFile( hPipeClt
, send_buf
, TEST_BUF_LEN
, &read
, NULL
);
1221 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1222 ok( ioSb
.Information
== 3, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1223 ok( U(ioSb
).Status
== STATUS_SUCCESS
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1224 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1225 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] );
1227 count
= get_pending_msgs(h
);
1228 ok( !count
, "Unexpected msg count: %ld\n", count
);
1231 CloseHandle( hPipeSrv
);
1232 CloseHandle( hPipeClt
);
1235 static void test_file_basic_information(void)
1238 FILE_BASIC_INFORMATION fbi
;
1241 int attrib_mask
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_NORMAL
;
1243 if (!(h
= create_temp_file(0))) return;
1245 /* Check default first */
1246 memset(&fbi
, 0, sizeof(fbi
));
1247 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1248 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1249 ok ( (fbi
.FileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) == FILE_ATTRIBUTE_ARCHIVE
,
1250 "attribute %x not expected\n", fbi
.FileAttributes
);
1253 /* Clear fbi to avoid setting times */
1254 memset(&fbi
, 0, sizeof(fbi
));
1255 fbi
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
1256 U(io
).Status
= 0xdeadbeef;
1257 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1258 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, NtSetInformationFile returned %x\n", res
);
1259 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status is %x\n", U(io
).Status
);
1261 memset(&fbi
, 0, sizeof(fbi
));
1262 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1263 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1264 ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_SYSTEM
, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fbi
.FileAttributes
);
1267 memset(&fbi
, 0, sizeof(fbi
));
1268 fbi
.FileAttributes
= FILE_ATTRIBUTE_HIDDEN
;
1269 U(io
).Status
= 0xdeadbeef;
1270 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1271 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, NtSetInformationFile returned %x\n", res
);
1272 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status is %x\n", U(io
).Status
);
1274 memset(&fbi
, 0, sizeof(fbi
));
1275 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1276 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1277 ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_HIDDEN
, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fbi
.FileAttributes
);
1279 /* Check NORMAL last of all (to make sure we can clear attributes) */
1280 memset(&fbi
, 0, sizeof(fbi
));
1281 fbi
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
1282 U(io
).Status
= 0xdeadbeef;
1283 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1284 ok ( res
== STATUS_SUCCESS
, "can't set normal attribute, NtSetInformationFile returned %x\n", res
);
1285 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set normal attribute, io.Status is %x\n", U(io
).Status
);
1287 memset(&fbi
, 0, sizeof(fbi
));
1288 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1289 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1290 todo_wine
ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_NORMAL
, "attribute %x not 0\n", fbi
.FileAttributes
);
1295 static void test_file_all_information(void)
1298 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1299 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1300 * don't leave enough room there.
1303 FILE_ALL_INFORMATION fai
;
1308 int attrib_mask
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_NORMAL
;
1310 if (!(h
= create_temp_file(0))) return;
1312 /* Check default first */
1313 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1314 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1315 ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) == FILE_ATTRIBUTE_ARCHIVE
,
1316 "attribute %x not expected\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1319 /* Clear fbi to avoid setting times */
1320 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1321 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
1322 U(io
).Status
= 0xdeadbeef;
1323 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1324 ok ( res
== STATUS_INVALID_INFO_CLASS
|| broken(res
== STATUS_NOT_IMPLEMENTED
), "shouldn't be able to set FileAllInformation, res %x\n", res
);
1325 todo_wine
ok ( U(io
).Status
== 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io
).Status
);
1326 U(io
).Status
= 0xdeadbeef;
1327 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1328 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1329 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %x\n", U(io
).Status
);
1331 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1332 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1333 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1334 ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_SYSTEM
, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1337 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1338 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_HIDDEN
;
1339 U(io
).Status
= 0xdeadbeef;
1340 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1341 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1342 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %x\n", U(io
).Status
);
1344 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1345 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1346 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1347 ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_HIDDEN
, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1349 /* Check NORMAL last of all (to make sure we can clear attributes) */
1350 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1351 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
1352 U(io
).Status
= 0xdeadbeef;
1353 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1354 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1355 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %x\n", U(io
).Status
);
1357 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1358 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1359 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1360 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
);
1365 static void test_file_both_information(void)
1368 FILE_BOTH_DIR_INFORMATION fbi
;
1372 if (!(h
= create_temp_file(0))) return;
1374 memset(&fbi
, 0, sizeof(fbi
));
1375 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBothDirectoryInformation
);
1376 ok ( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_NOT_IMPLEMENTED
, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res
);
1381 static void test_file_disposition_information(void)
1383 char tmp_path
[MAX_PATH
], buffer
[MAX_PATH
+ 16];
1385 HANDLE handle
, handle2
;
1388 FILE_DISPOSITION_INFORMATION fdi
;
1391 GetTempPathA( MAX_PATH
, tmp_path
);
1393 /* cannot set disposition on file not opened with delete access */
1394 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1395 handle
= CreateFileA(buffer
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
1396 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1397 res
= pNtQueryInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1398 ok( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_NOT_IMPLEMENTED
, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res
);
1399 fdi
.DoDeleteFile
= TRUE
;
1400 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1401 ok( res
== STATUS_ACCESS_DENIED
, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res
);
1402 CloseHandle( handle
);
1403 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1404 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
1405 DeleteFileA( buffer
);
1407 /* can set disposition on file opened with proper access */
1408 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1409 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
1410 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1411 fdi
.DoDeleteFile
= TRUE
;
1412 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1413 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res
);
1414 CloseHandle( handle
);
1415 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1416 ok( fileDeleted
, "File should have been deleted\n" );
1417 DeleteFileA( buffer
);
1419 /* cannot set disposition on readonly file */
1420 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1421 DeleteFileA( buffer
);
1422 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0);
1423 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1424 fdi
.DoDeleteFile
= TRUE
;
1425 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1426 ok( res
== STATUS_CANNOT_DELETE
, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res
);
1427 CloseHandle( handle
);
1428 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1429 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
1430 SetFileAttributesA( buffer
, FILE_ATTRIBUTE_NORMAL
);
1431 DeleteFileA( buffer
);
1433 /* cannot set disposition on readonly file */
1434 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1435 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0);
1436 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1437 fdi
.DoDeleteFile
= TRUE
;
1438 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1440 ok( res
== STATUS_CANNOT_DELETE
, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res
);
1441 CloseHandle( handle
);
1442 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1444 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
1445 SetFileAttributesA( buffer
, FILE_ATTRIBUTE_NORMAL
);
1446 DeleteFileA( buffer
);
1448 /* cannot set disposition on readonly file */
1449 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1450 DeleteFileA( buffer
);
1451 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0);
1452 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1453 fdi
.DoDeleteFile
= TRUE
;
1454 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1455 ok( res
== STATUS_CANNOT_DELETE
, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res
);
1456 CloseHandle( handle
);
1457 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1458 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
1459 SetFileAttributesA( buffer
, FILE_ATTRIBUTE_NORMAL
);
1460 DeleteFileA( buffer
);
1462 /* can set disposition on file and then reset it */
1463 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1464 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
1465 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1466 fdi
.DoDeleteFile
= TRUE
;
1467 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1468 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res
);
1469 fdi
.DoDeleteFile
= FALSE
;
1470 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1471 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res
);
1472 CloseHandle( handle
);
1473 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1474 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
1475 DeleteFileA( buffer
);
1477 /* Delete-on-close flag doesn't change file disposition until a handle is closed */
1478 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1479 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0);
1480 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1481 fdi
.DoDeleteFile
= FALSE
;
1482 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1483 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res
);
1484 CloseHandle( handle
);
1485 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1486 ok( fileDeleted
, "File should have been deleted\n" );
1487 DeleteFileA( buffer
);
1489 /* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
1490 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1491 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0);
1492 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
1493 ok( DuplicateHandle( GetCurrentProcess(), handle
, GetCurrentProcess(), &handle2
, 0, FALSE
, DUPLICATE_SAME_ACCESS
), "DuplicateHandle failed\n" );
1494 CloseHandle( handle
);
1495 fdi
.DoDeleteFile
= FALSE
;
1496 res
= pNtSetInformationFile( handle2
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1497 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res
);
1498 CloseHandle( handle2
);
1499 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1500 ok( fileDeleted
, "File should have been deleted\n" );
1501 DeleteFileA( buffer
);
1503 /* can set disposition on a directory opened with proper access */
1504 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1505 DeleteFileA( buffer
);
1506 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
1507 handle
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
1508 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
1509 fdi
.DoDeleteFile
= TRUE
;
1510 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1511 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res
);
1512 CloseHandle( handle
);
1513 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1514 ok( fileDeleted
, "Directory should have been deleted\n" );
1515 RemoveDirectoryA( buffer
);
1517 /* RemoveDirectory sets directory disposition and it can be undone */
1518 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1519 DeleteFileA( buffer
);
1520 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
1521 handle
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
1522 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
1523 RemoveDirectoryA( buffer
);
1524 fdi
.DoDeleteFile
= FALSE
;
1525 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1526 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res
);
1527 CloseHandle( handle
);
1528 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1529 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
1530 RemoveDirectoryA( buffer
);
1532 /* cannot set disposition on a non-empty directory */
1533 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
1534 DeleteFileA( buffer
);
1535 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
1536 handle
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
1537 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
1538 dirpos
= lstrlenA( buffer
);
1539 lstrcpyA( buffer
+ dirpos
, "\\tst" );
1540 handle2
= CreateFileA(buffer
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
1541 CloseHandle( handle2
);
1542 fdi
.DoDeleteFile
= TRUE
;
1543 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
1545 ok( res
== STATUS_DIRECTORY_NOT_EMPTY
, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res
);
1546 DeleteFileA( buffer
);
1547 buffer
[dirpos
] = '\0';
1548 CloseHandle( handle
);
1549 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1551 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
1552 RemoveDirectoryA( buffer
);
1555 static void test_iocompletion(void)
1557 HANDLE h
= INVALID_HANDLE_VALUE
;
1560 res
= pNtCreateIoCompletion( &h
, IO_COMPLETION_ALL_ACCESS
, NULL
, 0);
1562 ok( res
== 0, "NtCreateIoCompletion anonymous failed: %x\n", res
);
1563 ok( h
&& h
!= INVALID_HANDLE_VALUE
, "Invalid handle returned\n" );
1565 if ( h
&& h
!= INVALID_HANDLE_VALUE
)
1567 test_iocp_setcompletion(h
);
1568 test_iocp_fileio(h
);
1573 static void test_file_name_information(void)
1575 WCHAR
*file_name
, *volume_prefix
, *expected
;
1576 FILE_NAME_INFORMATION
*info
;
1577 ULONG old_redir
= 1, tmp
;
1578 UINT file_name_size
;
1585 /* GetVolumePathName is not present before w2k */
1586 if (!pGetVolumePathNameW
) {
1587 win_skip("GetVolumePathNameW not found\n");
1591 file_name_size
= GetSystemDirectoryW( NULL
, 0 );
1592 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1593 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1594 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1596 len
= GetSystemDirectoryW( file_name
, file_name_size
);
1597 ok(len
== file_name_size
- 1,
1598 "GetSystemDirectoryW returned %u, expected %u.\n",
1599 len
, file_name_size
- 1);
1601 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1602 ok(len
, "GetVolumePathNameW failed.\n");
1604 len
= lstrlenW( volume_prefix
);
1605 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1606 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1607 expected
[file_name_size
- len
- 1] = '\0';
1609 /* A bit more than we actually need, but it keeps the calculation simple. */
1610 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1611 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1613 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( TRUE
, &old_redir
);
1614 h
= CreateFileW( file_name
, GENERIC_READ
,
1615 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1616 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1617 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( old_redir
, &tmp
);
1618 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1620 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
) - 1, FileNameInformation
);
1621 ok(hr
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile returned %#x.\n", hr
);
1623 memset( info
, 0xcc, info_size
);
1624 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
), FileNameInformation
);
1625 ok(hr
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile returned %#x, expected %#x.\n",
1626 hr
, STATUS_BUFFER_OVERFLOW
);
1627 ok(U(io
).Status
== STATUS_BUFFER_OVERFLOW
, "io.Status is %#x, expected %#x.\n",
1628 U(io
).Status
, STATUS_BUFFER_OVERFLOW
);
1629 ok(info
->FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
), "info->FileNameLength is %u\n", info
->FileNameLength
);
1630 ok(info
->FileName
[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info
->FileName
[2]);
1631 ok(CharLowerW((LPWSTR
)(UINT_PTR
)info
->FileName
[1]) == CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]),
1632 "info->FileName[1] is %p, expected %p.\n",
1633 CharLowerW((LPWSTR
)(UINT_PTR
)info
->FileName
[1]), CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]));
1634 ok(io
.Information
== sizeof(*info
), "io.Information is %lu\n", io
.Information
);
1636 memset( info
, 0xcc, info_size
);
1637 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileNameInformation
);
1638 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1639 ok(U(io
).Status
== STATUS_SUCCESS
, "io.Status is %#x, expected %#x.\n", U(io
).Status
, STATUS_SUCCESS
);
1640 ok(info
->FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
), "info->FileNameLength is %u\n", info
->FileNameLength
);
1641 ok(info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
1642 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)]);
1643 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = '\0';
1644 ok(!lstrcmpiW( info
->FileName
, expected
), "info->FileName is %s, expected %s.\n",
1645 wine_dbgstr_w( info
->FileName
), wine_dbgstr_w( expected
));
1646 ok(io
.Information
== FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + info
->FileNameLength
,
1647 "io.Information is %lu, expected %u.\n",
1648 io
.Information
, FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + info
->FileNameLength
);
1651 HeapFree( GetProcessHeap(), 0, info
);
1652 HeapFree( GetProcessHeap(), 0, expected
);
1653 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1655 if (old_redir
|| !pGetSystemWow64DirectoryW
|| !(file_name_size
= pGetSystemWow64DirectoryW( NULL
, 0 )))
1657 skip("Not running on WoW64, skipping test.\n");
1658 HeapFree( GetProcessHeap(), 0, file_name
);
1662 h
= CreateFileW( file_name
, GENERIC_READ
,
1663 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1664 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1665 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1666 HeapFree( GetProcessHeap(), 0, file_name
);
1668 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1669 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1670 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*expected
) );
1672 len
= pGetSystemWow64DirectoryW( file_name
, file_name_size
);
1673 ok(len
== file_name_size
- 1,
1674 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1675 len
, file_name_size
- 1);
1677 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1678 ok(len
, "GetVolumePathNameW failed.\n");
1680 len
= lstrlenW( volume_prefix
);
1681 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1682 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1683 expected
[file_name_size
- len
- 1] = '\0';
1685 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1686 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1688 memset( info
, 0xcc, info_size
);
1689 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileNameInformation
);
1690 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1691 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = '\0';
1692 ok(!lstrcmpiW( info
->FileName
, expected
), "info->FileName is %s, expected %s.\n",
1693 wine_dbgstr_w( info
->FileName
), wine_dbgstr_w( expected
));
1696 HeapFree( GetProcessHeap(), 0, info
);
1697 HeapFree( GetProcessHeap(), 0, expected
);
1698 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1699 HeapFree( GetProcessHeap(), 0, file_name
);
1702 static void test_file_all_name_information(void)
1704 WCHAR
*file_name
, *volume_prefix
, *expected
;
1705 FILE_ALL_INFORMATION
*info
;
1706 ULONG old_redir
= 1, tmp
;
1707 UINT file_name_size
;
1714 /* GetVolumePathName is not present before w2k */
1715 if (!pGetVolumePathNameW
) {
1716 win_skip("GetVolumePathNameW not found\n");
1720 file_name_size
= GetSystemDirectoryW( NULL
, 0 );
1721 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1722 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1723 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1725 len
= GetSystemDirectoryW( file_name
, file_name_size
);
1726 ok(len
== file_name_size
- 1,
1727 "GetSystemDirectoryW returned %u, expected %u.\n",
1728 len
, file_name_size
- 1);
1730 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1731 ok(len
, "GetVolumePathNameW failed.\n");
1733 len
= lstrlenW( volume_prefix
);
1734 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1735 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1736 expected
[file_name_size
- len
- 1] = '\0';
1738 /* A bit more than we actually need, but it keeps the calculation simple. */
1739 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1740 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1742 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( TRUE
, &old_redir
);
1743 h
= CreateFileW( file_name
, GENERIC_READ
,
1744 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1745 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1746 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( old_redir
, &tmp
);
1747 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1749 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
) - 1, FileAllInformation
);
1750 ok(hr
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile returned %#x, expected %#x.\n",
1751 hr
, STATUS_INFO_LENGTH_MISMATCH
);
1753 memset( info
, 0xcc, info_size
);
1754 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
), FileAllInformation
);
1755 ok(hr
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile returned %#x, expected %#x.\n",
1756 hr
, STATUS_BUFFER_OVERFLOW
);
1757 ok(U(io
).Status
== STATUS_BUFFER_OVERFLOW
, "io.Status is %#x, expected %#x.\n",
1758 U(io
).Status
, STATUS_BUFFER_OVERFLOW
);
1759 ok(info
->NameInformation
.FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
),
1760 "info->NameInformation.FileNameLength is %u\n", info
->NameInformation
.FileNameLength
);
1761 ok(info
->NameInformation
.FileName
[2] == 0xcccc,
1762 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info
->NameInformation
.FileName
[2]);
1763 ok(CharLowerW((LPWSTR
)(UINT_PTR
)info
->NameInformation
.FileName
[1]) == CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]),
1764 "info->NameInformation.FileName[1] is %p, expected %p.\n",
1765 CharLowerW((LPWSTR
)(UINT_PTR
)info
->NameInformation
.FileName
[1]), CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]));
1766 ok(io
.Information
== sizeof(*info
), "io.Information is %lu\n", io
.Information
);
1768 memset( info
, 0xcc, info_size
);
1769 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileAllInformation
);
1770 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1771 ok(U(io
).Status
== STATUS_SUCCESS
, "io.Status is %#x, expected %#x.\n", U(io
).Status
, STATUS_SUCCESS
);
1772 ok(info
->NameInformation
.FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
),
1773 "info->NameInformation.FileNameLength is %u\n", info
->NameInformation
.FileNameLength
);
1774 ok(info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] == 0xcccc,
1775 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
1776 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)]);
1777 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] = '\0';
1778 ok(!lstrcmpiW( info
->NameInformation
.FileName
, expected
),
1779 "info->NameInformation.FileName is %s, expected %s.\n",
1780 wine_dbgstr_w( info
->NameInformation
.FileName
), wine_dbgstr_w( expected
));
1781 ok(io
.Information
== FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
)
1782 + info
->NameInformation
.FileNameLength
,
1783 "io.Information is %lu\n", io
.Information
);
1786 HeapFree( GetProcessHeap(), 0, info
);
1787 HeapFree( GetProcessHeap(), 0, expected
);
1788 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1790 if (old_redir
|| !pGetSystemWow64DirectoryW
|| !(file_name_size
= pGetSystemWow64DirectoryW( NULL
, 0 )))
1792 skip("Not running on WoW64, skipping test.\n");
1793 HeapFree( GetProcessHeap(), 0, file_name
);
1797 h
= CreateFileW( file_name
, GENERIC_READ
,
1798 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1799 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1800 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1801 HeapFree( GetProcessHeap(), 0, file_name
);
1803 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1804 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1805 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*expected
) );
1807 len
= pGetSystemWow64DirectoryW( file_name
, file_name_size
);
1808 ok(len
== file_name_size
- 1,
1809 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1810 len
, file_name_size
- 1);
1812 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1813 ok(len
, "GetVolumePathNameW failed.\n");
1815 len
= lstrlenW( volume_prefix
);
1816 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1817 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1818 expected
[file_name_size
- len
- 1] = '\0';
1820 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1821 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1823 memset( info
, 0xcc, info_size
);
1824 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileAllInformation
);
1825 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1826 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] = '\0';
1827 ok(!lstrcmpiW( info
->NameInformation
.FileName
, expected
), "info->NameInformation.FileName is %s, expected %s.\n",
1828 wine_dbgstr_w( info
->NameInformation
.FileName
), wine_dbgstr_w( expected
));
1831 HeapFree( GetProcessHeap(), 0, info
);
1832 HeapFree( GetProcessHeap(), 0, expected
);
1833 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1834 HeapFree( GetProcessHeap(), 0, file_name
);
1837 static void test_query_volume_information_file(void)
1841 WCHAR path
[MAX_PATH
];
1842 OBJECT_ATTRIBUTES attr
;
1844 UNICODE_STRING nameW
;
1845 FILE_FS_VOLUME_INFORMATION
*ffvi
;
1846 BYTE buf
[sizeof(FILE_FS_VOLUME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
1848 GetWindowsDirectoryW( path
, MAX_PATH
);
1849 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
1850 attr
.Length
= sizeof(attr
);
1851 attr
.RootDirectory
= 0;
1852 attr
.ObjectName
= &nameW
;
1853 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1854 attr
.SecurityDescriptor
= NULL
;
1855 attr
.SecurityQualityOfService
= NULL
;
1857 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
1858 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
1859 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
1860 pRtlFreeUnicodeString( &nameW
);
1862 ZeroMemory( buf
, sizeof(buf
) );
1863 U(io
).Status
= 0xdadadada;
1864 io
.Information
= 0xcacacaca;
1866 status
= pNtQueryVolumeInformationFile( dir
, &io
, buf
, sizeof(buf
), FileFsVolumeInformation
);
1868 ffvi
= (FILE_FS_VOLUME_INFORMATION
*)buf
;
1872 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %d\n", status
);
1873 ok(U(io
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %d\n", U(io
).Status
);
1875 ok(io
.Information
== (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + ffvi
->VolumeLabelLength
),
1876 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + ffvi
->VolumeLabelLength
),
1879 ok(ffvi
->VolumeCreationTime
.QuadPart
!= 0, "Missing VolumeCreationTime\n");
1880 ok(ffvi
->VolumeSerialNumber
!= 0, "Missing VolumeSerialNumber\n");
1881 ok(ffvi
->SupportsObjects
== 1,"expected 1, got %d\n", ffvi
->SupportsObjects
);
1883 ok(ffvi
->VolumeLabelLength
== lstrlenW(ffvi
->VolumeLabel
) * sizeof(WCHAR
), "got %d\n", ffvi
->VolumeLabelLength
);
1885 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi
->VolumeSerialNumber
, wine_dbgstr_w(ffvi
->VolumeLabel
));
1890 static void test_query_attribute_information_file(void)
1894 WCHAR path
[MAX_PATH
];
1895 OBJECT_ATTRIBUTES attr
;
1897 UNICODE_STRING nameW
;
1898 FILE_FS_ATTRIBUTE_INFORMATION
*ffai
;
1899 BYTE buf
[sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
1901 GetWindowsDirectoryW( path
, MAX_PATH
);
1902 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
1903 attr
.Length
= sizeof(attr
);
1904 attr
.RootDirectory
= 0;
1905 attr
.ObjectName
= &nameW
;
1906 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1907 attr
.SecurityDescriptor
= NULL
;
1908 attr
.SecurityQualityOfService
= NULL
;
1910 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
1911 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
1912 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
1913 pRtlFreeUnicodeString( &nameW
);
1915 ZeroMemory( buf
, sizeof(buf
) );
1916 U(io
).Status
= 0xdadadada;
1917 io
.Information
= 0xcacacaca;
1919 status
= pNtQueryVolumeInformationFile( dir
, &io
, buf
, sizeof(buf
), FileFsAttributeInformation
);
1921 ffai
= (FILE_FS_ATTRIBUTE_INFORMATION
*)buf
;
1923 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %d\n", status
);
1924 ok(U(io
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %d\n", U(io
).Status
);
1925 ok(ffai
->FileSystemAttribute
!= 0, "Missing FileSystemAttribute\n");
1926 ok(ffai
->MaximumComponentNameLength
!= 0, "Missing MaximumComponentNameLength\n");
1927 ok(ffai
->FileSystemNameLength
!= 0, "Missing FileSystemNameLength\n");
1929 trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
1930 ffai
->FileSystemAttribute
, ffai
->MaximumComponentNameLength
,
1931 wine_dbgstr_wn(ffai
->FileSystemName
, ffai
->FileSystemNameLength
/ sizeof(WCHAR
)));
1936 static void test_NtCreateFile(void)
1938 static const struct test_data
1940 DWORD disposition
, attrib_in
, status
, result
, attrib_out
, needs_cleanup
;
1943 /* 0*/{ FILE_CREATE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1944 /* 1*/{ FILE_CREATE
, 0, STATUS_OBJECT_NAME_COLLISION
, 0, 0, TRUE
},
1945 /* 2*/{ FILE_CREATE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1946 /* 3*/{ FILE_OPEN
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
},
1947 /* 4*/{ FILE_OPEN
, FILE_ATTRIBUTE_READONLY
, STATUS_OBJECT_NAME_NOT_FOUND
, 0, 0, FALSE
},
1948 /* 5*/{ FILE_OPEN_IF
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1949 /* 6*/{ FILE_OPEN_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
},
1950 /* 7*/{ FILE_OPEN_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1951 /* 8*/{ FILE_OPEN_IF
, 0, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1952 /* 9*/{ FILE_OVERWRITE
, 0, STATUS_ACCESS_DENIED
, 0, 0, TRUE
},
1953 /*10*/{ FILE_OVERWRITE
, 0, STATUS_OBJECT_NAME_NOT_FOUND
, 0, 0, FALSE
},
1954 /*11*/{ FILE_CREATE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1955 /*12*/{ FILE_OVERWRITE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OVERWRITTEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1956 /*13*/{ FILE_OVERWRITE_IF
, 0, STATUS_ACCESS_DENIED
, 0, 0, TRUE
},
1957 /*14*/{ FILE_OVERWRITE_IF
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1958 /*15*/{ FILE_OVERWRITE_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OVERWRITTEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1959 /*16*/{ FILE_SUPERSEDE
, 0, 0, FILE_SUPERSEDED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1960 /*17*/{ FILE_SUPERSEDE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_SUPERSEDED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, TRUE
},
1961 /*18*/{ FILE_SUPERSEDE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
}
1963 static const WCHAR fooW
[] = {'f','o','o',0};
1966 WCHAR path
[MAX_PATH
];
1967 OBJECT_ATTRIBUTES attr
;
1969 UNICODE_STRING nameW
;
1972 GetTempPathW(MAX_PATH
, path
);
1973 GetTempFileNameW(path
, fooW
, 0, path
);
1975 pRtlDosPathNameToNtPathName_U(path
, &nameW
, NULL
, NULL
);
1977 attr
.Length
= sizeof(attr
);
1978 attr
.RootDirectory
= NULL
;
1979 attr
.ObjectName
= &nameW
;
1980 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1981 attr
.SecurityDescriptor
= NULL
;
1982 attr
.SecurityQualityOfService
= NULL
;
1984 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
1986 status
= pNtCreateFile(&handle
, GENERIC_READ
, &attr
, &io
, NULL
,
1987 td
[i
].attrib_in
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1988 td
[i
].disposition
, 0, NULL
, 0);
1990 ok(status
== td
[i
].status
, "%d: expected %#x got %#x\n", i
, td
[i
].status
, status
);
1994 ok(io
.Information
== td
[i
].result
,"%d: expected %#x got %#lx\n", i
, td
[i
].result
, io
.Information
);
1996 ret
= GetFileAttributesW(path
);
1997 ret
&= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
;
1998 /* FIXME: leave only 'else' case below once Wine is fixed */
1999 if (ret
!= td
[i
].attrib_out
)
2002 ok(ret
== td
[i
].attrib_out
, "%d: expected %#x got %#x\n", i
, td
[i
].attrib_out
, ret
);
2003 SetFileAttributesW(path
, td
[i
].attrib_out
);
2006 ok(ret
== td
[i
].attrib_out
, "%d: expected %#x got %#x\n", i
, td
[i
].attrib_out
, ret
);
2008 CloseHandle(handle
);
2011 if (td
[i
].needs_cleanup
)
2013 SetFileAttributesW(path
, FILE_ATTRIBUTE_ARCHIVE
);
2018 pRtlFreeUnicodeString( &nameW
);
2019 SetFileAttributesW(path
, FILE_ATTRIBUTE_ARCHIVE
);
2020 DeleteFileW( path
);
2023 static void test_read_write(void)
2025 static const char contents
[14] = "1234567890abcd";
2029 IO_STATUS_BLOCK iob
;
2030 DWORD ret
, bytes
, status
, off
;
2031 LARGE_INTEGER offset
;
2035 iob
.Information
= -1;
2036 offset
.QuadPart
= 0;
2037 status
= pNtReadFile(INVALID_HANDLE_VALUE
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2038 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
|| status
== STATUS_INVALID_HANDLE
, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status
);
2039 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2040 ok(iob
.Information
== -1, "expected -1, got %lu\n", iob
.Information
);
2043 iob
.Information
= -1;
2044 offset
.QuadPart
= 0;
2045 status
= pNtWriteFile(INVALID_HANDLE_VALUE
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2046 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
|| status
== STATUS_INVALID_HANDLE
, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status
);
2047 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2048 ok(iob
.Information
== -1, "expected -1, got %lu\n", iob
.Information
);
2050 hfile
= create_temp_file(0);
2054 iob
.Information
= -1;
2055 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, NULL
, sizeof(contents
), NULL
, NULL
);
2056 ok(status
== STATUS_INVALID_USER_BUFFER
, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status
);
2057 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2058 ok(iob
.Information
== -1, "expected -1, got %lu\n", iob
.Information
);
2061 iob
.Information
= -1;
2062 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, NULL
, sizeof(contents
), NULL
, NULL
);
2063 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, 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
);
2068 iob
.Information
= -1;
2069 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, 7, NULL
, NULL
);
2070 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
2071 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2072 ok(iob
.Information
== 7, "expected 7, got %lu\n", iob
.Information
);
2074 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
2077 iob
.Information
= -1;
2078 offset
.QuadPart
= (LONGLONG
)-1 /* FILE_WRITE_TO_END_OF_FILE */;
2079 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
+ 7, sizeof(contents
) - 7, &offset
, NULL
);
2080 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
2081 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2082 ok(iob
.Information
== sizeof(contents
) - 7, "expected sizeof(contents)-7, got %lu\n", iob
.Information
);
2084 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2085 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2088 SetLastError(0xdeadbeef);
2089 ret
= ReadFile(INVALID_HANDLE_VALUE
, buf
, 0, &bytes
, NULL
);
2090 ok(!ret
, "ReadFile should fail\n");
2091 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2092 ok(bytes
== 0, "bytes %u\n", bytes
);
2095 SetLastError(0xdeadbeef);
2096 ret
= ReadFile(hfile
, buf
, 0, &bytes
, NULL
);
2097 ok(ret
, "ReadFile error %d\n", GetLastError());
2098 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2099 ok(bytes
== 0, "bytes %u\n", bytes
);
2102 SetLastError(0xdeadbeef);
2103 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
2104 ok(ret
, "ReadFile error %d\n", GetLastError());
2105 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2106 ok(bytes
== 0, "bytes %u\n", bytes
);
2108 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
2111 SetLastError(0xdeadbeef);
2112 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
2113 ok(ret
, "ReadFile error %d\n", GetLastError());
2114 ok(bytes
== sizeof(contents
), "bytes %u\n", bytes
);
2115 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
2117 for (i
= -20; i
< -1; i
++)
2119 if (i
== -2) continue;
2122 iob
.Information
= -1;
2123 offset
.QuadPart
= (LONGLONG
)i
;
2124 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), &offset
, NULL
);
2125 ok(status
== STATUS_INVALID_PARAMETER
, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i
, status
);
2126 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2127 ok(iob
.Information
== -1, "expected -1, got %ld\n", iob
.Information
);
2130 SetFilePointer(hfile
, sizeof(contents
) - 4, NULL
, FILE_BEGIN
);
2133 iob
.Information
= -1;
2134 offset
.QuadPart
= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2135 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, "DCBA", 4, &offset
, NULL
);
2136 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
2137 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2138 ok(iob
.Information
== 4, "expected 4, got %lu\n", iob
.Information
);
2140 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2141 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2144 iob
.Information
= -1;
2145 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), NULL
, NULL
);
2146 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", status
);
2147 ok(U(iob
).Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", U(iob
).Status
);
2148 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2150 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
2153 SetLastError(0xdeadbeef);
2154 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
2155 ok(ret
, "ReadFile error %d\n", GetLastError());
2156 ok(bytes
== sizeof(contents
), "bytes %u\n", bytes
);
2157 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
2158 ok(!memcmp(buf
+ sizeof(contents
) - 4, "DCBA", 4), "file contents mismatch\n");
2160 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2161 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2163 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
2166 SetLastError(0xdeadbeef);
2167 ret
= WriteFile(hfile
, contents
, sizeof(contents
), &bytes
, NULL
);
2168 ok(ret
, "WriteFile error %d\n", GetLastError());
2169 ok(bytes
== sizeof(contents
), "bytes %u\n", bytes
);
2171 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2172 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2174 /* test reading beyond EOF */
2176 SetLastError(0xdeadbeef);
2177 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
2178 ok(ret
, "ReadFile error %d\n", GetLastError());
2179 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2180 ok(bytes
== 0, "bytes %u\n", bytes
);
2183 SetLastError(0xdeadbeef);
2184 ret
= ReadFile(hfile
, buf
, 0, &bytes
, NULL
);
2185 ok(ret
, "ReadFile error %d\n", GetLastError());
2186 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2187 ok(bytes
== 0, "bytes %u\n", bytes
);
2190 SetLastError(0xdeadbeef);
2191 ret
= ReadFile(hfile
, NULL
, 0, &bytes
, NULL
);
2192 ok(ret
, "ReadFile error %d\n", GetLastError());
2193 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2194 ok(bytes
== 0, "bytes %u\n", bytes
);
2196 S(U(ovl
)).Offset
= sizeof(contents
);
2197 S(U(ovl
)).OffsetHigh
= 0;
2199 ovl
.InternalHigh
= -1;
2202 SetLastError(0xdeadbeef);
2203 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
2204 ok(!ret
, "ReadFile should fail\n");
2205 ok(GetLastError() == ERROR_HANDLE_EOF
, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
2206 ok(bytes
== 0, "bytes %u\n", bytes
);
2207 ok((NTSTATUS
)ovl
.Internal
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", ovl
.Internal
);
2208 ok(ovl
.InternalHigh
== 0, "expected 0, got %lu\n", ovl
.InternalHigh
);
2210 S(U(ovl
)).Offset
= sizeof(contents
);
2211 S(U(ovl
)).OffsetHigh
= 0;
2213 ovl
.InternalHigh
= -1;
2216 SetLastError(0xdeadbeef);
2217 ret
= ReadFile(hfile
, buf
, 0, &bytes
, &ovl
);
2218 ok(ret
, "ReadFile error %d\n", GetLastError());
2219 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2220 ok(bytes
== 0, "bytes %u\n", bytes
);
2221 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2222 ok(ovl
.InternalHigh
== 0, "expected 0, got %lu\n", ovl
.InternalHigh
);
2225 iob
.Information
= -1;
2226 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), NULL
, NULL
);
2227 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", status
);
2228 ok(U(iob
).Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", U(iob
).Status
);
2229 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2232 iob
.Information
= -1;
2233 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, NULL
, NULL
);
2234 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#x\n", status
);
2235 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2236 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2239 iob
.Information
= -1;
2240 offset
.QuadPart
= sizeof(contents
);
2241 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2242 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", status
);
2243 ok(U(iob
).Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", U(iob
).Status
);
2244 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2247 iob
.Information
= -1;
2248 offset
.QuadPart
= sizeof(contents
);
2249 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, &offset
, NULL
);
2250 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#x\n", status
);
2251 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2252 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2255 iob
.Information
= -1;
2256 offset
.QuadPart
= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2257 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2258 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", status
);
2259 ok(U(iob
).Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", U(iob
).Status
);
2260 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2263 iob
.Information
= -1;
2264 offset
.QuadPart
= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2265 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, &offset
, NULL
);
2266 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#x\n", status
);
2267 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2268 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2270 for (i
= -20; i
< 0; i
++)
2272 if (i
== -2) continue;
2275 iob
.Information
= -1;
2276 offset
.QuadPart
= (LONGLONG
)i
;
2277 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2278 ok(status
== STATUS_INVALID_PARAMETER
, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i
, status
);
2279 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2280 ok(iob
.Information
== -1, "expected -1, got %ld\n", iob
.Information
);
2283 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
2286 SetLastError(0xdeadbeef);
2287 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
2288 ok(ret
, "ReadFile error %d\n", GetLastError());
2289 ok(bytes
== sizeof(contents
), "bytes %u\n", bytes
);
2290 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
2292 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2293 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2296 iob
.Information
= -1;
2297 offset
.QuadPart
= 0;
2298 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2299 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#x\n", status
);
2300 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2301 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %lu\n", iob
.Information
);
2302 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
2304 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2305 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2308 iob
.Information
= -1;
2309 offset
.QuadPart
= sizeof(contents
) - 4;
2310 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, "DCBA", 4, &offset
, NULL
);
2311 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#x\n", status
);
2312 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2313 ok(iob
.Information
== 4, "expected 4, got %lu\n", iob
.Information
);
2315 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2316 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2319 iob
.Information
= -1;
2320 offset
.QuadPart
= 0;
2321 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2322 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#x\n", status
);
2323 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2324 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %lu\n", iob
.Information
);
2325 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
2326 ok(!memcmp(buf
+ sizeof(contents
) - 4, "DCBA", 4), "file contents mismatch\n");
2328 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2329 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2331 S(U(ovl
)).Offset
= sizeof(contents
) - 4;
2332 S(U(ovl
)).OffsetHigh
= 0;
2335 SetLastError(0xdeadbeef);
2336 ret
= WriteFile(hfile
, "ABCD", 4, &bytes
, &ovl
);
2337 ok(ret
, "WriteFile error %d\n", GetLastError());
2338 ok(bytes
== 4, "bytes %u\n", bytes
);
2340 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2341 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2343 S(U(ovl
)).Offset
= 0;
2344 S(U(ovl
)).OffsetHigh
= 0;
2346 ovl
.InternalHigh
= -1;
2349 SetLastError(0xdeadbeef);
2350 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
2351 ok(ret
, "ReadFile error %d\n", GetLastError());
2352 ok(bytes
== sizeof(contents
), "bytes %u\n", bytes
);
2353 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2354 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %lu\n", ovl
.InternalHigh
);
2355 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
2356 ok(!memcmp(buf
+ sizeof(contents
) - 4, "ABCD", 4), "file contents mismatch\n");
2358 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2359 ok(off
== sizeof(contents
), "expected sizeof(contents), got %u\n", off
);
2363 hfile
= create_temp_file(FILE_FLAG_OVERLAPPED
);
2367 SetLastError(0xdeadbeef);
2368 ret
= ReadFile(INVALID_HANDLE_VALUE
, buf
, 0, &bytes
, NULL
);
2369 ok(!ret
, "ReadFile should fail\n");
2370 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2371 ok(bytes
== 0, "bytes %u\n", bytes
);
2373 S(U(ovl
)).Offset
= 0;
2374 S(U(ovl
)).OffsetHigh
= 0;
2376 ovl
.InternalHigh
= -1;
2379 SetLastError(0xdeadbeef);
2380 /* ReadFile return value depends on Windows version and testing it is not practical */
2381 ReadFile(hfile
, buf
, 0, &bytes
, &ovl
);
2382 ok(bytes
== 0, "bytes %u\n", bytes
);
2383 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2384 ok(ovl
.InternalHigh
== 0, "expected 0, got %lu\n", ovl
.InternalHigh
);
2387 SetLastError(0xdeadbeef);
2388 ret
= WriteFile(hfile
, contents
, sizeof(contents
), &bytes
, NULL
);
2389 ok(!ret
, "WriteFile should fail\n");
2390 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2391 ok(bytes
== 0, "bytes %u\n", bytes
);
2394 iob
.Information
= -1;
2395 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), NULL
, NULL
);
2396 ok(status
== STATUS_INVALID_PARAMETER
, "expected STATUS_INVALID_PARAMETER, got %#x\n", status
);
2397 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2398 ok(iob
.Information
== -1, "expected -1, got %ld\n", iob
.Information
);
2400 for (i
= -20; i
< -1; i
++)
2403 iob
.Information
= -1;
2404 offset
.QuadPart
= (LONGLONG
)i
;
2405 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), &offset
, NULL
);
2406 ok(status
== STATUS_INVALID_PARAMETER
, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i
, status
);
2407 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2408 ok(iob
.Information
== -1, "expected -1, got %ld\n", iob
.Information
);
2412 iob
.Information
= -1;
2413 offset
.QuadPart
= 0;
2414 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), &offset
, NULL
);
2415 ok(status
== STATUS_PENDING
|| status
== STATUS_SUCCESS
/* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status
);
2416 if (status
== STATUS_PENDING
)
2418 ret
= WaitForSingleObject(hfile
, 3000);
2419 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %d\n", ret
);
2421 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2422 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %lu\n", iob
.Information
);
2424 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2425 ok(off
== 0, "expected 0, got %u\n", off
);
2428 SetLastError(0xdeadbeef);
2429 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
2430 ok(!ret
, "ReadFile should fail\n");
2431 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2432 ok(bytes
== 0, "bytes %u\n", bytes
);
2435 iob
.Information
= -1;
2436 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), NULL
, NULL
);
2437 ok(status
== STATUS_INVALID_PARAMETER
, "expected STATUS_INVALID_PARAMETER, got %#x\n", status
);
2438 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2439 ok(iob
.Information
== -1, "expected -1, got %ld\n", iob
.Information
);
2441 for (i
= -20; i
< 0; i
++)
2444 iob
.Information
= -1;
2445 offset
.QuadPart
= (LONGLONG
)i
;
2446 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2447 ok(status
== STATUS_INVALID_PARAMETER
, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i
, status
);
2448 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2449 ok(iob
.Information
== -1, "expected -1, got %ld\n", iob
.Information
);
2452 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2453 ok(off
== 0, "expected 0, got %u\n", off
);
2455 /* test reading beyond EOF */
2456 offset
.QuadPart
= sizeof(contents
);
2457 S(U(ovl
)).Offset
= offset
.u
.LowPart
;
2458 S(U(ovl
)).OffsetHigh
= offset
.u
.HighPart
;
2460 ovl
.InternalHigh
= -1;
2463 SetLastError(0xdeadbeef);
2464 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
2465 ok(!ret
, "ReadFile should fail\n");
2466 ret
= GetLastError();
2467 ok(ret
== ERROR_IO_PENDING
|| ret
== ERROR_HANDLE_EOF
/* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret
);
2468 ok(bytes
== 0, "bytes %u\n", bytes
);
2470 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2471 ok(off
== 0, "expected 0, got %u\n", off
);
2473 if (ret
== ERROR_IO_PENDING
)
2476 SetLastError(0xdeadbeef);
2477 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
2478 ok(!ret
, "GetOverlappedResult should report FALSE\n");
2479 ok(GetLastError() == ERROR_HANDLE_EOF
, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
2480 ok(bytes
== 0, "expected 0, read %u\n", bytes
);
2481 ok((NTSTATUS
)ovl
.Internal
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", ovl
.Internal
);
2482 ok(ovl
.InternalHigh
== 0, "expected 0, got %lu\n", ovl
.InternalHigh
);
2485 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2486 ok(off
== 0, "expected 0, got %u\n", off
);
2488 offset
.QuadPart
= sizeof(contents
);
2489 S(U(ovl
)).Offset
= offset
.u
.LowPart
;
2490 S(U(ovl
)).OffsetHigh
= offset
.u
.HighPart
;
2492 ovl
.InternalHigh
= -1;
2495 SetLastError(0xdeadbeef);
2496 ret
= ReadFile(hfile
, buf
, 0, &bytes
, &ovl
);
2497 /* ReadFile return value depends on Windows version and testing it is not practical */
2500 ok(GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2501 ret
= GetLastError();
2502 ok(bytes
== 0, "bytes %u\n", bytes
);
2504 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2505 ok(off
== 0, "expected 0, got %u\n", off
);
2507 if (ret
== ERROR_IO_PENDING
)
2510 SetLastError(0xdeadbeef);
2511 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
2512 ok(ret
, "GetOverlappedResult should report TRUE\n");
2513 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2514 ok(bytes
== 0, "expected 0, read %u\n", bytes
);
2515 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2516 ok(ovl
.InternalHigh
== 0, "expected 0, got %lu\n", ovl
.InternalHigh
);
2519 offset
.QuadPart
= sizeof(contents
);
2520 S(U(ovl
)).Offset
= offset
.u
.LowPart
;
2521 S(U(ovl
)).OffsetHigh
= offset
.u
.HighPart
;
2523 ovl
.InternalHigh
= -1;
2526 SetLastError(0xdeadbeef);
2527 ret
= ReadFile(hfile
, NULL
, 0, &bytes
, &ovl
);
2528 /* ReadFile return value depends on Windows version and testing it is not practical */
2531 ok(GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2532 ret
= GetLastError();
2533 ok(bytes
== 0, "bytes %u\n", bytes
);
2535 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2536 ok(off
== 0, "expected 0, got %u\n", off
);
2538 if (ret
== ERROR_IO_PENDING
)
2541 SetLastError(0xdeadbeef);
2542 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
2543 ok(ret
, "GetOverlappedResult should report TRUE\n");
2544 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2545 ok(bytes
== 0, "expected 0, read %u\n", bytes
);
2546 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2547 ok(ovl
.InternalHigh
== 0, "expected 0, got %lu\n", ovl
.InternalHigh
);
2551 iob
.Information
= -1;
2552 offset
.QuadPart
= sizeof(contents
);
2553 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2554 if (status
== STATUS_PENDING
)
2556 ret
= WaitForSingleObject(hfile
, 3000);
2557 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %d\n", ret
);
2558 ok(U(iob
).Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", U(iob
).Status
);
2559 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2563 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#x\n", status
);
2564 ok(U(iob
).Status
== -1, "expected -1, got %#x\n", U(iob
).Status
);
2565 ok(iob
.Information
== -1, "expected -1, got %lu\n", iob
.Information
);
2568 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2569 ok(off
== 0, "expected 0, got %u\n", off
);
2572 iob
.Information
= -1;
2573 offset
.QuadPart
= sizeof(contents
);
2574 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, &offset
, NULL
);
2575 if (status
== STATUS_PENDING
)
2577 ret
= WaitForSingleObject(hfile
, 3000);
2578 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %d\n", ret
);
2579 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2580 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2584 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", status
);
2585 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2586 ok(iob
.Information
== 0, "expected 0, got %lu\n", iob
.Information
);
2589 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2590 ok(off
== 0, "expected 0, got %u\n", off
);
2592 S(U(ovl
)).Offset
= 0;
2593 S(U(ovl
)).OffsetHigh
= 0;
2595 ovl
.InternalHigh
= -1;
2598 SetLastError(0xdeadbeef);
2599 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
2600 /* ReadFile return value depends on Windows version and testing it is not practical */
2603 ok(GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2604 ok(bytes
== 0, "bytes %u\n", bytes
);
2606 else ok(bytes
== 14, "bytes %u\n", bytes
);
2607 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2608 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %lu\n", ovl
.InternalHigh
);
2610 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2611 ok(off
== 0, "expected 0, got %u\n", off
);
2614 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
2615 ok(ret
, "GetOverlappedResult error %d\n", GetLastError());
2616 ok(bytes
== sizeof(contents
), "bytes %u\n", bytes
);
2617 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2618 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %lu\n", ovl
.InternalHigh
);
2619 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
2621 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2622 ok(off
== 0, "expected 0, got %u\n", off
);
2624 SetFilePointer(hfile
, sizeof(contents
) - 4, NULL
, FILE_BEGIN
);
2625 SetEndOfFile(hfile
);
2626 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
2629 iob
.Information
= -1;
2630 offset
.QuadPart
= (LONGLONG
)-1 /* FILE_WRITE_TO_END_OF_FILE */;
2631 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, "DCBA", 4, &offset
, NULL
);
2632 ok(status
== STATUS_PENDING
|| status
== STATUS_SUCCESS
/* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status
);
2633 if (status
== STATUS_PENDING
)
2635 ret
= WaitForSingleObject(hfile
, 3000);
2636 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %d\n", ret
);
2638 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2639 ok(iob
.Information
== 4, "expected 4, got %lu\n", iob
.Information
);
2641 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2642 ok(off
== 0, "expected 0, got %u\n", off
);
2645 iob
.Information
= -1;
2646 offset
.QuadPart
= 0;
2647 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
2648 ok(status
== STATUS_PENDING
|| status
== STATUS_SUCCESS
, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status
);
2649 if (status
== STATUS_PENDING
)
2651 ret
= WaitForSingleObject(hfile
, 3000);
2652 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %d\n", ret
);
2654 ok(U(iob
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#x\n", U(iob
).Status
);
2655 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %lu\n", iob
.Information
);
2657 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2658 ok(off
== 0, "expected 0, got %u\n", off
);
2660 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
2661 ok(!memcmp(buf
+ sizeof(contents
) - 4, "DCBA", 4), "file contents mismatch\n");
2663 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2664 ok(off
== 0, "expected 0, got %u\n", off
);
2666 S(U(ovl
)).Offset
= sizeof(contents
) - 4;
2667 S(U(ovl
)).OffsetHigh
= 0;
2669 ovl
.InternalHigh
= -1;
2672 SetLastError(0xdeadbeef);
2673 ret
= WriteFile(hfile
, "ABCD", 4, &bytes
, &ovl
);
2674 /* WriteFile return value depends on Windows version and testing it is not practical */
2677 ok(GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2678 ok(bytes
== 0, "bytes %u\n", bytes
);
2680 else ok(bytes
== 4, "bytes %u\n", bytes
);
2681 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2682 ok(ovl
.InternalHigh
== 4, "expected 4, got %lu\n", ovl
.InternalHigh
);
2684 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2685 ok(off
== 0, "expected 0, got %u\n", off
);
2688 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
2689 ok(ret
, "GetOverlappedResult error %d\n", GetLastError());
2690 ok(bytes
== 4, "bytes %u\n", bytes
);
2691 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2692 ok(ovl
.InternalHigh
== 4, "expected 4, got %lu\n", ovl
.InternalHigh
);
2694 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2695 ok(off
== 0, "expected 0, got %u\n", off
);
2697 S(U(ovl
)).Offset
= 0;
2698 S(U(ovl
)).OffsetHigh
= 0;
2700 ovl
.InternalHigh
= -1;
2703 SetLastError(0xdeadbeef);
2704 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
2705 /* ReadFile return value depends on Windows version and testing it is not practical */
2708 ok(GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2709 ok(bytes
== 0, "bytes %u\n", bytes
);
2711 else ok(bytes
== 14, "bytes %u\n", bytes
);
2712 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2713 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %lu\n", ovl
.InternalHigh
);
2715 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2716 ok(off
== 0, "expected 0, got %u\n", off
);
2719 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
2720 ok(ret
, "GetOverlappedResult error %d\n", GetLastError());
2721 ok(bytes
== sizeof(contents
), "bytes %u\n", bytes
);
2722 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", ovl
.Internal
);
2723 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %lu\n", ovl
.InternalHigh
);
2724 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
2725 ok(!memcmp(buf
+ sizeof(contents
) - 4, "ABCD", 4), "file contents mismatch\n");
2727 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
2728 ok(off
== 0, "expected 0, got %u\n", off
);
2733 static INT
build_reparse_buffer(WCHAR
*filename
, REPARSE_DATA_BUFFER
**pbuffer
)
2735 REPARSE_DATA_BUFFER
*buffer
;
2736 INT buffer_len
, string_len
;
2739 string_len
= (lstrlenW(filename
)+1)*sizeof(WCHAR
);
2740 buffer_len
= FIELD_OFFSET(REPARSE_DATA_BUFFER
, MountPointReparseBuffer
.PathBuffer
[1]) + string_len
;
2741 buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buffer_len
);
2742 buffer
->ReparseTag
= IO_REPARSE_TAG_MOUNT_POINT
;
2743 buffer
->ReparseDataLength
= sizeof(buffer
->MountPointReparseBuffer
) + string_len
;
2744 buffer
->MountPointReparseBuffer
.SubstituteNameLength
= string_len
- sizeof(WCHAR
);
2745 buffer
->MountPointReparseBuffer
.PrintNameOffset
= string_len
;
2746 dest
= &buffer
->MountPointReparseBuffer
.PathBuffer
[0];
2747 memcpy(dest
, filename
, string_len
);
2752 static void test_junction_points(void)
2754 static const WCHAR junctionW
[] = {'\\','j','u','n','c','t','i','o','n',0};
2755 WCHAR path
[MAX_PATH
], junction_path
[MAX_PATH
], target_path
[MAX_PATH
];
2756 static const WCHAR targetW
[] = {'\\','t','a','r','g','e','t',0};
2757 FILE_BASIC_INFORMATION old_attrib
, new_attrib
;
2758 static const WCHAR fooW
[] = {'f','o','o',0};
2759 static WCHAR volW
[] = {'c',':','\\',0};
2760 REPARSE_GUID_DATA_BUFFER guid_buffer
;
2761 static const WCHAR dotW
[] = {'.',0};
2762 REPARSE_DATA_BUFFER
*buffer
= NULL
;
2763 DWORD dwret
, dwLen
, dwFlags
, err
;
2764 INT buffer_len
, string_len
;
2765 IO_STATUS_BLOCK iosb
;
2766 UNICODE_STRING nameW
;
2771 /* Create a temporary folder for the junction point tests */
2772 GetTempFileNameW(dotW
, fooW
, 0, path
);
2774 if (!CreateDirectoryW(path
, NULL
))
2776 win_skip("Unable to create a temporary junction point directory.\n");
2780 /* Check that the volume this folder is located on supports junction points */
2781 pRtlDosPathNameToNtPathName_U(path
, &nameW
, NULL
, NULL
);
2782 volW
[0] = nameW
.Buffer
[4];
2783 pRtlFreeUnicodeString( &nameW
);
2784 GetVolumeInformationW(volW
, 0, 0, 0, &dwLen
, &dwFlags
, 0, 0);
2785 if (!(dwFlags
& FILE_SUPPORTS_REPARSE_POINTS
))
2787 skip("File system does not support junction points.\n");
2788 RemoveDirectoryW(path
);
2792 /* Create the folder to be replaced by a junction point */
2793 lstrcpyW(junction_path
, path
);
2794 lstrcatW(junction_path
, junctionW
);
2795 bret
= CreateDirectoryW(junction_path
, NULL
);
2796 ok(bret
, "Failed to create junction point directory.\n");
2798 /* Create a destination folder for the junction point to target */
2799 lstrcpyW(target_path
, path
);
2800 lstrcatW(target_path
, targetW
);
2801 bret
= CreateDirectoryW(target_path
, NULL
);
2802 ok(bret
, "Failed to create junction point target directory.\n");
2803 pRtlDosPathNameToNtPathName_U(target_path
, &nameW
, NULL
, NULL
);
2805 /* Create the junction point */
2806 hJunction
= CreateFileW(junction_path
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
,
2807 FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OPEN_REPARSE_POINT
, 0);
2808 if (hJunction
== INVALID_HANDLE_VALUE
)
2810 win_skip("Failed to open junction point directory handle (0x%x).\n", GetLastError());
2813 dwret
= NtQueryInformationFile(hJunction
, &iosb
, &old_attrib
, sizeof(old_attrib
), FileBasicInformation
);
2814 ok(dwret
== STATUS_SUCCESS
, "Failed to get junction point folder's attributes (0x%x).\n", dwret
);
2815 buffer_len
= build_reparse_buffer(nameW
.Buffer
, &buffer
);
2816 bret
= DeviceIoControl(hJunction
, FSCTL_SET_REPARSE_POINT
, (LPVOID
)buffer
, buffer_len
, NULL
, 0, &dwret
, 0);
2817 ok(bret
, "Failed to create junction point! (0x%x)\n", GetLastError());
2819 /* Check the file attributes of the junction point */
2820 dwret
= GetFileAttributesW(junction_path
);
2821 ok(dwret
!= (DWORD
)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret
);
2822 ok(dwret
& FILE_ATTRIBUTE_REPARSE_POINT
, "File is not a junction point! (attributes: %d)\n", dwret
);
2824 /* Read back the junction point */
2825 HeapFree(GetProcessHeap(), 0, buffer
);
2826 buffer_len
= sizeof(*buffer
) + MAX_PATH
*sizeof(WCHAR
);
2827 buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buffer_len
);
2828 bret
= DeviceIoControl(hJunction
, FSCTL_GET_REPARSE_POINT
, NULL
, 0, (LPVOID
)buffer
, buffer_len
, &dwret
, 0);
2829 string_len
= buffer
->MountPointReparseBuffer
.SubstituteNameLength
;
2830 dest
= &buffer
->MountPointReparseBuffer
.PathBuffer
[buffer
->MountPointReparseBuffer
.SubstituteNameOffset
/sizeof(WCHAR
)];
2831 ok(bret
, "Failed to read junction point!\n");
2832 ok((memcmp(dest
, nameW
.Buffer
, string_len
) == 0), "Junction point destination does not match ('%s' != '%s')!\n",
2833 wine_dbgstr_w(dest
), wine_dbgstr_w(nameW
.Buffer
));
2835 /* Delete the junction point */
2836 memset(&old_attrib
, 0x00, sizeof(old_attrib
));
2837 old_attrib
.LastAccessTime
.QuadPart
= 0x200deadcafebeef;
2838 dwret
= NtSetInformationFile(hJunction
, &iosb
, &old_attrib
, sizeof(old_attrib
), FileBasicInformation
);
2839 ok(dwret
== STATUS_SUCCESS
, "Failed to set junction point folder's attributes (0x%x).\n", dwret
);
2840 memset(&guid_buffer
, 0x00, sizeof(guid_buffer
));
2841 guid_buffer
.ReparseTag
= IO_REPARSE_TAG_MOUNT_POINT
;
2842 bret
= DeviceIoControl(hJunction
, FSCTL_DELETE_REPARSE_POINT
, (LPVOID
)&guid_buffer
,
2843 REPARSE_GUID_DATA_BUFFER_HEADER_SIZE
, NULL
, 0, &dwret
, 0);
2844 ok(bret
, "Failed to delete junction point! (0x%x)\n", GetLastError());
2845 memset(&new_attrib
, 0x00, sizeof(new_attrib
));
2846 dwret
= NtQueryInformationFile(hJunction
, &iosb
, &new_attrib
, sizeof(new_attrib
), FileBasicInformation
);
2847 ok(dwret
== STATUS_SUCCESS
, "Failed to get junction point folder's attributes (0x%x).\n", dwret
);
2848 ok(old_attrib
.LastAccessTime
.QuadPart
== new_attrib
.LastAccessTime
.QuadPart
,
2849 "Junction point folder's access time does not match (0x%llx != 0x%llx).\n",
2850 new_attrib
.LastAccessTime
.QuadPart
, old_attrib
.LastAccessTime
.QuadPart
);
2851 CloseHandle(hJunction
);
2853 /* Check deleting a junction point as if it were a directory */
2854 HeapFree(GetProcessHeap(), 0, buffer
);
2855 hJunction
= CreateFileW(junction_path
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
,
2856 FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OPEN_REPARSE_POINT
, 0);
2857 buffer_len
= build_reparse_buffer(nameW
.Buffer
, &buffer
);
2858 bret
= DeviceIoControl(hJunction
, FSCTL_SET_REPARSE_POINT
, (LPVOID
)buffer
, buffer_len
, NULL
, 0, &dwret
, 0);
2859 ok(bret
, "Failed to create junction point! (0x%x)\n", GetLastError());
2860 CloseHandle(hJunction
);
2861 bret
= RemoveDirectoryW(junction_path
);
2862 ok(bret
, "Failed to delete junction point as directory!\n");
2863 dwret
= GetFileAttributesW(junction_path
);
2864 ok(dwret
== (DWORD
)~0, "Junction point still exists (attributes: 0x%x)!\n", dwret
);
2866 /* Check deleting a junction point as if it were a file */
2867 HeapFree(GetProcessHeap(), 0, buffer
);
2868 bret
= CreateDirectoryW(junction_path
, NULL
);
2869 ok(bret
, "Failed to create junction point target directory.\n");
2870 hJunction
= CreateFileW(junction_path
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
,
2871 FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OPEN_REPARSE_POINT
, 0);
2872 buffer_len
= build_reparse_buffer(nameW
.Buffer
, &buffer
);
2873 bret
= DeviceIoControl(hJunction
, FSCTL_SET_REPARSE_POINT
, (LPVOID
)buffer
, buffer_len
, NULL
, 0, &dwret
, 0);
2874 ok(bret
, "Failed to create junction point! (0x%x)\n", GetLastError());
2875 CloseHandle(hJunction
);
2876 bret
= DeleteFileW(junction_path
);
2877 ok(!bret
, "Succeeded in deleting junction point as file!\n");
2878 err
= GetLastError();
2879 ok(err
== ERROR_ACCESS_DENIED
, "Expected last error 0x%x for DeleteFile on junction point (actually 0x%x)!\n",
2880 ERROR_ACCESS_DENIED
, err
);
2881 dwret
= GetFileAttributesW(junction_path
);
2882 ok(dwret
!= (DWORD
)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret
);
2883 ok(dwret
& FILE_ATTRIBUTE_REPARSE_POINT
, "File is not a junction point! (attributes: 0x%x)\n", dwret
);
2885 /* Test deleting a junction point's target */
2886 dwret
= GetFileAttributesW(junction_path
);
2887 ok(dwret
== 0x410 || broken(dwret
== 0x430) /* win2k */,
2888 "Unexpected junction point attributes (0x%x != 0x410)!\n", dwret
);
2889 bret
= RemoveDirectoryW(target_path
);
2890 ok(bret
, "Failed to delete junction point target!\n");
2891 bret
= CreateDirectoryW(target_path
, NULL
);
2892 ok(bret
, "Failed to create junction point target directory.\n");
2896 pRtlFreeUnicodeString( &nameW
);
2897 HeapFree(GetProcessHeap(), 0, buffer
);
2898 bret
= RemoveDirectoryW(junction_path
);
2899 ok(bret
, "Failed to remove temporary junction point directory!\n");
2900 bret
= RemoveDirectoryW(target_path
);
2901 ok(bret
, "Failed to remove temporary target directory!\n");
2902 RemoveDirectoryW(path
);
2907 HMODULE hkernel32
= GetModuleHandleA("kernel32.dll");
2908 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
2911 skip("not running on NT, skipping test\n");
2915 pGetVolumePathNameW
= (void *)GetProcAddress(hkernel32
, "GetVolumePathNameW");
2916 pGetSystemWow64DirectoryW
= (void *)GetProcAddress(hkernel32
, "GetSystemWow64DirectoryW");
2918 pRtlFreeUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlFreeUnicodeString");
2919 pRtlInitUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlInitUnicodeString");
2920 pRtlDosPathNameToNtPathName_U
= (void *)GetProcAddress(hntdll
, "RtlDosPathNameToNtPathName_U");
2921 pRtlWow64EnableFsRedirectionEx
= (void *)GetProcAddress(hntdll
, "RtlWow64EnableFsRedirectionEx");
2922 pNtCreateMailslotFile
= (void *)GetProcAddress(hntdll
, "NtCreateMailslotFile");
2923 pNtCreateFile
= (void *)GetProcAddress(hntdll
, "NtCreateFile");
2924 pNtOpenFile
= (void *)GetProcAddress(hntdll
, "NtOpenFile");
2925 pNtDeleteFile
= (void *)GetProcAddress(hntdll
, "NtDeleteFile");
2926 pNtReadFile
= (void *)GetProcAddress(hntdll
, "NtReadFile");
2927 pNtWriteFile
= (void *)GetProcAddress(hntdll
, "NtWriteFile");
2928 pNtCancelIoFile
= (void *)GetProcAddress(hntdll
, "NtCancelIoFile");
2929 pNtCancelIoFileEx
= (void *)GetProcAddress(hntdll
, "NtCancelIoFileEx");
2930 pNtClose
= (void *)GetProcAddress(hntdll
, "NtClose");
2931 pNtCreateIoCompletion
= (void *)GetProcAddress(hntdll
, "NtCreateIoCompletion");
2932 pNtOpenIoCompletion
= (void *)GetProcAddress(hntdll
, "NtOpenIoCompletion");
2933 pNtQueryIoCompletion
= (void *)GetProcAddress(hntdll
, "NtQueryIoCompletion");
2934 pNtRemoveIoCompletion
= (void *)GetProcAddress(hntdll
, "NtRemoveIoCompletion");
2935 pNtSetIoCompletion
= (void *)GetProcAddress(hntdll
, "NtSetIoCompletion");
2936 pNtSetInformationFile
= (void *)GetProcAddress(hntdll
, "NtSetInformationFile");
2937 pNtQueryInformationFile
= (void *)GetProcAddress(hntdll
, "NtQueryInformationFile");
2938 pNtQueryDirectoryFile
= (void *)GetProcAddress(hntdll
, "NtQueryDirectoryFile");
2939 pNtQueryVolumeInformationFile
= (void *)GetProcAddress(hntdll
, "NtQueryVolumeInformationFile");
2942 test_NtCreateFile();
2949 test_iocompletion();
2950 test_file_basic_information();
2951 test_file_all_information();
2952 test_file_both_information();
2953 test_file_name_information();
2954 test_file_all_name_information();
2955 test_file_disposition_information();
2956 test_query_volume_information_file();
2957 test_query_attribute_information_file();
2958 test_junction_points();