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"
41 #ifndef IO_COMPLETION_ALL_ACCESS
42 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
45 static BOOL (WINAPI
* pGetVolumePathNameW
)(LPCWSTR
, LPWSTR
, DWORD
);
46 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)( LPWSTR
, UINT
);
48 static VOID (WINAPI
*pRtlFreeUnicodeString
)( PUNICODE_STRING
);
49 static VOID (WINAPI
*pRtlInitUnicodeString
)( PUNICODE_STRING
, LPCWSTR
);
50 static BOOL (WINAPI
*pRtlDosPathNameToNtPathName_U
)( LPCWSTR
, PUNICODE_STRING
, PWSTR
*, CURDIR
* );
51 static NTSTATUS (WINAPI
*pRtlWow64EnableFsRedirectionEx
)( ULONG
, ULONG
* );
53 static NTSTATUS (WINAPI
*pNtCreateMailslotFile
)( PHANDLE
, ULONG
, POBJECT_ATTRIBUTES
, PIO_STATUS_BLOCK
,
54 ULONG
, ULONG
, ULONG
, PLARGE_INTEGER
);
55 static NTSTATUS (WINAPI
*pNtCreateFile
)(PHANDLE
,ACCESS_MASK
,POBJECT_ATTRIBUTES
,PIO_STATUS_BLOCK
,PLARGE_INTEGER
,ULONG
,ULONG
,ULONG
,ULONG
,PVOID
,ULONG
);
56 static NTSTATUS (WINAPI
*pNtOpenFile
)(PHANDLE
,ACCESS_MASK
,POBJECT_ATTRIBUTES
,PIO_STATUS_BLOCK
,ULONG
,ULONG
);
57 static NTSTATUS (WINAPI
*pNtDeleteFile
)(POBJECT_ATTRIBUTES ObjectAttributes
);
58 static NTSTATUS (WINAPI
*pNtReadFile
)(HANDLE hFile
, HANDLE hEvent
,
59 PIO_APC_ROUTINE apc
, void* apc_user
,
60 PIO_STATUS_BLOCK io_status
, void* buffer
, ULONG length
,
61 PLARGE_INTEGER offset
, PULONG key
);
62 static NTSTATUS (WINAPI
*pNtWriteFile
)(HANDLE hFile
, HANDLE hEvent
,
63 PIO_APC_ROUTINE apc
, void* apc_user
,
64 PIO_STATUS_BLOCK io_status
,
65 const void* buffer
, ULONG length
,
66 PLARGE_INTEGER offset
, PULONG key
);
67 static NTSTATUS (WINAPI
*pNtCancelIoFile
)(HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
68 static NTSTATUS (WINAPI
*pNtCancelIoFileEx
)(HANDLE hFile
, PIO_STATUS_BLOCK iosb
, PIO_STATUS_BLOCK io_status
);
69 static NTSTATUS (WINAPI
*pNtClose
)( PHANDLE
);
71 static NTSTATUS (WINAPI
*pNtCreateIoCompletion
)(PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
, ULONG
);
72 static NTSTATUS (WINAPI
*pNtOpenIoCompletion
)(PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
);
73 static NTSTATUS (WINAPI
*pNtQueryIoCompletion
)(HANDLE
, IO_COMPLETION_INFORMATION_CLASS
, PVOID
, ULONG
, PULONG
);
74 static NTSTATUS (WINAPI
*pNtRemoveIoCompletion
)(HANDLE
, PULONG_PTR
, PULONG_PTR
, PIO_STATUS_BLOCK
, PLARGE_INTEGER
);
75 static NTSTATUS (WINAPI
*pNtSetIoCompletion
)(HANDLE
, ULONG_PTR
, ULONG_PTR
, NTSTATUS
, ULONG
);
76 static NTSTATUS (WINAPI
*pNtSetInformationFile
)(HANDLE
, PIO_STATUS_BLOCK
, PVOID
, ULONG
, FILE_INFORMATION_CLASS
);
77 static NTSTATUS (WINAPI
*pNtQueryInformationFile
)(HANDLE
, PIO_STATUS_BLOCK
, PVOID
, ULONG
, FILE_INFORMATION_CLASS
);
78 static NTSTATUS (WINAPI
*pNtQueryDirectoryFile
)(HANDLE
,HANDLE
,PIO_APC_ROUTINE
,PVOID
,PIO_STATUS_BLOCK
,
79 PVOID
,ULONG
,FILE_INFORMATION_CLASS
,BOOLEAN
,PUNICODE_STRING
,BOOLEAN
);
80 static NTSTATUS (WINAPI
*pNtQueryVolumeInformationFile
)(HANDLE
,PIO_STATUS_BLOCK
,PVOID
,ULONG
,FS_INFORMATION_CLASS
);
82 static inline BOOL
is_signaled( HANDLE obj
)
84 return WaitForSingleObject( obj
, 0 ) == 0;
87 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
88 #define TEST_BUF_LEN 3
90 static BOOL
create_pipe( HANDLE
*read
, HANDLE
*write
, ULONG flags
, ULONG size
)
92 *read
= CreateNamedPipe(PIPENAME
, PIPE_ACCESS_INBOUND
| flags
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
93 1, size
, size
, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
94 ok(*read
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
96 *write
= CreateFileA(PIPENAME
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
97 ok(*write
!= INVALID_HANDLE_VALUE
, "CreateFile failed (%d)\n", GetLastError());
102 static HANDLE
create_temp_file( ULONG flags
)
104 char buffer
[MAX_PATH
];
107 GetTempFileNameA( ".", "foo", 0, buffer
);
108 handle
= CreateFileA(buffer
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
109 flags
| FILE_FLAG_DELETE_ON_CLOSE
, 0);
110 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
111 return (handle
== INVALID_HANDLE_VALUE
) ? 0 : handle
;
114 #define CVALUE_FIRST 0xfffabbcc
115 #define CKEY_FIRST 0x1030341
116 #define CKEY_SECOND 0x132E46
118 static ULONG_PTR completionKey
;
119 static IO_STATUS_BLOCK ioSb
;
120 static ULONG_PTR completionValue
;
122 static ULONG
get_pending_msgs(HANDLE h
)
127 res
= pNtQueryIoCompletion( h
, IoCompletionBasicInformation
, &a
, sizeof(a
), &req
);
128 ok( res
== STATUS_SUCCESS
, "NtQueryIoCompletion failed: %x\n", res
);
129 if (res
!= STATUS_SUCCESS
) return -1;
130 ok( req
== sizeof(a
), "Unexpected response size: %x\n", req
);
134 static BOOL
get_msg(HANDLE h
)
136 LARGE_INTEGER timeout
= {{-10000000*3}};
137 DWORD res
= pNtRemoveIoCompletion( h
, &completionKey
, &completionValue
, &ioSb
, &timeout
);
138 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletion failed: %x\n", res
);
139 if (res
!= STATUS_SUCCESS
)
141 completionKey
= completionValue
= 0;
142 memset(&ioSb
, 0, sizeof(ioSb
));
149 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
153 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
154 iosb
, U(*iosb
).Status
, iosb
->Information
);
156 ok( !reserved
, "reserved is not 0: %x\n", reserved
);
159 static void create_file_test(void)
161 static const WCHAR systemrootW
[] = {'\\','S','y','s','t','e','m','R','o','o','t',
162 '\\','f','a','i','l','i','n','g',0};
163 static const WCHAR questionmarkInvalidNameW
[] = {'a','f','i','l','e','?',0};
164 static const WCHAR pipeInvalidNameW
[] = {'a','|','b',0};
167 WCHAR path
[MAX_PATH
];
168 OBJECT_ATTRIBUTES attr
;
170 UNICODE_STRING nameW
;
172 GetCurrentDirectoryW( MAX_PATH
, path
);
173 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
174 attr
.Length
= sizeof(attr
);
175 attr
.RootDirectory
= 0;
176 attr
.ObjectName
= &nameW
;
177 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
178 attr
.SecurityDescriptor
= NULL
;
179 attr
.SecurityQualityOfService
= NULL
;
181 /* try various open modes and options on directories */
182 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
183 FILE_OPEN
, FILE_DIRECTORY_FILE
, NULL
, 0 );
184 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
187 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
188 FILE_CREATE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
189 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
190 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
192 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
193 FILE_OPEN_IF
, FILE_DIRECTORY_FILE
, NULL
, 0 );
194 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
197 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
198 FILE_SUPERSEDE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
199 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
201 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
202 FILE_OVERWRITE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
203 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
205 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
206 FILE_OVERWRITE_IF
, FILE_DIRECTORY_FILE
, NULL
, 0 );
207 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
209 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
210 FILE_OPEN
, 0, NULL
, 0 );
211 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
214 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
215 FILE_CREATE
, 0, NULL
, 0 );
216 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
217 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
219 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
220 FILE_OPEN_IF
, 0, NULL
, 0 );
221 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
224 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
225 FILE_SUPERSEDE
, 0, NULL
, 0 );
226 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
227 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
229 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
230 FILE_OVERWRITE
, 0, NULL
, 0 );
231 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
232 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
234 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
235 FILE_OVERWRITE_IF
, 0, NULL
, 0 );
236 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
237 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
239 pRtlFreeUnicodeString( &nameW
);
241 pRtlInitUnicodeString( &nameW
, systemrootW
);
242 attr
.Length
= sizeof(attr
);
243 attr
.RootDirectory
= NULL
;
244 attr
.ObjectName
= &nameW
;
245 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
246 attr
.SecurityDescriptor
= NULL
;
247 attr
.SecurityQualityOfService
= NULL
;
249 status
= pNtCreateFile( &dir
, FILE_APPEND_DATA
, &attr
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0,
250 FILE_OPEN_IF
, FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
252 ok( status
== STATUS_INVALID_PARAMETER
,
253 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
255 /* Invalid chars in file/dirnames */
256 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW
, &nameW
, NULL
, NULL
);
257 attr
.ObjectName
= &nameW
;
258 status
= pNtCreateFile(&dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
259 FILE_SHARE_READ
, FILE_CREATE
,
260 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
261 ok(status
== STATUS_OBJECT_NAME_INVALID
,
262 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
264 status
= pNtCreateFile(&file
, GENERIC_WRITE
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
266 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
267 ok(status
== STATUS_OBJECT_NAME_INVALID
,
268 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
270 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW
, &nameW
, NULL
, NULL
);
271 attr
.ObjectName
= &nameW
;
272 status
= pNtCreateFile(&dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
273 FILE_SHARE_READ
, FILE_CREATE
,
274 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
275 ok(status
== STATUS_OBJECT_NAME_INVALID
,
276 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
278 status
= pNtCreateFile(&file
, GENERIC_WRITE
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
280 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
281 ok(status
== STATUS_OBJECT_NAME_INVALID
,
282 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
285 static void open_file_test(void)
288 HANDLE dir
, root
, handle
;
289 WCHAR path
[MAX_PATH
];
291 OBJECT_ATTRIBUTES attr
;
293 UNICODE_STRING nameW
;
297 len
= GetWindowsDirectoryW( path
, MAX_PATH
);
298 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
299 attr
.Length
= sizeof(attr
);
300 attr
.RootDirectory
= 0;
301 attr
.ObjectName
= &nameW
;
302 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
303 attr
.SecurityDescriptor
= NULL
;
304 attr
.SecurityQualityOfService
= NULL
;
305 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
306 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
307 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
308 pRtlFreeUnicodeString( &nameW
);
310 path
[3] = 0; /* root of the drive */
311 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
312 status
= pNtOpenFile( &root
, GENERIC_READ
, &attr
, &io
,
313 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
314 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
315 pRtlFreeUnicodeString( &nameW
);
317 /* test opening system dir with RootDirectory set to windows dir */
318 GetSystemDirectoryW( path
, MAX_PATH
);
319 while (path
[len
] == '\\') len
++;
320 nameW
.Buffer
= path
+ len
;
321 nameW
.Length
= lstrlenW(path
+ len
) * sizeof(WCHAR
);
322 attr
.RootDirectory
= dir
;
323 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
324 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
325 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
326 CloseHandle( handle
);
328 /* try uppercase name */
329 for (i
= len
; path
[i
]; i
++) if (path
[i
] >= 'a' && path
[i
] <= 'z') path
[i
] -= 'a' - 'A';
330 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
331 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
332 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
333 CloseHandle( handle
);
335 /* try with leading backslash */
337 nameW
.Length
+= sizeof(WCHAR
);
338 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
339 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
340 ok( status
== STATUS_INVALID_PARAMETER
||
341 status
== STATUS_OBJECT_NAME_INVALID
||
342 status
== STATUS_OBJECT_PATH_SYNTAX_BAD
,
343 "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
344 if (!status
) CloseHandle( handle
);
346 /* try with empty name */
348 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
349 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
350 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
351 CloseHandle( handle
);
353 /* try open by file id */
355 while (!pNtQueryDirectoryFile( dir
, NULL
, NULL
, NULL
, &io
, data
, sizeof(data
),
356 FileIdBothDirectoryInformation
, TRUE
, NULL
, restart
))
358 FILE_ID_BOTH_DIRECTORY_INFORMATION
*info
= (FILE_ID_BOTH_DIRECTORY_INFORMATION
*)data
;
362 if (!info
->FileId
.QuadPart
) continue;
364 nameW
.Buffer
= (WCHAR
*)&info
->FileId
;
365 nameW
.Length
= sizeof(info
->FileId
);
366 info
->FileName
[info
->FileNameLength
/sizeof(WCHAR
)] = 0;
367 attr
.RootDirectory
= dir
;
368 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
369 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
371 FILE_OPEN_BY_FILE_ID
|
372 ((info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ? FILE_DIRECTORY_FILE
: 0) );
373 ok( status
== STATUS_SUCCESS
|| status
== STATUS_ACCESS_DENIED
|| status
== STATUS_NOT_IMPLEMENTED
|| status
== STATUS_SHARING_VIOLATION
,
374 "open %s failed %x\n", wine_dbgstr_w(info
->FileName
), status
);
375 if (status
== STATUS_NOT_IMPLEMENTED
)
377 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
380 if (status
== STATUS_SHARING_VIOLATION
)
381 trace( "%s is currently open\n", wine_dbgstr_w(info
->FileName
) );
384 BYTE buf
[sizeof(FILE_ALL_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
386 if (!pNtQueryInformationFile( handle
, &io
, buf
, sizeof(buf
), FileAllInformation
))
388 FILE_ALL_INFORMATION
*fai
= (FILE_ALL_INFORMATION
*)buf
;
390 /* check that it's the same file/directory */
392 /* don't check the size for directories */
393 if (!(info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
394 ok( info
->EndOfFile
.QuadPart
== fai
->StandardInformation
.EndOfFile
.QuadPart
,
395 "mismatched file size for %s\n", wine_dbgstr_w(info
->FileName
));
397 ok( info
->CreationTime
.QuadPart
== fai
->BasicInformation
.CreationTime
.QuadPart
,
398 "mismatched creation time for %s\n", wine_dbgstr_w(info
->FileName
));
400 CloseHandle( handle
);
402 /* try same thing from drive root */
403 attr
.RootDirectory
= root
;
404 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
405 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
406 FILE_OPEN_BY_FILE_ID
|
407 ((info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ? FILE_DIRECTORY_FILE
: 0) );
408 ok( status
== STATUS_SUCCESS
|| status
== STATUS_NOT_IMPLEMENTED
,
409 "open %s failed %x\n", wine_dbgstr_w(info
->FileName
), status
);
410 if (!status
) CloseHandle( handle
);
418 static void delete_file_test(void)
421 OBJECT_ATTRIBUTES attr
;
422 UNICODE_STRING nameW
;
423 WCHAR pathW
[MAX_PATH
];
424 WCHAR pathsubW
[MAX_PATH
];
425 static const WCHAR testdirW
[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
426 static const WCHAR subdirW
[] = {'\\','s','u','b',0};
428 ret
= GetTempPathW(MAX_PATH
, pathW
);
431 ok(0, "couldn't get temp dir\n");
434 if (ret
+ sizeof(testdirW
)/sizeof(WCHAR
)-1 + sizeof(subdirW
)/sizeof(WCHAR
)-1 >= MAX_PATH
)
436 ok(0, "MAX_PATH exceeded in constructing paths\n");
440 lstrcatW(pathW
, testdirW
);
441 lstrcpyW(pathsubW
, pathW
);
442 lstrcatW(pathsubW
, subdirW
);
444 ret
= CreateDirectoryW(pathW
, NULL
);
445 ok(ret
== TRUE
, "couldn't create directory ntdeletefile\n");
446 if (!pRtlDosPathNameToNtPathName_U(pathW
, &nameW
, NULL
, NULL
))
448 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
452 attr
.Length
= sizeof(attr
);
453 attr
.RootDirectory
= 0;
454 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
455 attr
.ObjectName
= &nameW
;
456 attr
.SecurityDescriptor
= NULL
;
457 attr
.SecurityQualityOfService
= NULL
;
459 /* test NtDeleteFile on an empty directory */
460 ret
= pNtDeleteFile(&attr
);
461 ok(ret
== STATUS_SUCCESS
, "NtDeleteFile should succeed in removing an empty directory\n");
462 ret
= RemoveDirectoryW(pathW
);
463 ok(ret
== FALSE
, "expected to fail removing directory, NtDeleteFile should have removed it\n");
465 /* test NtDeleteFile on a non-empty directory */
466 ret
= CreateDirectoryW(pathW
, NULL
);
467 ok(ret
== TRUE
, "couldn't create directory ntdeletefile ?!\n");
468 ret
= CreateDirectoryW(pathsubW
, NULL
);
469 ok(ret
== TRUE
, "couldn't create directory subdir\n");
470 ret
= pNtDeleteFile(&attr
);
471 ok(ret
== STATUS_SUCCESS
, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
472 ret
= RemoveDirectoryW(pathsubW
);
473 ok(ret
== TRUE
, "expected to remove directory ntdeletefile\\sub\n");
474 ret
= RemoveDirectoryW(pathW
);
475 ok(ret
== TRUE
, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
477 pRtlFreeUnicodeString( &nameW
);
480 static void read_file_test(void)
482 const char text
[] = "foobar";
483 HANDLE handle
, read
, write
;
485 IO_STATUS_BLOCK iosb
, iosb2
;
489 LARGE_INTEGER offset
;
490 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
495 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
497 /* try read with no data */
498 U(iosb
).Status
= 0xdeadbabe;
499 iosb
.Information
= 0xdeadbeef;
500 ok( is_signaled( read
), "read handle is not signaled\n" );
501 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
502 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
503 ok( !is_signaled( read
), "read handle is signaled\n" );
504 ok( !is_signaled( event
), "event is signaled\n" );
505 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
506 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
507 ok( !apc_count
, "apc was called\n" );
508 WriteFile( write
, buffer
, 1, &written
, NULL
);
509 /* iosb updated here by async i/o */
510 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
511 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
512 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
513 ok( !is_signaled( read
), "read handle is signaled\n" );
514 ok( is_signaled( event
), "event is not signaled\n" );
515 ok( !apc_count
, "apc was called\n" );
517 SleepEx( 1, FALSE
); /* non-alertable sleep */
518 ok( !apc_count
, "apc was called\n" );
519 SleepEx( 1, TRUE
); /* alertable sleep */
520 ok( apc_count
== 1, "apc not called\n" );
522 /* with no event, the pipe handle itself gets signaled */
524 U(iosb
).Status
= 0xdeadbabe;
525 iosb
.Information
= 0xdeadbeef;
526 ok( !is_signaled( read
), "read handle is not signaled\n" );
527 status
= pNtReadFile( read
, 0, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
528 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
529 ok( !is_signaled( read
), "read handle is signaled\n" );
530 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
531 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
532 ok( !apc_count
, "apc was called\n" );
533 WriteFile( write
, buffer
, 1, &written
, NULL
);
534 /* iosb updated here by async i/o */
535 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
536 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
537 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
538 ok( is_signaled( read
), "read handle is signaled\n" );
539 ok( !apc_count
, "apc was called\n" );
541 SleepEx( 1, FALSE
); /* non-alertable sleep */
542 ok( !apc_count
, "apc was called\n" );
543 SleepEx( 1, TRUE
); /* alertable sleep */
544 ok( apc_count
== 1, "apc not called\n" );
546 /* now read with data ready */
548 U(iosb
).Status
= 0xdeadbabe;
549 iosb
.Information
= 0xdeadbeef;
551 WriteFile( write
, buffer
, 1, &written
, NULL
);
552 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
553 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
554 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
555 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
556 ok( is_signaled( event
), "event is not signaled\n" );
557 ok( !apc_count
, "apc was called\n" );
558 SleepEx( 1, FALSE
); /* non-alertable sleep */
559 ok( !apc_count
, "apc was called\n" );
560 SleepEx( 1, TRUE
); /* alertable sleep */
561 ok( apc_count
== 1, "apc not called\n" );
563 /* try read with no data */
565 U(iosb
).Status
= 0xdeadbabe;
566 iosb
.Information
= 0xdeadbeef;
567 ok( is_signaled( event
), "event is not signaled\n" ); /* check that read resets the event */
568 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
569 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
570 ok( !is_signaled( event
), "event is signaled\n" );
571 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
572 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
573 ok( !apc_count
, "apc was called\n" );
574 WriteFile( write
, buffer
, 1, &written
, NULL
);
575 /* partial read is good enough */
576 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
577 ok( is_signaled( event
), "event is signaled\n" );
578 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
579 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
580 ok( !apc_count
, "apc was called\n" );
581 SleepEx( 1, TRUE
); /* alertable sleep */
582 ok( apc_count
== 1, "apc was not called\n" );
584 /* read from disconnected pipe */
586 U(iosb
).Status
= 0xdeadbabe;
587 iosb
.Information
= 0xdeadbeef;
588 CloseHandle( write
);
589 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
590 ok( status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", status
);
591 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
592 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
593 ok( !is_signaled( event
), "event is signaled\n" );
594 ok( !apc_count
, "apc was called\n" );
595 SleepEx( 1, TRUE
); /* alertable sleep */
596 ok( !apc_count
, "apc was called\n" );
599 /* read from closed handle */
601 U(iosb
).Status
= 0xdeadbabe;
602 iosb
.Information
= 0xdeadbeef;
604 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
605 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
606 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
607 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
608 ok( is_signaled( event
), "event is signaled\n" ); /* not reset on invalid handle */
609 ok( !apc_count
, "apc was called\n" );
610 SleepEx( 1, TRUE
); /* alertable sleep */
611 ok( !apc_count
, "apc was called\n" );
613 /* disconnect while async read is in progress */
614 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
616 U(iosb
).Status
= 0xdeadbabe;
617 iosb
.Information
= 0xdeadbeef;
618 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
619 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
620 ok( !is_signaled( event
), "event is signaled\n" );
621 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
622 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
623 ok( !apc_count
, "apc was called\n" );
624 CloseHandle( write
);
625 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
626 ok( U(iosb
).Status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", U(iosb
).Status
);
627 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
628 ok( is_signaled( event
), "event is signaled\n" );
629 ok( !apc_count
, "apc was called\n" );
630 SleepEx( 1, TRUE
); /* alertable sleep */
631 ok( apc_count
== 1, "apc was not called\n" );
634 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
635 ret
= DuplicateHandle(GetCurrentProcess(), read
, GetCurrentProcess(), &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
636 ok(ret
, "Failed to duplicate handle: %d\n", GetLastError());
639 U(iosb
).Status
= 0xdeadbabe;
640 iosb
.Information
= 0xdeadbeef;
641 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
642 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
643 ok( !is_signaled( event
), "event is signaled\n" );
644 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
645 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
646 ok( !apc_count
, "apc was called\n" );
647 /* Cancel by other handle */
648 status
= pNtCancelIoFile( read
, &iosb2
);
649 ok(status
== STATUS_SUCCESS
, "failed to cancel by different handle: %x\n", status
);
650 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
651 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
652 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
653 ok( is_signaled( event
), "event is signaled\n" );
654 todo_wine
ok( !apc_count
, "apc was called\n" );
655 SleepEx( 1, TRUE
); /* alertable sleep */
656 ok( apc_count
== 1, "apc was not called\n" );
659 U(iosb
).Status
= 0xdeadbabe;
660 iosb
.Information
= 0xdeadbeef;
661 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
662 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
663 ok( !is_signaled( event
), "event is signaled\n" );
664 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
665 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
666 ok( !apc_count
, "apc was called\n" );
667 /* Close queued handle */
669 SleepEx( 1, TRUE
); /* alertable sleep */
670 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
671 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
672 status
= pNtCancelIoFile( read
, &iosb2
);
673 ok(status
== STATUS_INVALID_HANDLE
, "cancelled by closed handle?\n");
674 status
= pNtCancelIoFile( handle
, &iosb2
);
675 ok(status
== STATUS_SUCCESS
, "failed to cancel: %x\n", status
);
676 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
677 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
678 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
679 ok( is_signaled( event
), "event is signaled\n" );
680 todo_wine
ok( !apc_count
, "apc was called\n" );
681 SleepEx( 1, TRUE
); /* alertable sleep */
682 ok( apc_count
== 1, "apc was not called\n" );
683 CloseHandle( handle
);
684 CloseHandle( write
);
686 if (pNtCancelIoFileEx
)
688 /* Basic Cancel Ex */
689 if (!create_pipe( &read
, &write
, FILE_FLAG_OVERLAPPED
, 4096 )) return;
692 U(iosb
).Status
= 0xdeadbabe;
693 iosb
.Information
= 0xdeadbeef;
694 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
695 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
696 ok( !is_signaled( event
), "event is signaled\n" );
697 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
698 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
699 ok( !apc_count
, "apc was called\n" );
700 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
701 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
702 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
703 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
704 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
705 ok( is_signaled( event
), "event is signaled\n" );
706 todo_wine
ok( !apc_count
, "apc was called\n" );
707 SleepEx( 1, TRUE
); /* alertable sleep */
708 ok( apc_count
== 1, "apc was not called\n" );
712 U(iosb
).Status
= 0xdeadbabe;
713 iosb
.Information
= 0xdeadbeef;
714 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
715 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
716 ok( !is_signaled( event
), "event is signaled\n" );
717 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
718 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
719 ok( !apc_count
, "apc was called\n" );
720 status
= pNtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
721 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
722 ok( !is_signaled( event
), "event is signaled\n" );
723 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
724 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
725 ok( !apc_count
, "apc was called\n" );
726 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
727 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
728 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
729 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
730 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
731 ok( is_signaled( event
), "event is signaled\n" );
732 todo_wine
ok( !apc_count
, "apc was called\n" );
733 SleepEx( 1, TRUE
); /* alertable sleep */
734 ok( apc_count
== 2, "apc was not called\n" );
737 CloseHandle( write
);
740 /* now try a real file */
741 if (!(handle
= create_temp_file( FILE_FLAG_OVERLAPPED
))) return;
743 U(iosb
).Status
= 0xdeadbabe;
744 iosb
.Information
= 0xdeadbeef;
747 status
= pNtWriteFile( handle
, event
, apc
, &apc_count
, &iosb
, text
, strlen(text
), &offset
, NULL
);
748 ok( status
== STATUS_SUCCESS
|| status
== STATUS_PENDING
, "wrong status %x\n", status
);
749 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
750 ok( U(iosb
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(iosb
).Status
);
751 ok( iosb
.Information
== strlen(text
), "wrong info %lu\n", iosb
.Information
);
752 ok( is_signaled( event
), "event is signaled\n" );
753 ok( !apc_count
, "apc was called\n" );
754 SleepEx( 1, TRUE
); /* alertable sleep */
755 ok( apc_count
== 1, "apc was not called\n" );
758 U(iosb
).Status
= 0xdeadbabe;
759 iosb
.Information
= 0xdeadbeef;
762 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, strlen(text
) + 10, &offset
, NULL
);
763 ok( status
== STATUS_SUCCESS
||
764 status
== STATUS_PENDING
, /* vista */
765 "wrong status %x\n", status
);
766 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
767 ok( U(iosb
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(iosb
).Status
);
768 ok( iosb
.Information
== strlen(text
), "wrong info %lu\n", iosb
.Information
);
769 ok( is_signaled( event
), "event is signaled\n" );
770 ok( !apc_count
, "apc was called\n" );
771 SleepEx( 1, TRUE
); /* alertable sleep */
772 ok( apc_count
== 1, "apc was not called\n" );
774 /* read beyond eof */
776 U(iosb
).Status
= 0xdeadbabe;
777 iosb
.Information
= 0xdeadbeef;
778 offset
.QuadPart
= strlen(text
) + 2;
779 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, &offset
, NULL
);
780 if (status
== STATUS_PENDING
) /* vista */
782 WaitForSingleObject( event
, 1000 );
783 ok( U(iosb
).Status
== STATUS_END_OF_FILE
, "wrong status %x\n", U(iosb
).Status
);
784 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
785 ok( is_signaled( event
), "event is signaled\n" );
786 ok( !apc_count
, "apc was called\n" );
787 SleepEx( 1, TRUE
); /* alertable sleep */
788 ok( apc_count
== 1, "apc was not called\n" );
792 ok( status
== STATUS_END_OF_FILE
, "wrong status %x\n", status
);
793 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
794 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
795 ok( !is_signaled( event
), "event is signaled\n" );
796 ok( !apc_count
, "apc was called\n" );
797 SleepEx( 1, TRUE
); /* alertable sleep */
798 ok( !apc_count
, "apc was called\n" );
800 CloseHandle( handle
);
802 /* now a non-overlapped file */
803 if (!(handle
= create_temp_file(0))) return;
805 U(iosb
).Status
= 0xdeadbabe;
806 iosb
.Information
= 0xdeadbeef;
808 status
= pNtWriteFile( handle
, event
, apc
, &apc_count
, &iosb
, text
, strlen(text
), &offset
, NULL
);
809 ok( status
== STATUS_END_OF_FILE
||
810 status
== STATUS_SUCCESS
||
811 status
== STATUS_PENDING
, /* vista */
812 "wrong status %x\n", status
);
813 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
814 ok( U(iosb
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(iosb
).Status
);
815 ok( iosb
.Information
== strlen(text
), "wrong info %lu\n", iosb
.Information
);
816 ok( is_signaled( event
), "event is signaled\n" );
817 ok( !apc_count
, "apc was called\n" );
818 SleepEx( 1, TRUE
); /* alertable sleep */
819 ok( apc_count
== 1, "apc was not called\n" );
822 U(iosb
).Status
= 0xdeadbabe;
823 iosb
.Information
= 0xdeadbeef;
826 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, strlen(text
) + 10, &offset
, NULL
);
827 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
828 ok( U(iosb
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(iosb
).Status
);
829 ok( iosb
.Information
== strlen(text
), "wrong info %lu\n", iosb
.Information
);
830 ok( is_signaled( event
), "event is signaled\n" );
831 ok( !apc_count
, "apc was called\n" );
832 SleepEx( 1, TRUE
); /* alertable sleep */
833 todo_wine
ok( !apc_count
, "apc was called\n" );
835 /* read beyond eof */
837 U(iosb
).Status
= 0xdeadbabe;
838 iosb
.Information
= 0xdeadbeef;
839 offset
.QuadPart
= strlen(text
) + 2;
841 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, &offset
, NULL
);
842 ok( status
== STATUS_END_OF_FILE
, "wrong status %x\n", status
);
843 todo_wine
ok( U(iosb
).Status
== STATUS_END_OF_FILE
, "wrong status %x\n", U(iosb
).Status
);
844 todo_wine
ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
845 todo_wine
ok( is_signaled( event
), "event is not signaled\n" );
846 ok( !apc_count
, "apc was called\n" );
847 SleepEx( 1, TRUE
); /* alertable sleep */
848 ok( !apc_count
, "apc was called\n" );
850 CloseHandle( handle
);
852 CloseHandle( event
);
855 static void append_file_test(void)
857 const char text
[] = "foobar";
860 IO_STATUS_BLOCK iosb
;
864 GetTempFileNameA( ".", "foo", 0, buffer
);
865 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
866 It matches the O_WRONLY|O_APPEND open() posix behavior */
867 handle
= CreateFileA(buffer
, FILE_APPEND_DATA
, 0, NULL
, CREATE_ALWAYS
,
868 FILE_FLAG_DELETE_ON_CLOSE
, 0);
869 ok( handle
!= INVALID_HANDLE_VALUE
, "Failed to create a temp file in FILE_APPEND_DATA mode.\n" );
870 if(handle
== INVALID_HANDLE_VALUE
)
872 skip("Couldn't create a temporary file, skipping FILE_APPEND_DATA test\n");
876 U(iosb
).Status
= STATUS_PENDING
;
877 iosb
.Information
= 0;
879 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
,
880 text
, sizeof(text
), NULL
, NULL
);
882 if (status
== STATUS_PENDING
)
884 WaitForSingleObject( handle
, 1000 );
885 status
= U(iosb
).Status
;
887 written
= iosb
.Information
;
890 ok(status
== STATUS_SUCCESS
&& written
== sizeof(text
), "FILE_APPEND_DATA NtWriteFile failed\n");
895 static void nt_mailslot_test(void)
898 ACCESS_MASK DesiredAccess
;
899 OBJECT_ATTRIBUTES attr
;
903 ULONG MaxMessageSize
;
904 LARGE_INTEGER TimeOut
;
905 IO_STATUS_BLOCK IoStatusBlock
;
908 WCHAR buffer1
[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
909 'R',':','\\','F','R','E','D','\0' };
911 TimeOut
.QuadPart
= -1;
913 pRtlInitUnicodeString(&str
, buffer1
);
914 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
915 CreateOptions
= MailslotQuota
= MaxMessageSize
= 0;
916 DesiredAccess
= GENERIC_READ
;
919 * Check for NULL pointer handling
921 rc
= pNtCreateMailslotFile(NULL
, DesiredAccess
,
922 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
924 ok( rc
== STATUS_ACCESS_VIOLATION
||
925 rc
== STATUS_INVALID_PARAMETER
, /* win2k3 */
926 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc
);
929 * Test to see if the Timeout can be NULL
931 hslot
= (HANDLE
)0xdeadbeef;
932 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
933 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
935 ok( rc
== STATUS_SUCCESS
||
936 rc
== STATUS_INVALID_PARAMETER
, /* win2k3 */
937 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc
);
938 ok( hslot
!= 0, "Handle is invalid\n");
940 if ( rc
== STATUS_SUCCESS
) pNtClose(hslot
);
943 * Test that the length field is checked properly
946 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
947 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
949 todo_wine
ok( rc
== STATUS_INVALID_PARAMETER
, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc
);
951 if (rc
== STATUS_SUCCESS
) pNtClose(hslot
);
953 attr
.Length
= sizeof(OBJECT_ATTRIBUTES
)+1;
954 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
955 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
957 todo_wine
ok( rc
== STATUS_INVALID_PARAMETER
, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc
);
959 if (rc
== STATUS_SUCCESS
) pNtClose(hslot
);
962 * Test handling of a NULL unicode string in ObjectName
964 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
965 attr
.ObjectName
= NULL
;
966 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
967 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
969 ok( rc
== STATUS_OBJECT_PATH_SYNTAX_BAD
||
970 rc
== STATUS_INVALID_PARAMETER
,
971 "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc
);
973 if (rc
== STATUS_SUCCESS
) pNtClose(hslot
);
978 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
979 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
980 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
982 ok( rc
== STATUS_SUCCESS
, "Create MailslotFile failed rc = %x\n", rc
);
983 ok( hslot
!= 0, "Handle is invalid\n");
985 rc
= pNtClose(hslot
);
986 ok( rc
== STATUS_SUCCESS
, "NtClose failed\n");
989 static void test_iocp_setcompletion(HANDLE h
)
994 res
= pNtSetIoCompletion( h
, CKEY_FIRST
, CVALUE_FIRST
, STATUS_INVALID_DEVICE_REQUEST
, 3 );
995 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %x\n", res
);
997 count
= get_pending_msgs(h
);
998 ok( count
== 1, "Unexpected msg count: %d\n", count
);
1002 ok( completionKey
== CKEY_FIRST
, "Invalid completion key: %lx\n", completionKey
);
1003 ok( ioSb
.Information
== 3, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1004 ok( U(ioSb
).Status
== STATUS_INVALID_DEVICE_REQUEST
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1005 ok( completionValue
== CVALUE_FIRST
, "Invalid completion value: %lx\n", completionValue
);
1008 count
= get_pending_msgs(h
);
1009 ok( !count
, "Unexpected msg count: %d\n", count
);
1012 static void test_iocp_fileio(HANDLE h
)
1014 static const char pipe_name
[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1016 IO_STATUS_BLOCK iosb
;
1017 FILE_COMPLETION_INFORMATION fci
= {h
, CKEY_SECOND
};
1018 HANDLE hPipeSrv
, hPipeClt
;
1021 hPipeSrv
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
, 4, 1024, 1024, 1000, NULL
);
1022 ok( hPipeSrv
!= INVALID_HANDLE_VALUE
, "Cannot create named pipe\n" );
1023 if (hPipeSrv
!= INVALID_HANDLE_VALUE
)
1025 hPipeClt
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1026 ok( hPipeClt
!= INVALID_HANDLE_VALUE
, "Cannot connect to pipe\n" );
1027 if (hPipeClt
!= INVALID_HANDLE_VALUE
)
1029 U(iosb
).Status
= 0xdeadbeef;
1030 res
= pNtSetInformationFile( hPipeSrv
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1031 ok( res
== STATUS_INVALID_PARAMETER
, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res
);
1032 ok( U(iosb
).Status
== STATUS_INVALID_PARAMETER
/* 98 */ || U(iosb
).Status
== 0xdeadbeef /* NT4+ */,
1033 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb
).Status
);
1034 CloseHandle(hPipeClt
);
1036 CloseHandle( hPipeSrv
);
1039 hPipeSrv
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
, 4, 1024, 1024, 1000, NULL
);
1040 ok( hPipeSrv
!= INVALID_HANDLE_VALUE
, "Cannot create named pipe\n" );
1041 if (hPipeSrv
== INVALID_HANDLE_VALUE
)
1044 hPipeClt
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1045 ok( hPipeClt
!= INVALID_HANDLE_VALUE
, "Cannot connect to pipe\n" );
1046 if (hPipeClt
!= INVALID_HANDLE_VALUE
)
1048 OVERLAPPED o
= {0,};
1049 BYTE send_buf
[TEST_BUF_LEN
], recv_buf
[TEST_BUF_LEN
];
1053 U(iosb
).Status
= 0xdeadbeef;
1054 res
= pNtSetInformationFile( hPipeSrv
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1055 ok( res
== STATUS_SUCCESS
, "NtSetInformationFile failed: %x\n", res
);
1056 ok( U(iosb
).Status
== STATUS_SUCCESS
, "iosb.Status invalid: %x\n", U(iosb
).Status
);
1058 memset( send_buf
, 0, TEST_BUF_LEN
);
1059 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1060 count
= get_pending_msgs(h
);
1061 ok( !count
, "Unexpected msg count: %ld\n", count
);
1062 ReadFile( hPipeSrv
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1063 count
= get_pending_msgs(h
);
1064 ok( !count
, "Unexpected msg count: %ld\n", count
);
1065 WriteFile( hPipeClt
, send_buf
, TEST_BUF_LEN
, &read
, NULL
);
1069 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1070 ok( ioSb
.Information
== 3, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1071 ok( U(ioSb
).Status
== STATUS_SUCCESS
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1072 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1073 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] );
1075 count
= get_pending_msgs(h
);
1076 ok( !count
, "Unexpected msg count: %ld\n", count
);
1078 memset( send_buf
, 0, TEST_BUF_LEN
);
1079 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1080 WriteFile( hPipeClt
, send_buf
, 2, &read
, NULL
);
1081 count
= get_pending_msgs(h
);
1082 ok( !count
, "Unexpected msg count: %ld\n", count
);
1083 ReadFile( hPipeSrv
, recv_buf
, 2, &read
, &o
);
1084 count
= get_pending_msgs(h
);
1085 ok( count
== 1, "Unexpected msg count: %ld\n", count
);
1088 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1089 ok( ioSb
.Information
== 2, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1090 ok( U(ioSb
).Status
== STATUS_SUCCESS
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1091 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1092 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] );
1095 ReadFile( hPipeSrv
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1096 CloseHandle( hPipeSrv
);
1097 count
= get_pending_msgs(h
);
1098 ok( count
== 1, "Unexpected msg count: %ld\n", count
);
1101 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1102 ok( ioSb
.Information
== 0, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1103 /* wine sends wrong status here */
1104 todo_wine
ok( U(ioSb
).Status
== STATUS_PIPE_BROKEN
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1105 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1109 CloseHandle( hPipeClt
);
1111 /* test associating a completion port with a handle after an async is queued */
1112 hPipeSrv
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
, 4, 1024, 1024, 1000, NULL
);
1113 ok( hPipeSrv
!= INVALID_HANDLE_VALUE
, "Cannot create named pipe\n" );
1114 if (hPipeSrv
== INVALID_HANDLE_VALUE
)
1116 hPipeClt
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1117 ok( hPipeClt
!= INVALID_HANDLE_VALUE
, "Cannot connect to pipe\n" );
1118 if (hPipeClt
!= INVALID_HANDLE_VALUE
)
1120 OVERLAPPED o
= {0,};
1121 BYTE send_buf
[TEST_BUF_LEN
], recv_buf
[TEST_BUF_LEN
];
1125 memset( send_buf
, 0, TEST_BUF_LEN
);
1126 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1127 count
= get_pending_msgs(h
);
1128 ok( !count
, "Unexpected msg count: %ld\n", count
);
1129 ReadFile( hPipeSrv
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1131 U(iosb
).Status
= 0xdeadbeef;
1132 res
= pNtSetInformationFile( hPipeSrv
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1133 ok( res
== STATUS_SUCCESS
, "NtSetInformationFile failed: %x\n", res
);
1134 ok( U(iosb
).Status
== STATUS_SUCCESS
, "iosb.Status invalid: %x\n", U(iosb
).Status
);
1135 count
= get_pending_msgs(h
);
1136 ok( !count
, "Unexpected msg count: %ld\n", count
);
1138 WriteFile( hPipeClt
, send_buf
, TEST_BUF_LEN
, &read
, NULL
);
1142 ok( completionKey
== CKEY_SECOND
, "Invalid completion key: %lx\n", completionKey
);
1143 ok( ioSb
.Information
== 3, "Invalid ioSb.Information: %ld\n", ioSb
.Information
);
1144 ok( U(ioSb
).Status
== STATUS_SUCCESS
, "Invalid ioSb.Status: %x\n", U(ioSb
).Status
);
1145 ok( completionValue
== (ULONG_PTR
)&o
, "Invalid completion value: %lx\n", completionValue
);
1146 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] );
1148 count
= get_pending_msgs(h
);
1149 ok( !count
, "Unexpected msg count: %ld\n", count
);
1152 CloseHandle( hPipeSrv
);
1153 CloseHandle( hPipeClt
);
1156 static void test_file_basic_information(void)
1159 FILE_BASIC_INFORMATION fbi
;
1162 int attrib_mask
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_NORMAL
;
1164 if (!(h
= create_temp_file(0))) return;
1166 /* Check default first */
1167 memset(&fbi
, 0, sizeof(fbi
));
1168 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1169 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1170 ok ( (fbi
.FileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) == FILE_ATTRIBUTE_ARCHIVE
,
1171 "attribute %x not expected\n", fbi
.FileAttributes
);
1174 /* Clear fbi to avoid setting times */
1175 memset(&fbi
, 0, sizeof(fbi
));
1176 fbi
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
1177 U(io
).Status
= 0xdeadbeef;
1178 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1179 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, NtSetInformationFile returned %x\n", res
);
1180 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status is %x\n", U(io
).Status
);
1182 memset(&fbi
, 0, sizeof(fbi
));
1183 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1184 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1185 todo_wine
ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_SYSTEM
, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi
.FileAttributes
);
1188 memset(&fbi
, 0, sizeof(fbi
));
1189 fbi
.FileAttributes
= FILE_ATTRIBUTE_HIDDEN
;
1190 U(io
).Status
= 0xdeadbeef;
1191 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1192 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, NtSetInformationFile returned %x\n", res
);
1193 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status is %x\n", U(io
).Status
);
1195 memset(&fbi
, 0, sizeof(fbi
));
1196 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1197 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1198 todo_wine
ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_HIDDEN
, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi
.FileAttributes
);
1200 /* Check NORMAL last of all (to make sure we can clear attributes) */
1201 memset(&fbi
, 0, sizeof(fbi
));
1202 fbi
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
1203 U(io
).Status
= 0xdeadbeef;
1204 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1205 ok ( res
== STATUS_SUCCESS
, "can't set normal attribute, NtSetInformationFile returned %x\n", res
);
1206 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set normal attribute, io.Status is %x\n", U(io
).Status
);
1208 memset(&fbi
, 0, sizeof(fbi
));
1209 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1210 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1211 todo_wine
ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_NORMAL
, "attribute %x not 0\n", fbi
.FileAttributes
);
1216 static void test_file_all_information(void)
1219 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1220 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1221 * don't leave enough room there.
1224 FILE_ALL_INFORMATION fai
;
1229 int attrib_mask
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_NORMAL
;
1231 if (!(h
= create_temp_file(0))) return;
1233 /* Check default first */
1234 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1235 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1236 ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) == FILE_ATTRIBUTE_ARCHIVE
,
1237 "attribute %x not expected\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1240 /* Clear fbi to avoid setting times */
1241 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1242 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
1243 U(io
).Status
= 0xdeadbeef;
1244 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1245 ok ( res
== STATUS_INVALID_INFO_CLASS
|| broken(res
== STATUS_NOT_IMPLEMENTED
), "shouldn't be able to set FileAllInformation, res %x\n", res
);
1246 todo_wine
ok ( U(io
).Status
== 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io
).Status
);
1247 U(io
).Status
= 0xdeadbeef;
1248 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1249 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1250 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %x\n", U(io
).Status
);
1252 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1253 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1254 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1255 todo_wine
ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_SYSTEM
, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1258 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1259 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_HIDDEN
;
1260 U(io
).Status
= 0xdeadbeef;
1261 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1262 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1263 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %x\n", U(io
).Status
);
1265 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1266 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1267 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1268 todo_wine
ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_HIDDEN
, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1270 /* Check NORMAL last of all (to make sure we can clear attributes) */
1271 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1272 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
1273 U(io
).Status
= 0xdeadbeef;
1274 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1275 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1276 ok ( U(io
).Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %x\n", U(io
).Status
);
1278 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1279 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1280 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1281 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
);
1286 static void test_file_both_information(void)
1289 FILE_BOTH_DIR_INFORMATION fbi
;
1293 if (!(h
= create_temp_file(0))) return;
1295 memset(&fbi
, 0, sizeof(fbi
));
1296 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBothDirectoryInformation
);
1297 ok ( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_NOT_IMPLEMENTED
, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res
);
1302 static void test_iocompletion(void)
1304 HANDLE h
= INVALID_HANDLE_VALUE
;
1307 res
= pNtCreateIoCompletion( &h
, IO_COMPLETION_ALL_ACCESS
, NULL
, 0);
1309 ok( res
== 0, "NtCreateIoCompletion anonymous failed: %x\n", res
);
1310 ok( h
&& h
!= INVALID_HANDLE_VALUE
, "Invalid handle returned\n" );
1312 if ( h
&& h
!= INVALID_HANDLE_VALUE
)
1314 test_iocp_setcompletion(h
);
1315 test_iocp_fileio(h
);
1320 static void test_file_name_information(void)
1322 WCHAR
*file_name
, *volume_prefix
, *expected
;
1323 FILE_NAME_INFORMATION
*info
;
1324 ULONG old_redir
= 1, tmp
;
1325 UINT file_name_size
;
1332 /* GetVolumePathName is not present before w2k */
1333 if (!pGetVolumePathNameW
) {
1334 win_skip("GetVolumePathNameW not found\n");
1338 file_name_size
= GetSystemDirectoryW( NULL
, 0 );
1339 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1340 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1341 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1343 len
= GetSystemDirectoryW( file_name
, file_name_size
);
1344 ok(len
== file_name_size
- 1,
1345 "GetSystemDirectoryW returned %u, expected %u.\n",
1346 len
, file_name_size
- 1);
1348 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1349 ok(len
, "GetVolumePathNameW failed.\n");
1351 len
= lstrlenW( volume_prefix
);
1352 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1353 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1354 expected
[file_name_size
- len
- 1] = '\0';
1356 /* A bit more than we actually need, but it keeps the calculation simple. */
1357 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1358 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1360 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( TRUE
, &old_redir
);
1361 h
= CreateFileW( file_name
, GENERIC_READ
,
1362 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1363 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1364 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( old_redir
, &tmp
);
1365 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1367 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
) - 1, FileNameInformation
);
1368 ok(hr
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile returned %#x.\n", hr
);
1370 memset( info
, 0xcc, info_size
);
1371 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
), FileNameInformation
);
1372 ok(hr
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile returned %#x, expected %#x.\n",
1373 hr
, STATUS_BUFFER_OVERFLOW
);
1374 ok(U(io
).Status
== STATUS_BUFFER_OVERFLOW
, "io.Status is %#x, expected %#x.\n",
1375 U(io
).Status
, STATUS_BUFFER_OVERFLOW
);
1376 ok(info
->FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
), "info->FileNameLength is %u\n", info
->FileNameLength
);
1377 ok(info
->FileName
[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info
->FileName
[2]);
1378 ok(CharLowerW((LPWSTR
)(UINT_PTR
)info
->FileName
[1]) == CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]),
1379 "info->FileName[1] is %p, expected %p.\n",
1380 CharLowerW((LPWSTR
)(UINT_PTR
)info
->FileName
[1]), CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]));
1381 ok(io
.Information
== sizeof(*info
), "io.Information is %lu\n", io
.Information
);
1383 memset( info
, 0xcc, info_size
);
1384 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileNameInformation
);
1385 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1386 ok(U(io
).Status
== STATUS_SUCCESS
, "io.Status is %#x, expected %#x.\n", U(io
).Status
, STATUS_SUCCESS
);
1387 ok(info
->FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
), "info->FileNameLength is %u\n", info
->FileNameLength
);
1388 ok(info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
1389 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)]);
1390 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = '\0';
1391 ok(!lstrcmpiW( info
->FileName
, expected
), "info->FileName is %s, expected %s.\n",
1392 wine_dbgstr_w( info
->FileName
), wine_dbgstr_w( expected
));
1393 ok(io
.Information
== FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + info
->FileNameLength
,
1394 "io.Information is %lu, expected %u.\n",
1395 io
.Information
, FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + info
->FileNameLength
);
1398 HeapFree( GetProcessHeap(), 0, info
);
1399 HeapFree( GetProcessHeap(), 0, expected
);
1400 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1402 if (old_redir
|| !pGetSystemWow64DirectoryW
|| !(file_name_size
= pGetSystemWow64DirectoryW( NULL
, 0 )))
1404 skip("Not running on WoW64, skipping test.\n");
1405 HeapFree( GetProcessHeap(), 0, file_name
);
1409 h
= CreateFileW( file_name
, GENERIC_READ
,
1410 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1411 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1412 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1413 HeapFree( GetProcessHeap(), 0, file_name
);
1415 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1416 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1417 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*expected
) );
1419 len
= pGetSystemWow64DirectoryW( file_name
, file_name_size
);
1420 ok(len
== file_name_size
- 1,
1421 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1422 len
, file_name_size
- 1);
1424 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1425 ok(len
, "GetVolumePathNameW failed.\n");
1427 len
= lstrlenW( volume_prefix
);
1428 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1429 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1430 expected
[file_name_size
- len
- 1] = '\0';
1432 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1433 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1435 memset( info
, 0xcc, info_size
);
1436 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileNameInformation
);
1437 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1438 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = '\0';
1439 ok(!lstrcmpiW( info
->FileName
, expected
), "info->FileName is %s, expected %s.\n",
1440 wine_dbgstr_w( info
->FileName
), wine_dbgstr_w( expected
));
1443 HeapFree( GetProcessHeap(), 0, info
);
1444 HeapFree( GetProcessHeap(), 0, expected
);
1445 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1446 HeapFree( GetProcessHeap(), 0, file_name
);
1449 static void test_file_all_name_information(void)
1451 WCHAR
*file_name
, *volume_prefix
, *expected
;
1452 FILE_ALL_INFORMATION
*info
;
1453 ULONG old_redir
= 1, tmp
;
1454 UINT file_name_size
;
1461 /* GetVolumePathName is not present before w2k */
1462 if (!pGetVolumePathNameW
) {
1463 win_skip("GetVolumePathNameW not found\n");
1467 file_name_size
= GetSystemDirectoryW( NULL
, 0 );
1468 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1469 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1470 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1472 len
= GetSystemDirectoryW( file_name
, file_name_size
);
1473 ok(len
== file_name_size
- 1,
1474 "GetSystemDirectoryW returned %u, expected %u.\n",
1475 len
, file_name_size
- 1);
1477 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1478 ok(len
, "GetVolumePathNameW failed.\n");
1480 len
= lstrlenW( volume_prefix
);
1481 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1482 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1483 expected
[file_name_size
- len
- 1] = '\0';
1485 /* A bit more than we actually need, but it keeps the calculation simple. */
1486 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1487 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1489 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( TRUE
, &old_redir
);
1490 h
= CreateFileW( file_name
, GENERIC_READ
,
1491 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1492 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1493 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( old_redir
, &tmp
);
1494 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1496 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
) - 1, FileAllInformation
);
1497 ok(hr
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile returned %#x, expected %#x.\n",
1498 hr
, STATUS_INFO_LENGTH_MISMATCH
);
1500 memset( info
, 0xcc, info_size
);
1501 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
), FileAllInformation
);
1502 ok(hr
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile returned %#x, expected %#x.\n",
1503 hr
, STATUS_BUFFER_OVERFLOW
);
1504 ok(U(io
).Status
== STATUS_BUFFER_OVERFLOW
, "io.Status is %#x, expected %#x.\n",
1505 U(io
).Status
, STATUS_BUFFER_OVERFLOW
);
1506 ok(info
->NameInformation
.FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
),
1507 "info->NameInformation.FileNameLength is %u\n", info
->NameInformation
.FileNameLength
);
1508 ok(info
->NameInformation
.FileName
[2] == 0xcccc,
1509 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info
->NameInformation
.FileName
[2]);
1510 ok(CharLowerW((LPWSTR
)(UINT_PTR
)info
->NameInformation
.FileName
[1]) == CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]),
1511 "info->NameInformation.FileName[1] is %p, expected %p.\n",
1512 CharLowerW((LPWSTR
)(UINT_PTR
)info
->NameInformation
.FileName
[1]), CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]));
1513 ok(io
.Information
== sizeof(*info
), "io.Information is %lu\n", io
.Information
);
1515 memset( info
, 0xcc, info_size
);
1516 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileAllInformation
);
1517 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1518 ok(U(io
).Status
== STATUS_SUCCESS
, "io.Status is %#x, expected %#x.\n", U(io
).Status
, STATUS_SUCCESS
);
1519 ok(info
->NameInformation
.FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
),
1520 "info->NameInformation.FileNameLength is %u\n", info
->NameInformation
.FileNameLength
);
1521 ok(info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] == 0xcccc,
1522 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
1523 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)]);
1524 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] = '\0';
1525 ok(!lstrcmpiW( info
->NameInformation
.FileName
, expected
),
1526 "info->NameInformation.FileName is %s, expected %s.\n",
1527 wine_dbgstr_w( info
->NameInformation
.FileName
), wine_dbgstr_w( expected
));
1528 ok(io
.Information
== FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
)
1529 + info
->NameInformation
.FileNameLength
,
1530 "io.Information is %lu\n", io
.Information
);
1533 HeapFree( GetProcessHeap(), 0, info
);
1534 HeapFree( GetProcessHeap(), 0, expected
);
1535 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1537 if (old_redir
|| !pGetSystemWow64DirectoryW
|| !(file_name_size
= pGetSystemWow64DirectoryW( NULL
, 0 )))
1539 skip("Not running on WoW64, skipping test.\n");
1540 HeapFree( GetProcessHeap(), 0, file_name
);
1544 h
= CreateFileW( file_name
, GENERIC_READ
,
1545 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1546 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1547 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
1548 HeapFree( GetProcessHeap(), 0, file_name
);
1550 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
1551 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
1552 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*expected
) );
1554 len
= pGetSystemWow64DirectoryW( file_name
, file_name_size
);
1555 ok(len
== file_name_size
- 1,
1556 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1557 len
, file_name_size
- 1);
1559 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
1560 ok(len
, "GetVolumePathNameW failed.\n");
1562 len
= lstrlenW( volume_prefix
);
1563 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
1564 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
1565 expected
[file_name_size
- len
- 1] = '\0';
1567 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
1568 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1570 memset( info
, 0xcc, info_size
);
1571 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileAllInformation
);
1572 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#x, expected %#x.\n", hr
, STATUS_SUCCESS
);
1573 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] = '\0';
1574 ok(!lstrcmpiW( info
->NameInformation
.FileName
, expected
), "info->NameInformation.FileName is %s, expected %s.\n",
1575 wine_dbgstr_w( info
->NameInformation
.FileName
), wine_dbgstr_w( expected
));
1578 HeapFree( GetProcessHeap(), 0, info
);
1579 HeapFree( GetProcessHeap(), 0, expected
);
1580 HeapFree( GetProcessHeap(), 0, volume_prefix
);
1581 HeapFree( GetProcessHeap(), 0, file_name
);
1584 static void test_query_volume_information_file(void)
1588 WCHAR path
[MAX_PATH
];
1589 OBJECT_ATTRIBUTES attr
;
1591 UNICODE_STRING nameW
;
1592 FILE_FS_VOLUME_INFORMATION
*ffvi
;
1593 BYTE buf
[sizeof(FILE_FS_VOLUME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
1595 GetWindowsDirectoryW( path
, MAX_PATH
);
1596 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
1597 attr
.Length
= sizeof(attr
);
1598 attr
.RootDirectory
= 0;
1599 attr
.ObjectName
= &nameW
;
1600 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1601 attr
.SecurityDescriptor
= NULL
;
1602 attr
.SecurityQualityOfService
= NULL
;
1604 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
1605 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
1606 ok( !status
, "open %s failed %x\n", wine_dbgstr_w(nameW
.Buffer
), status
);
1607 pRtlFreeUnicodeString( &nameW
);
1609 ZeroMemory( buf
, sizeof(buf
) );
1610 U(io
).Status
= 0xdadadada;
1611 io
.Information
= 0xcacacaca;
1613 status
= pNtQueryVolumeInformationFile( dir
, &io
, buf
, sizeof(buf
), FileFsVolumeInformation
);
1615 ffvi
= (FILE_FS_VOLUME_INFORMATION
*)buf
;
1619 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %d\n", status
);
1620 ok(U(io
).Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %d\n", U(io
).Status
);
1622 ok(io
.Information
== (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + ffvi
->VolumeLabelLength
),
1623 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + ffvi
->VolumeLabelLength
),
1626 ok(ffvi
->VolumeCreationTime
.QuadPart
!= 0, "Missing VolumeCreationTime\n");
1627 ok(ffvi
->VolumeSerialNumber
!= 0, "Missing VolumeSerialNumber\n");
1628 ok(ffvi
->SupportsObjects
== 1,"expected 1, got %d\n", ffvi
->SupportsObjects
);
1630 ok(ffvi
->VolumeLabelLength
== lstrlenW(ffvi
->VolumeLabel
) * sizeof(WCHAR
), "got %d\n", ffvi
->VolumeLabelLength
);
1632 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi
->VolumeSerialNumber
, wine_dbgstr_w(ffvi
->VolumeLabel
));
1637 static void test_NtCreateFile(void)
1639 static const struct test_data
1641 DWORD disposition
, attrib_in
, status
, result
, attrib_out
, needs_cleanup
;
1644 /* 0*/{ FILE_CREATE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1645 /* 1*/{ FILE_CREATE
, 0, STATUS_OBJECT_NAME_COLLISION
, 0, 0, TRUE
},
1646 /* 2*/{ FILE_CREATE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1647 /* 3*/{ FILE_OPEN
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
},
1648 /* 4*/{ FILE_OPEN
, FILE_ATTRIBUTE_READONLY
, STATUS_OBJECT_NAME_NOT_FOUND
, 0, 0, FALSE
},
1649 /* 5*/{ FILE_OPEN_IF
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1650 /* 6*/{ FILE_OPEN_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
},
1651 /* 7*/{ FILE_OPEN_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1652 /* 8*/{ FILE_OPEN_IF
, 0, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1653 /* 9*/{ FILE_OVERWRITE
, 0, STATUS_ACCESS_DENIED
, 0, 0, TRUE
},
1654 /*10*/{ FILE_OVERWRITE
, 0, STATUS_OBJECT_NAME_NOT_FOUND
, 0, 0, FALSE
},
1655 /*11*/{ FILE_CREATE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1656 /*12*/{ FILE_OVERWRITE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OVERWRITTEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1657 /*13*/{ FILE_OVERWRITE_IF
, 0, STATUS_ACCESS_DENIED
, 0, 0, TRUE
},
1658 /*14*/{ FILE_OVERWRITE_IF
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1659 /*15*/{ FILE_OVERWRITE_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OVERWRITTEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
1660 /*16*/{ FILE_SUPERSEDE
, 0, 0, FILE_SUPERSEDED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
1661 /*17*/{ FILE_SUPERSEDE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_SUPERSEDED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, TRUE
},
1662 /*18*/{ FILE_SUPERSEDE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
}
1664 static const WCHAR fooW
[] = {'f','o','o',0};
1665 static const WCHAR dotW
[] = {'.',0};
1668 WCHAR path
[MAX_PATH
];
1669 OBJECT_ATTRIBUTES attr
;
1671 UNICODE_STRING nameW
;
1674 GetTempFileNameW(dotW
, fooW
, 0, path
);
1676 pRtlDosPathNameToNtPathName_U(path
, &nameW
, NULL
, NULL
);
1678 attr
.Length
= sizeof(attr
);
1679 attr
.RootDirectory
= NULL
;
1680 attr
.ObjectName
= &nameW
;
1681 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1682 attr
.SecurityDescriptor
= NULL
;
1683 attr
.SecurityQualityOfService
= NULL
;
1685 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
1687 status
= pNtCreateFile(&handle
, GENERIC_READ
, &attr
, &io
, NULL
,
1688 td
[i
].attrib_in
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1689 td
[i
].disposition
, 0, NULL
, 0);
1691 ok(status
== td
[i
].status
, "%d: expected %#x got %#x\n", i
, td
[i
].status
, status
);
1695 ok(io
.Information
== td
[i
].result
,"%d: expected %#x got %#lx\n", i
, td
[i
].result
, io
.Information
);
1697 ret
= GetFileAttributesW(path
);
1698 ret
&= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
;
1699 /* FIXME: leave only 'else' case below once Wine is fixed */
1700 if (ret
!= td
[i
].attrib_out
)
1703 ok(ret
== td
[i
].attrib_out
, "%d: expected %#x got %#x\n", i
, td
[i
].attrib_out
, ret
);
1704 SetFileAttributesW(path
, td
[i
].attrib_out
);
1707 ok(ret
== td
[i
].attrib_out
, "%d: expected %#x got %#x\n", i
, td
[i
].attrib_out
, ret
);
1709 CloseHandle(handle
);
1712 if (td
[i
].needs_cleanup
)
1714 SetFileAttributesW(path
, FILE_ATTRIBUTE_ARCHIVE
);
1719 SetFileAttributesW(path
, FILE_ATTRIBUTE_ARCHIVE
);
1720 DeleteFileW( path
);
1725 HMODULE hkernel32
= GetModuleHandleA("kernel32.dll");
1726 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
1729 skip("not running on NT, skipping test\n");
1733 pGetVolumePathNameW
= (void *)GetProcAddress(hkernel32
, "GetVolumePathNameW");
1734 pGetSystemWow64DirectoryW
= (void *)GetProcAddress(hkernel32
, "GetSystemWow64DirectoryW");
1736 pRtlFreeUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlFreeUnicodeString");
1737 pRtlInitUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlInitUnicodeString");
1738 pRtlDosPathNameToNtPathName_U
= (void *)GetProcAddress(hntdll
, "RtlDosPathNameToNtPathName_U");
1739 pRtlWow64EnableFsRedirectionEx
= (void *)GetProcAddress(hntdll
, "RtlWow64EnableFsRedirectionEx");
1740 pNtCreateMailslotFile
= (void *)GetProcAddress(hntdll
, "NtCreateMailslotFile");
1741 pNtCreateFile
= (void *)GetProcAddress(hntdll
, "NtCreateFile");
1742 pNtOpenFile
= (void *)GetProcAddress(hntdll
, "NtOpenFile");
1743 pNtDeleteFile
= (void *)GetProcAddress(hntdll
, "NtDeleteFile");
1744 pNtReadFile
= (void *)GetProcAddress(hntdll
, "NtReadFile");
1745 pNtWriteFile
= (void *)GetProcAddress(hntdll
, "NtWriteFile");
1746 pNtCancelIoFile
= (void *)GetProcAddress(hntdll
, "NtCancelIoFile");
1747 pNtCancelIoFileEx
= (void *)GetProcAddress(hntdll
, "NtCancelIoFileEx");
1748 pNtClose
= (void *)GetProcAddress(hntdll
, "NtClose");
1749 pNtCreateIoCompletion
= (void *)GetProcAddress(hntdll
, "NtCreateIoCompletion");
1750 pNtOpenIoCompletion
= (void *)GetProcAddress(hntdll
, "NtOpenIoCompletion");
1751 pNtQueryIoCompletion
= (void *)GetProcAddress(hntdll
, "NtQueryIoCompletion");
1752 pNtRemoveIoCompletion
= (void *)GetProcAddress(hntdll
, "NtRemoveIoCompletion");
1753 pNtSetIoCompletion
= (void *)GetProcAddress(hntdll
, "NtSetIoCompletion");
1754 pNtSetInformationFile
= (void *)GetProcAddress(hntdll
, "NtSetInformationFile");
1755 pNtQueryInformationFile
= (void *)GetProcAddress(hntdll
, "NtQueryInformationFile");
1756 pNtQueryDirectoryFile
= (void *)GetProcAddress(hntdll
, "NtQueryDirectoryFile");
1757 pNtQueryVolumeInformationFile
= (void *)GetProcAddress(hntdll
, "NtQueryVolumeInformationFile");
1759 test_NtCreateFile();
1766 test_iocompletion();
1767 test_file_basic_information();
1768 test_file_all_information();
1769 test_file_both_information();
1770 test_file_name_information();
1771 test_file_all_name_information();
1772 test_query_volume_information_file();