2007-02-27 13:41:55 +01:00
/* Unit test suite for Ntdll file functions
*
* Copyright 2007 Jeff Latimer
2007-11-09 23:11:31 +01:00
* Copyright 2007 Andrey Turkin
2008-08-31 13:54:03 +02:00
* Copyright 2008 Jeff Zaroyko
2007-02-27 13:41:55 +01:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
*
* NOTES
* We use function pointers here as there is no import library for NTDLL on
* windows .
*/
# include <stdio.h>
# include <stdarg.h>
# include "ntstatus.h"
/* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
* definition errors when we get to winnt . h
*/
# define WIN32_NO_STATUS
# include "wine/test.h"
# include "winternl.h"
2009-11-12 15:10:14 +01:00
# include "winuser.h"
2010-11-22 21:24:42 +01:00
# include "winioctl.h"
2007-02-27 13:41:55 +01:00
2007-11-09 23:11:31 +01:00
# ifndef IO_COMPLETION_ALL_ACCESS
# define IO_COMPLETION_ALL_ACCESS 0x001F0003
# endif
2009-11-12 23:42:53 +01:00
static BOOL ( WINAPI * pGetVolumePathNameW ) ( LPCWSTR , LPWSTR , DWORD ) ;
2009-11-19 11:41:23 +01:00
static UINT ( WINAPI * pGetSystemWow64DirectoryW ) ( LPWSTR , UINT ) ;
2009-11-12 23:42:53 +01:00
2009-12-08 11:44:04 +01:00
static VOID ( WINAPI * pRtlFreeUnicodeString ) ( PUNICODE_STRING ) ;
2007-02-27 13:41:55 +01:00
static VOID ( WINAPI * pRtlInitUnicodeString ) ( PUNICODE_STRING , LPCWSTR ) ;
2008-08-31 13:54:03 +02:00
static BOOL ( WINAPI * pRtlDosPathNameToNtPathName_U ) ( LPCWSTR , PUNICODE_STRING , PWSTR * , CURDIR * ) ;
2009-11-19 11:41:22 +01:00
static NTSTATUS ( WINAPI * pRtlWow64EnableFsRedirectionEx ) ( ULONG , ULONG * ) ;
2007-02-27 13:41:55 +01:00
static NTSTATUS ( WINAPI * pNtCreateMailslotFile ) ( PHANDLE , ULONG , POBJECT_ATTRIBUTES , PIO_STATUS_BLOCK ,
ULONG , ULONG , ULONG , PLARGE_INTEGER ) ;
2009-12-08 12:19:05 +01:00
static NTSTATUS ( WINAPI * pNtCreateFile ) ( PHANDLE , ACCESS_MASK , POBJECT_ATTRIBUTES , PIO_STATUS_BLOCK , PLARGE_INTEGER , ULONG , ULONG , ULONG , ULONG , PVOID , ULONG ) ;
2009-12-01 17:38:39 +01:00
static NTSTATUS ( WINAPI * pNtOpenFile ) ( PHANDLE , ACCESS_MASK , POBJECT_ATTRIBUTES , PIO_STATUS_BLOCK , ULONG , ULONG ) ;
2008-08-31 13:54:03 +02:00
static NTSTATUS ( WINAPI * pNtDeleteFile ) ( POBJECT_ATTRIBUTES ObjectAttributes ) ;
2007-04-09 12:23:13 +02:00
static NTSTATUS ( WINAPI * pNtReadFile ) ( HANDLE hFile , HANDLE hEvent ,
PIO_APC_ROUTINE apc , void * apc_user ,
PIO_STATUS_BLOCK io_status , void * buffer , ULONG length ,
PLARGE_INTEGER offset , PULONG key ) ;
static NTSTATUS ( WINAPI * pNtWriteFile ) ( HANDLE hFile , HANDLE hEvent ,
PIO_APC_ROUTINE apc , void * apc_user ,
PIO_STATUS_BLOCK io_status ,
const void * buffer , ULONG length ,
PLARGE_INTEGER offset , PULONG key ) ;
2009-08-14 00:56:23 +02:00
static NTSTATUS ( WINAPI * pNtCancelIoFile ) ( HANDLE hFile , PIO_STATUS_BLOCK io_status ) ;
2009-08-08 22:32:34 +02:00
static NTSTATUS ( WINAPI * pNtCancelIoFileEx ) ( HANDLE hFile , PIO_STATUS_BLOCK iosb , PIO_STATUS_BLOCK io_status ) ;
2007-02-27 13:41:55 +01:00
static NTSTATUS ( WINAPI * pNtClose ) ( PHANDLE ) ;
2007-11-09 23:11:31 +01:00
static NTSTATUS ( WINAPI * pNtCreateIoCompletion ) ( PHANDLE , ACCESS_MASK , POBJECT_ATTRIBUTES , ULONG ) ;
static NTSTATUS ( WINAPI * pNtOpenIoCompletion ) ( PHANDLE , ACCESS_MASK , POBJECT_ATTRIBUTES ) ;
static NTSTATUS ( WINAPI * pNtQueryIoCompletion ) ( HANDLE , IO_COMPLETION_INFORMATION_CLASS , PVOID , ULONG , PULONG ) ;
static NTSTATUS ( WINAPI * pNtRemoveIoCompletion ) ( HANDLE , PULONG_PTR , PULONG_PTR , PIO_STATUS_BLOCK , PLARGE_INTEGER ) ;
static NTSTATUS ( WINAPI * pNtSetIoCompletion ) ( HANDLE , ULONG_PTR , ULONG_PTR , NTSTATUS , ULONG ) ;
static NTSTATUS ( WINAPI * pNtSetInformationFile ) ( HANDLE , PIO_STATUS_BLOCK , PVOID , ULONG , FILE_INFORMATION_CLASS ) ;
2009-09-09 14:41:30 +02:00
static NTSTATUS ( WINAPI * pNtQueryInformationFile ) ( HANDLE , PIO_STATUS_BLOCK , PVOID , ULONG , FILE_INFORMATION_CLASS ) ;
2009-12-02 17:36:58 +01:00
static NTSTATUS ( WINAPI * pNtQueryDirectoryFile ) ( HANDLE , HANDLE , PIO_APC_ROUTINE , PVOID , PIO_STATUS_BLOCK ,
PVOID , ULONG , FILE_INFORMATION_CLASS , BOOLEAN , PUNICODE_STRING , BOOLEAN ) ;
2010-11-22 21:24:42 +01:00
static NTSTATUS ( WINAPI * pNtQueryVolumeInformationFile ) ( HANDLE , PIO_STATUS_BLOCK , PVOID , ULONG , FS_INFORMATION_CLASS ) ;
2007-11-09 23:11:31 +01:00
2007-04-09 12:23:13 +02:00
static inline BOOL is_signaled ( HANDLE obj )
{
return WaitForSingleObject ( obj , 0 ) = = 0 ;
}
# define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
2008-06-02 22:14:26 +02:00
# define TEST_BUF_LEN 3
2007-04-09 12:23:13 +02:00
static BOOL create_pipe ( HANDLE * read , HANDLE * write , ULONG flags , ULONG size )
{
* read = CreateNamedPipe ( PIPENAME , PIPE_ACCESS_INBOUND | flags , PIPE_TYPE_BYTE | PIPE_WAIT ,
1 , size , size , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( * read ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
* write = CreateFileA ( PIPENAME , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( * write ! = INVALID_HANDLE_VALUE , " CreateFile failed (%d) \n " , GetLastError ( ) ) ;
return TRUE ;
}
static HANDLE create_temp_file ( ULONG flags )
{
char buffer [ MAX_PATH ] ;
HANDLE handle ;
GetTempFileNameA ( " . " , " foo " , 0 , buffer ) ;
handle = CreateFileA ( buffer , GENERIC_READ | GENERIC_WRITE , 0 , NULL , CREATE_ALWAYS ,
flags | FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
return ( handle = = INVALID_HANDLE_VALUE ) ? 0 : handle ;
}
2007-11-09 23:11:31 +01:00
# define CVALUE_FIRST 0xfffabbcc
# define CKEY_FIRST 0x1030341
# define CKEY_SECOND 0x132E46
2010-10-01 13:37:03 +02:00
static ULONG_PTR completionKey ;
static IO_STATUS_BLOCK ioSb ;
static ULONG_PTR completionValue ;
2007-11-09 23:11:31 +01:00
2010-04-21 11:00:26 +02:00
static ULONG get_pending_msgs ( HANDLE h )
2007-11-09 23:11:31 +01:00
{
NTSTATUS res ;
ULONG a , req ;
2009-03-17 00:12:11 +01:00
res = pNtQueryIoCompletion ( h , IoCompletionBasicInformation , & a , sizeof ( a ) , & req ) ;
2007-11-09 23:11:31 +01:00
ok ( res = = STATUS_SUCCESS , " NtQueryIoCompletion failed: %x \n " , res ) ;
if ( res ! = STATUS_SUCCESS ) return - 1 ;
ok ( req = = sizeof ( a ) , " Unexpected response size: %x \n " , req ) ;
return a ;
}
static BOOL get_msg ( HANDLE h )
{
LARGE_INTEGER timeout = { { - 10000000 * 3 } } ;
DWORD res = pNtRemoveIoCompletion ( h , & completionKey , & completionValue , & ioSb , & timeout ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletion failed: %x \n " , res ) ;
if ( res ! = STATUS_SUCCESS )
{
completionKey = completionValue = 0 ;
memset ( & ioSb , 0 , sizeof ( ioSb ) ) ;
return FALSE ;
}
return TRUE ;
}
2007-04-09 12:23:13 +02:00
static void WINAPI apc ( void * arg , IO_STATUS_BLOCK * iosb , ULONG reserved )
{
int * count = arg ;
trace ( " apc called block %p iosb.status %x iosb.info %lu \n " ,
iosb , U ( * iosb ) . Status , iosb - > Information ) ;
( * count ) + + ;
ok ( ! reserved , " reserved is not 0: %x \n " , reserved ) ;
}
2009-12-08 12:19:05 +01:00
static void create_file_test ( void )
{
2010-02-22 22:37:04 +01:00
static const WCHAR systemrootW [ ] = { ' \\ ' , ' S ' , ' y ' , ' s ' , ' t ' , ' e ' , ' m ' , ' R ' , ' o ' , ' o ' , ' t ' ,
' \\ ' , ' f ' , ' a ' , ' i ' , ' l ' , ' i ' , ' n ' , ' g ' , 0 } ;
2009-12-08 12:19:05 +01:00
NTSTATUS status ;
HANDLE dir ;
WCHAR path [ MAX_PATH ] ;
OBJECT_ATTRIBUTES attr ;
IO_STATUS_BLOCK io ;
UNICODE_STRING nameW ;
2010-05-05 00:24:46 +02:00
GetCurrentDirectoryW ( MAX_PATH , path ) ;
2009-12-08 12:19:05 +01:00
pRtlDosPathNameToNtPathName_U ( path , & nameW , NULL , NULL ) ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = 0 ;
attr . ObjectName = & nameW ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
/* try various open modes and options on directories */
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN , FILE_DIRECTORY_FILE , NULL , 0 ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
CloseHandle ( dir ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_CREATE , FILE_DIRECTORY_FILE , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_COLLISION | | status = = STATUS_ACCESS_DENIED ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN_IF , FILE_DIRECTORY_FILE , NULL , 0 ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
CloseHandle ( dir ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_SUPERSEDE , FILE_DIRECTORY_FILE , NULL , 0 ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OVERWRITE , FILE_DIRECTORY_FILE , NULL , 0 ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OVERWRITE_IF , FILE_DIRECTORY_FILE , NULL , 0 ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN , 0 , NULL , 0 ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
CloseHandle ( dir ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_CREATE , 0 , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_COLLISION | | status = = STATUS_ACCESS_DENIED ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN_IF , 0 , NULL , 0 ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
CloseHandle ( dir ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_SUPERSEDE , 0 , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_COLLISION | | status = = STATUS_ACCESS_DENIED ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OVERWRITE , 0 , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_COLLISION | | status = = STATUS_ACCESS_DENIED ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & dir , GENERIC_READ , & attr , & io , NULL , 0 , FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OVERWRITE_IF , 0 , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_COLLISION | | status = = STATUS_ACCESS_DENIED ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
2009-12-16 16:14:02 +01:00
pRtlFreeUnicodeString ( & nameW ) ;
2010-02-22 22:37:04 +01:00
pRtlInitUnicodeString ( & nameW , systemrootW ) ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = NULL ;
attr . ObjectName = & nameW ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
dir = NULL ;
status = pNtCreateFile ( & dir , FILE_APPEND_DATA , & attr , & io , NULL , FILE_ATTRIBUTE_NORMAL , 0 ,
FILE_OPEN_IF , FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
todo_wine
ok ( status = = STATUS_INVALID_PARAMETER ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
2009-12-08 12:19:05 +01:00
}
2009-12-01 17:38:39 +01:00
static void open_file_test ( void )
{
NTSTATUS status ;
2009-12-09 23:34:45 +01:00
HANDLE dir , root , handle ;
2009-12-01 17:38:39 +01:00
WCHAR path [ MAX_PATH ] ;
2010-04-12 14:52:50 +02:00
BYTE data [ 1024 ] ;
2009-12-01 17:38:39 +01:00
OBJECT_ATTRIBUTES attr ;
IO_STATUS_BLOCK io ;
UNICODE_STRING nameW ;
UINT i , len ;
2009-12-02 17:36:58 +01:00
BOOL restart = TRUE ;
2009-12-01 17:38:39 +01:00
len = GetWindowsDirectoryW ( path , MAX_PATH ) ;
pRtlDosPathNameToNtPathName_U ( path , & nameW , NULL , NULL ) ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = 0 ;
attr . ObjectName = & nameW ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
2010-04-12 14:44:30 +02:00
status = pNtOpenFile ( & dir , SYNCHRONIZE | FILE_LIST_DIRECTORY , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ) ;
2009-12-01 17:38:39 +01:00
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
2009-12-09 11:45:49 +01:00
pRtlFreeUnicodeString ( & nameW ) ;
2009-12-01 17:38:39 +01:00
2009-12-09 23:34:45 +01:00
path [ 3 ] = 0 ; /* root of the drive */
pRtlDosPathNameToNtPathName_U ( path , & nameW , NULL , NULL ) ;
status = pNtOpenFile ( & root , GENERIC_READ , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_DIRECTORY_FILE ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
pRtlFreeUnicodeString ( & nameW ) ;
2009-12-01 17:38:39 +01:00
/* test opening system dir with RootDirectory set to windows dir */
GetSystemDirectoryW ( path , MAX_PATH ) ;
while ( path [ len ] = = ' \\ ' ) len + + ;
nameW . Buffer = path + len ;
nameW . Length = lstrlenW ( path + len ) * sizeof ( WCHAR ) ;
attr . RootDirectory = dir ;
status = pNtOpenFile ( & handle , GENERIC_READ , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_DIRECTORY_FILE ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
CloseHandle ( handle ) ;
/* try uppercase name */
for ( i = len ; path [ i ] ; i + + ) if ( path [ i ] > = ' a ' & & path [ i ] < = ' z ' ) path [ i ] - = ' a ' - ' A ' ;
status = pNtOpenFile ( & handle , GENERIC_READ , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_DIRECTORY_FILE ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
CloseHandle ( handle ) ;
/* try with leading backslash */
nameW . Buffer - - ;
nameW . Length + = sizeof ( WCHAR ) ;
status = pNtOpenFile ( & handle , GENERIC_READ , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_DIRECTORY_FILE ) ;
2009-12-04 12:06:40 +01:00
ok ( status = = STATUS_INVALID_PARAMETER | |
status = = STATUS_OBJECT_NAME_INVALID | |
status = = STATUS_OBJECT_PATH_SYNTAX_BAD ,
2009-12-01 17:38:39 +01:00
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
if ( ! status ) CloseHandle ( handle ) ;
/* try with empty name */
nameW . Length = 0 ;
status = pNtOpenFile ( & handle , GENERIC_READ , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_DIRECTORY_FILE ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
CloseHandle ( handle ) ;
2009-12-02 17:36:58 +01:00
/* try open by file id */
while ( ! pNtQueryDirectoryFile ( dir , NULL , NULL , NULL , & io , data , sizeof ( data ) ,
2010-04-12 14:52:50 +02:00
FileIdBothDirectoryInformation , TRUE , NULL , restart ) )
2009-12-02 17:36:58 +01:00
{
FILE_ID_BOTH_DIRECTORY_INFORMATION * info = ( FILE_ID_BOTH_DIRECTORY_INFORMATION * ) data ;
restart = FALSE ;
2010-04-12 14:52:50 +02:00
if ( ! info - > FileId . QuadPart ) continue ;
nameW . Buffer = ( WCHAR * ) & info - > FileId ;
nameW . Length = sizeof ( info - > FileId ) ;
info - > FileName [ info - > FileNameLength / sizeof ( WCHAR ) ] = 0 ;
attr . RootDirectory = dir ;
2010-04-12 15:10:24 +02:00
/* We skip 'open' files by not specifying FILE_SHARE_WRITE */
2010-04-12 14:52:50 +02:00
status = pNtOpenFile ( & handle , GENERIC_READ , & attr , & io ,
2010-04-12 15:10:24 +02:00
FILE_SHARE_READ ,
2010-04-12 14:52:50 +02:00
FILE_OPEN_BY_FILE_ID |
( ( info - > FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ? FILE_DIRECTORY_FILE : 0 ) ) ;
2010-04-12 15:10:24 +02:00
ok ( status = = STATUS_SUCCESS | | status = = STATUS_ACCESS_DENIED | | status = = STATUS_NOT_IMPLEMENTED | | status = = STATUS_SHARING_VIOLATION ,
2010-04-12 14:52:50 +02:00
" open %s failed %x \n " , wine_dbgstr_w ( info - > FileName ) , status ) ;
if ( status = = STATUS_NOT_IMPLEMENTED )
{
win_skip ( " FILE_OPEN_BY_FILE_ID not supported \n " ) ;
break ;
}
2010-04-12 15:10:24 +02:00
if ( status = = STATUS_SHARING_VIOLATION )
trace ( " %s is currently open \n " , wine_dbgstr_w ( info - > FileName ) ) ;
2010-04-12 14:52:50 +02:00
if ( ! status )
2009-12-02 17:36:58 +01:00
{
2010-04-12 14:59:58 +02:00
BYTE buf [ sizeof ( FILE_ALL_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ] ;
2010-04-12 14:52:50 +02:00
2010-04-12 14:59:58 +02:00
if ( ! pNtQueryInformationFile ( handle , & io , buf , sizeof ( buf ) , FileAllInformation ) )
2010-04-12 14:52:50 +02:00
{
2010-04-12 14:59:58 +02:00
FILE_ALL_INFORMATION * fai = ( FILE_ALL_INFORMATION * ) buf ;
2010-04-12 15:10:24 +02:00
/* check that it's the same file/directory */
/* don't check the size for directories */
if ( ! ( info - > FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
ok ( info - > EndOfFile . QuadPart = = fai - > StandardInformation . EndOfFile . QuadPart ,
" mismatched file size for %s \n " , wine_dbgstr_w ( info - > FileName ) ) ;
ok ( info - > CreationTime . QuadPart = = fai - > BasicInformation . CreationTime . QuadPart ,
" mismatched creation time for %s \n " , wine_dbgstr_w ( info - > FileName ) ) ;
2010-04-12 14:52:50 +02:00
}
CloseHandle ( handle ) ;
/* try same thing from drive root */
attr . RootDirectory = root ;
2009-12-02 17:36:58 +01:00
status = pNtOpenFile ( & handle , GENERIC_READ , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN_BY_FILE_ID |
( ( info - > FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ? FILE_DIRECTORY_FILE : 0 ) ) ;
2010-04-12 14:52:50 +02:00
ok ( status = = STATUS_SUCCESS | | status = = STATUS_NOT_IMPLEMENTED ,
2009-12-02 17:36:58 +01:00
" open %s failed %x \n " , wine_dbgstr_w ( info - > FileName ) , status ) ;
2010-04-12 14:52:50 +02:00
if ( ! status ) CloseHandle ( handle ) ;
2009-12-02 17:36:58 +01:00
}
}
2009-12-01 17:38:39 +01:00
CloseHandle ( dir ) ;
2009-12-09 23:34:45 +01:00
CloseHandle ( root ) ;
2009-12-01 17:38:39 +01:00
}
2008-08-31 13:54:03 +02:00
static void delete_file_test ( void )
{
NTSTATUS ret ;
OBJECT_ATTRIBUTES attr ;
UNICODE_STRING nameW ;
WCHAR pathW [ MAX_PATH ] ;
WCHAR pathsubW [ MAX_PATH ] ;
static const WCHAR testdirW [ ] = { ' n ' , ' t ' , ' d ' , ' e ' , ' l ' , ' e ' , ' t ' , ' e ' , ' f ' , ' i ' , ' l ' , ' e ' , 0 } ;
static const WCHAR subdirW [ ] = { ' \\ ' , ' s ' , ' u ' , ' b ' , 0 } ;
ret = GetTempPathW ( MAX_PATH , pathW ) ;
if ( ! ret )
{
ok ( 0 , " couldn't get temp dir \n " ) ;
return ;
}
if ( ret + sizeof ( testdirW ) / sizeof ( WCHAR ) - 1 + sizeof ( subdirW ) / sizeof ( WCHAR ) - 1 > = MAX_PATH )
{
ok ( 0 , " MAX_PATH exceeded in constructing paths \n " ) ;
return ;
}
lstrcatW ( pathW , testdirW ) ;
lstrcpyW ( pathsubW , pathW ) ;
lstrcatW ( pathsubW , subdirW ) ;
ret = CreateDirectoryW ( pathW , NULL ) ;
ok ( ret = = TRUE , " couldn't create directory ntdeletefile \n " ) ;
if ( ! pRtlDosPathNameToNtPathName_U ( pathW , & nameW , NULL , NULL ) )
{
ok ( 0 , " RtlDosPathNametoNtPathName_U failed \n " ) ;
return ;
}
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = 0 ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . ObjectName = & nameW ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
/* test NtDeleteFile on an empty directory */
ret = pNtDeleteFile ( & attr ) ;
ok ( ret = = STATUS_SUCCESS , " NtDeleteFile should succeed in removing an empty directory \n " ) ;
ret = RemoveDirectoryW ( pathW ) ;
ok ( ret = = FALSE , " expected to fail removing directory, NtDeleteFile should have removed it \n " ) ;
/* test NtDeleteFile on a non-empty directory */
ret = CreateDirectoryW ( pathW , NULL ) ;
ok ( ret = = TRUE , " couldn't create directory ntdeletefile ?! \n " ) ;
ret = CreateDirectoryW ( pathsubW , NULL ) ;
ok ( ret = = TRUE , " couldn't create directory subdir \n " ) ;
ret = pNtDeleteFile ( & attr ) ;
ok ( ret = = STATUS_SUCCESS , " expected NtDeleteFile to ret STATUS_SUCCESS \n " ) ;
ret = RemoveDirectoryW ( pathsubW ) ;
ok ( ret = = TRUE , " expected to remove directory ntdeletefile \\ sub \n " ) ;
ret = RemoveDirectoryW ( pathW ) ;
ok ( ret = = TRUE , " expected to remove directory ntdeletefile, NtDeleteFile failed. \n " ) ;
pRtlFreeUnicodeString ( & nameW ) ;
}
2007-04-09 12:23:13 +02:00
static void read_file_test ( void )
{
const char text [ ] = " foobar " ;
HANDLE handle , read , write ;
NTSTATUS status ;
2009-08-14 00:56:23 +02:00
IO_STATUS_BLOCK iosb , iosb2 ;
2007-04-09 12:23:13 +02:00
DWORD written ;
int apc_count = 0 ;
char buffer [ 128 ] ;
LARGE_INTEGER offset ;
HANDLE event = CreateEventA ( NULL , TRUE , FALSE , NULL ) ;
2010-12-28 21:10:40 +01:00
BOOL ret ;
2007-04-09 12:23:13 +02:00
2007-11-11 14:56:50 +01:00
buffer [ 0 ] = 1 ;
2007-04-09 12:23:13 +02:00
if ( ! create_pipe ( & read , & write , FILE_FLAG_OVERLAPPED , 4096 ) ) return ;
/* try read with no data */
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
ok ( is_signaled ( read ) , " read handle is not signaled \n " ) ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 1 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( read ) , " read handle is signaled \n " ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
WriteFile ( write , buffer , 1 , & written , NULL ) ;
/* iosb updated here by async i/o */
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( U ( iosb ) . Status = = 0 , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 1 , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! is_signaled ( read ) , " read handle is signaled \n " ) ;
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
apc_count = 0 ;
SleepEx ( 1 , FALSE ) ; /* non-alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc not called \n " ) ;
/* with no event, the pipe handle itself gets signaled */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
ok ( ! is_signaled ( read ) , " read handle is not signaled \n " ) ;
status = pNtReadFile ( read , 0 , apc , & apc_count , & iosb , buffer , 1 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( read ) , " read handle is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
WriteFile ( write , buffer , 1 , & written , NULL ) ;
/* iosb updated here by async i/o */
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( U ( iosb ) . Status = = 0 , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 1 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( read ) , " read handle is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
apc_count = 0 ;
SleepEx ( 1 , FALSE ) ; /* non-alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc not called \n " ) ;
/* now read with data ready */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
ResetEvent ( event ) ;
WriteFile ( write , buffer , 1 , & written , NULL ) ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 1 , NULL , NULL ) ;
ok ( status = = STATUS_SUCCESS , " wrong status %x \n " , status ) ;
ok ( U ( iosb ) . Status = = 0 , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 1 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , FALSE ) ; /* non-alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc not called \n " ) ;
/* try read with no data */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
ok ( is_signaled ( event ) , " event is not signaled \n " ) ; /* check that read resets the event */
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 2 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
WriteFile ( write , buffer , 1 , & written , NULL ) ;
/* partial read is good enough */
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0 , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 1 , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
/* read from disconnected pipe */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
CloseHandle ( write ) ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 1 , NULL , NULL ) ;
ok ( status = = STATUS_PIPE_BROKEN , " wrong status %x \n " , status ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
CloseHandle ( read ) ;
/* read from closed handle */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
SetEvent ( event ) ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 1 , NULL , NULL ) ;
ok ( status = = STATUS_INVALID_HANDLE , " wrong status %x \n " , status ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ; /* not reset on invalid handle */
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
/* disconnect while async read is in progress */
if ( ! create_pipe ( & read , & write , FILE_FLAG_OVERLAPPED , 4096 ) ) return ;
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 2 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
CloseHandle ( write ) ;
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( U ( iosb ) . Status = = STATUS_PIPE_BROKEN , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
CloseHandle ( read ) ;
2009-08-14 00:56:23 +02:00
if ( ! create_pipe ( & read , & write , FILE_FLAG_OVERLAPPED , 4096 ) ) return ;
2010-12-28 21:10:40 +01:00
ret = DuplicateHandle ( GetCurrentProcess ( ) , read , GetCurrentProcess ( ) , & handle , 0 , TRUE , DUPLICATE_SAME_ACCESS ) ;
ok ( ret , " Failed to duplicate handle: %d \n " , GetLastError ( ) ) ;
2009-08-14 00:56:23 +02:00
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
status = pNtReadFile ( handle , event , apc , & apc_count , & iosb , buffer , 2 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
/* Cancel by other handle */
status = pNtCancelIoFile ( read , & iosb2 ) ;
ok ( status = = STATUS_SUCCESS , " failed to cancel by different handle: %x \n " , status ) ;
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( U ( iosb ) . Status = = STATUS_CANCELLED , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
todo_wine ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 2 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
/* Close queued handle */
CloseHandle ( read ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
status = pNtCancelIoFile ( read , & iosb2 ) ;
ok ( status = = STATUS_INVALID_HANDLE , " cancelled by closed handle? \n " ) ;
status = pNtCancelIoFile ( handle , & iosb2 ) ;
ok ( status = = STATUS_SUCCESS , " failed to cancel: %x \n " , status ) ;
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( U ( iosb ) . Status = = STATUS_CANCELLED , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
todo_wine ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( write ) ;
2009-08-08 22:32:34 +02:00
if ( pNtCancelIoFileEx )
{
2009-08-14 00:56:23 +02:00
/* Basic Cancel Ex */
2009-08-08 22:32:34 +02:00
if ( ! create_pipe ( & read , & write , FILE_FLAG_OVERLAPPED , 4096 ) ) return ;
2009-08-14 00:56:23 +02:00
2009-08-08 22:32:34 +02:00
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 2 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
status = pNtCancelIoFileEx ( read , & iosb , & iosb2 ) ;
ok ( status = = STATUS_SUCCESS , " Failed to cancel I/O \n " ) ;
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( U ( iosb ) . Status = = STATUS_CANCELLED , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
2009-08-09 06:11:30 +02:00
todo_wine ok ( ! apc_count , " apc was called \n " ) ;
2009-08-08 22:32:34 +02:00
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
2009-08-14 00:56:23 +02:00
/* Duplicate iosb */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 2 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
status = pNtReadFile ( read , event , apc , & apc_count , & iosb , buffer , 2 , NULL , NULL ) ;
ok ( status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! apc_count , " apc was called \n " ) ;
status = pNtCancelIoFileEx ( read , & iosb , & iosb2 ) ;
ok ( status = = STATUS_SUCCESS , " Failed to cancel I/O \n " ) ;
Sleep ( 1 ) ; /* FIXME: needed for wine to run the i/o apc */
ok ( U ( iosb ) . Status = = STATUS_CANCELLED , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
todo_wine ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 2 , " apc was not called \n " ) ;
2009-08-08 22:32:34 +02:00
CloseHandle ( read ) ;
CloseHandle ( write ) ;
}
2007-04-09 12:23:13 +02:00
/* now try a real file */
if ( ! ( handle = create_temp_file ( FILE_FLAG_OVERLAPPED ) ) ) return ;
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = 0 ;
ResetEvent ( event ) ;
2009-08-10 19:17:52 +02:00
status = pNtWriteFile ( handle , event , apc , & apc_count , & iosb , text , strlen ( text ) , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS | | status = = STATUS_PENDING , " wrong status %x \n " , status ) ;
2007-04-09 12:23:13 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = strlen ( text ) , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = 0 ;
ResetEvent ( event ) ;
status = pNtReadFile ( handle , event , apc , & apc_count , & iosb , buffer , strlen ( text ) + 10 , & offset , NULL ) ;
2008-09-11 14:18:46 +02:00
ok ( status = = STATUS_SUCCESS | |
status = = STATUS_PENDING , /* vista */
" wrong status %x \n " , status ) ;
2007-04-09 12:23:13 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = strlen ( text ) , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
/* read beyond eof */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = strlen ( text ) + 2 ;
status = pNtReadFile ( handle , event , apc , & apc_count , & iosb , buffer , 2 , & offset , NULL ) ;
2008-09-11 14:18:46 +02:00
if ( status = = STATUS_PENDING ) /* vista */
{
ok ( U ( iosb ) . Status = = STATUS_END_OF_FILE , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0 , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
}
else
{
ok ( status = = STATUS_END_OF_FILE , " wrong status %x \n " , status ) ;
ok ( U ( iosb ) . Status = = 0xdeadbabe , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = 0xdeadbeef , " wrong info %lu \n " , iosb . Information ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
}
2007-04-09 12:23:13 +02:00
CloseHandle ( handle ) ;
/* now a non-overlapped file */
if ( ! ( handle = create_temp_file ( 0 ) ) ) return ;
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = 0 ;
2009-08-10 19:17:52 +02:00
status = pNtWriteFile ( handle , event , apc , & apc_count , & iosb , text , strlen ( text ) , & offset , NULL ) ;
2008-09-11 14:18:46 +02:00
ok ( status = = STATUS_END_OF_FILE | |
2009-08-10 19:17:52 +02:00
status = = STATUS_SUCCESS | |
2008-09-11 14:18:46 +02:00
status = = STATUS_PENDING , /* vista */
" wrong status %x \n " , status ) ;
2007-04-09 12:23:13 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = strlen ( text ) , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = 0 ;
ResetEvent ( event ) ;
status = pNtReadFile ( handle , event , apc , & apc_count , & iosb , buffer , strlen ( text ) + 10 , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " wrong status %x \n " , status ) ;
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " wrong status %x \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = strlen ( text ) , " wrong info %lu \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
todo_wine ok ( ! apc_count , " apc was called \n " ) ;
/* read beyond eof */
apc_count = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = strlen ( text ) + 2 ;
ResetEvent ( event ) ;
status = pNtReadFile ( handle , event , apc , & apc_count , & iosb , buffer , 2 , & offset , NULL ) ;
ok ( status = = STATUS_END_OF_FILE , " wrong status %x \n " , status ) ;
todo_wine ok ( U ( iosb ) . Status = = STATUS_END_OF_FILE , " wrong status %x \n " , U ( iosb ) . Status ) ;
todo_wine ok ( iosb . Information = = 0 , " wrong info %lu \n " , iosb . Information ) ;
todo_wine ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( event ) ;
}
2011-01-12 01:09:32 +01:00
static void append_file_test ( void )
{
const char text [ ] = " foobar " ;
HANDLE handle ;
NTSTATUS status ;
IO_STATUS_BLOCK iosb ;
DWORD written ;
char buffer [ 128 ] ;
GetTempFileNameA ( " . " , " foo " , 0 , buffer ) ;
/* It is possible to open a file with only FILE_APPEND_DATA access flags.
It matches the O_WRONLY | O_APPEND open ( ) posix behavior */
handle = CreateFileA ( buffer , FILE_APPEND_DATA , 0 , NULL , CREATE_ALWAYS ,
FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " Failed to create a temp file in FILE_APPEND_DATA mode. \n " ) ;
if ( handle = = INVALID_HANDLE_VALUE )
{
skip ( " Couldn't create a temporary file, skipping FILE_APPEND_DATA test \n " ) ;
return ;
}
2011-01-15 20:10:26 +01:00
U ( iosb ) . Status = STATUS_PENDING ;
2011-01-12 01:09:32 +01:00
iosb . Information = 0 ;
status = NtWriteFile ( handle , NULL , NULL , NULL , & iosb ,
text , sizeof ( text ) , NULL , NULL ) ;
if ( status = = STATUS_PENDING )
{
WaitForSingleObject ( handle , INFINITE ) ;
2011-01-15 20:10:26 +01:00
status = U ( iosb ) . Status ;
2011-01-12 01:09:32 +01:00
}
written = iosb . Information ;
todo_wine
ok ( status = = STATUS_SUCCESS & & written = = sizeof ( text ) , " FILE_APPEND_DATA NtWriteFile failed \n " ) ;
CloseHandle ( handle ) ;
}
2007-02-27 13:41:55 +01:00
static void nt_mailslot_test ( void )
{
HANDLE hslot ;
ACCESS_MASK DesiredAccess ;
OBJECT_ATTRIBUTES attr ;
ULONG CreateOptions ;
ULONG MailslotQuota ;
ULONG MaxMessageSize ;
LARGE_INTEGER TimeOut ;
IO_STATUS_BLOCK IoStatusBlock ;
NTSTATUS rc ;
UNICODE_STRING str ;
WCHAR buffer1 [ ] = { ' \\ ' , ' ? ' , ' ? ' , ' \\ ' , ' M ' , ' A ' , ' I ' , ' L ' , ' S ' , ' L ' , ' O ' , ' T ' , ' \\ ' ,
' R ' , ' : ' , ' \\ ' , ' F ' , ' R ' , ' E ' , ' D ' , ' \0 ' } ;
2007-02-27 13:42:02 +01:00
TimeOut . QuadPart = - 1 ;
2007-02-27 13:41:55 +01:00
pRtlInitUnicodeString ( & str , buffer1 ) ;
InitializeObjectAttributes ( & attr , & str , OBJ_CASE_INSENSITIVE , 0 , NULL ) ;
2008-05-13 20:35:36 +02:00
CreateOptions = MailslotQuota = MaxMessageSize = 0 ;
DesiredAccess = GENERIC_READ ;
2007-02-27 13:42:02 +01:00
/*
* Check for NULL pointer handling
*/
rc = pNtCreateMailslotFile ( NULL , DesiredAccess ,
& attr , & IoStatusBlock , CreateOptions , MailslotQuota , MaxMessageSize ,
& TimeOut ) ;
2008-05-13 20:35:36 +02:00
ok ( rc = = STATUS_ACCESS_VIOLATION | |
rc = = STATUS_INVALID_PARAMETER , /* win2k3 */
" rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER \n " , rc ) ;
2007-02-27 13:41:55 +01:00
2007-02-27 13:42:06 +01:00
/*
* Test to see if the Timeout can be NULL
*/
2008-05-13 20:35:36 +02:00
hslot = ( HANDLE ) 0xdeadbeef ;
2007-02-27 13:42:06 +01:00
rc = pNtCreateMailslotFile ( & hslot , DesiredAccess ,
& attr , & IoStatusBlock , CreateOptions , MailslotQuota , MaxMessageSize ,
NULL ) ;
2008-05-13 20:35:36 +02:00
ok ( rc = = STATUS_SUCCESS | |
rc = = STATUS_INVALID_PARAMETER , /* win2k3 */
" rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER \n " , rc ) ;
2007-02-27 13:42:06 +01:00
ok ( hslot ! = 0 , " Handle is invalid \n " ) ;
if ( rc = = STATUS_SUCCESS ) rc = pNtClose ( hslot ) ;
2007-02-27 13:42:10 +01:00
/*
* Test that the length field is checked properly
*/
attr . Length = 0 ;
rc = pNtCreateMailslotFile ( & hslot , DesiredAccess ,
& attr , & IoStatusBlock , CreateOptions , MailslotQuota , MaxMessageSize ,
& TimeOut ) ;
todo_wine ok ( rc = = STATUS_INVALID_PARAMETER , " rc = %x not c000000d STATUS_INVALID_PARAMETER \n " , rc ) ;
if ( rc = = STATUS_SUCCESS ) pNtClose ( hslot ) ;
attr . Length = sizeof ( OBJECT_ATTRIBUTES ) + 1 ;
rc = pNtCreateMailslotFile ( & hslot , DesiredAccess ,
& attr , & IoStatusBlock , CreateOptions , MailslotQuota , MaxMessageSize ,
& TimeOut ) ;
todo_wine ok ( rc = = STATUS_INVALID_PARAMETER , " rc = %x not c000000d STATUS_INVALID_PARAMETER \n " , rc ) ;
if ( rc = = STATUS_SUCCESS ) pNtClose ( hslot ) ;
/*
* Test handling of a NULL unicode string in ObjectName
*/
InitializeObjectAttributes ( & attr , & str , OBJ_CASE_INSENSITIVE , 0 , NULL ) ;
attr . ObjectName = NULL ;
rc = pNtCreateMailslotFile ( & hslot , DesiredAccess ,
& attr , & IoStatusBlock , CreateOptions , MailslotQuota , MaxMessageSize ,
& TimeOut ) ;
2008-05-13 20:35:36 +02:00
ok ( rc = = STATUS_OBJECT_PATH_SYNTAX_BAD | |
rc = = STATUS_INVALID_PARAMETER ,
" rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER \n " , rc ) ;
2007-02-27 13:42:10 +01:00
if ( rc = = STATUS_SUCCESS ) pNtClose ( hslot ) ;
2007-02-27 13:41:55 +01:00
/*
* Test a valid call
*/
2007-02-27 13:42:10 +01:00
InitializeObjectAttributes ( & attr , & str , OBJ_CASE_INSENSITIVE , 0 , NULL ) ;
2007-02-27 13:41:55 +01:00
rc = pNtCreateMailslotFile ( & hslot , DesiredAccess ,
& attr , & IoStatusBlock , CreateOptions , MailslotQuota , MaxMessageSize ,
& TimeOut ) ;
2008-05-13 20:35:36 +02:00
ok ( rc = = STATUS_SUCCESS , " Create MailslotFile failed rc = %x \n " , rc ) ;
2007-02-27 13:41:55 +01:00
ok ( hslot ! = 0 , " Handle is invalid \n " ) ;
rc = pNtClose ( hslot ) ;
ok ( rc = = STATUS_SUCCESS , " NtClose failed \n " ) ;
}
2007-11-09 23:11:31 +01:00
static void test_iocp_setcompletion ( HANDLE h )
{
NTSTATUS res ;
2010-04-21 11:00:26 +02:00
ULONG count ;
2007-11-09 23:11:31 +01:00
res = pNtSetIoCompletion ( h , CKEY_FIRST , CVALUE_FIRST , STATUS_INVALID_DEVICE_REQUEST , 3 ) ;
ok ( res = = STATUS_SUCCESS , " NtSetIoCompletion failed: %x \n " , res ) ;
count = get_pending_msgs ( h ) ;
2010-04-21 11:00:26 +02:00
ok ( count = = 1 , " Unexpected msg count: %d \n " , count ) ;
2007-11-09 23:11:31 +01:00
if ( get_msg ( h ) )
{
ok ( completionKey = = CKEY_FIRST , " Invalid completion key: %lx \n " , completionKey ) ;
ok ( ioSb . Information = = 3 , " Invalid ioSb.Information: %ld \n " , ioSb . Information ) ;
ok ( U ( ioSb ) . Status = = STATUS_INVALID_DEVICE_REQUEST , " Invalid ioSb.Status: %x \n " , U ( ioSb ) . Status ) ;
ok ( completionValue = = CVALUE_FIRST , " Invalid completion value: %lx \n " , completionValue ) ;
}
count = get_pending_msgs ( h ) ;
2010-04-21 11:00:26 +02:00
ok ( ! count , " Unexpected msg count: %d \n " , count ) ;
2007-11-09 23:11:31 +01:00
}
static void test_iocp_fileio ( HANDLE h )
{
static const char pipe_name [ ] = " \\ \\ . \\ pipe \\ iocompletiontestnamedpipe " ;
2007-12-17 00:02:12 +01:00
IO_STATUS_BLOCK iosb ;
FILE_COMPLETION_INFORMATION fci = { h , CKEY_SECOND } ;
HANDLE hPipeSrv , hPipeClt ;
NTSTATUS res ;
hPipeSrv = CreateNamedPipeA ( pipe_name , PIPE_ACCESS_INBOUND , PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT , 4 , 1024 , 1024 , 1000 , NULL ) ;
ok ( hPipeSrv ! = INVALID_HANDLE_VALUE , " Cannot create named pipe \n " ) ;
if ( hPipeSrv ! = INVALID_HANDLE_VALUE )
{
hPipeClt = CreateFileA ( pipe_name , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED , NULL ) ;
ok ( hPipeClt ! = INVALID_HANDLE_VALUE , " Cannot connect to pipe \n " ) ;
if ( hPipeClt ! = INVALID_HANDLE_VALUE )
{
2010-07-27 22:20:35 +02:00
U ( iosb ) . Status = 0xdeadbeef ;
2007-12-17 00:02:12 +01:00
res = pNtSetInformationFile ( hPipeSrv , & iosb , & fci , sizeof ( fci ) , FileCompletionInformation ) ;
ok ( res = = STATUS_INVALID_PARAMETER , " Unexpected NtSetInformationFile on non-overlapped handle: %x \n " , res ) ;
2010-07-27 22:20:35 +02:00
ok ( U ( iosb ) . Status = = STATUS_INVALID_PARAMETER /* 98 */ | | U ( iosb ) . Status = = 0xdeadbeef /* NT4+ */ ,
" Unexpected iosb.Status on non-overlapped handle: %x \n " , U ( iosb ) . Status ) ;
2007-12-17 00:02:12 +01:00
CloseHandle ( hPipeClt ) ;
}
CloseHandle ( hPipeSrv ) ;
}
hPipeSrv = CreateNamedPipeA ( pipe_name , PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED , PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT , 4 , 1024 , 1024 , 1000 , NULL ) ;
ok ( hPipeSrv ! = INVALID_HANDLE_VALUE , " Cannot create named pipe \n " ) ;
if ( hPipeSrv = = INVALID_HANDLE_VALUE )
return ;
hPipeClt = CreateFileA ( pipe_name , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED , NULL ) ;
ok ( hPipeClt ! = INVALID_HANDLE_VALUE , " Cannot connect to pipe \n " ) ;
if ( hPipeClt ! = INVALID_HANDLE_VALUE )
2007-11-09 23:11:31 +01:00
{
OVERLAPPED o = { 0 , } ;
2008-06-02 22:14:26 +02:00
BYTE send_buf [ TEST_BUF_LEN ] , recv_buf [ TEST_BUF_LEN ] ;
2007-11-09 23:11:31 +01:00
DWORD read ;
long count ;
2010-07-27 22:20:35 +02:00
U ( iosb ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( hPipeSrv , & iosb , & fci , sizeof ( fci ) , FileCompletionInformation ) ;
2007-11-09 23:11:31 +01:00
ok ( res = = STATUS_SUCCESS , " NtSetInformationFile failed: %x \n " , res ) ;
2007-11-20 13:48:15 +01:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " iosb.Status invalid: %x \n " , U ( iosb ) . Status ) ;
2007-11-09 23:11:31 +01:00
2008-06-02 22:14:26 +02:00
memset ( send_buf , 0 , TEST_BUF_LEN ) ;
memset ( recv_buf , 0xde , TEST_BUF_LEN ) ;
2007-11-09 23:11:31 +01:00
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
2008-06-02 22:14:26 +02:00
ReadFile ( hPipeSrv , recv_buf , TEST_BUF_LEN , & read , & o ) ;
2007-11-09 23:11:31 +01:00
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
2008-06-02 22:14:26 +02:00
WriteFile ( hPipeClt , send_buf , TEST_BUF_LEN , & read , NULL ) ;
2007-11-09 23:11:31 +01:00
if ( get_msg ( h ) )
{
ok ( completionKey = = CKEY_SECOND , " Invalid completion key: %lx \n " , completionKey ) ;
ok ( ioSb . Information = = 3 , " Invalid ioSb.Information: %ld \n " , ioSb . Information ) ;
ok ( U ( ioSb ) . Status = = STATUS_SUCCESS , " Invalid ioSb.Status: %x \n " , U ( ioSb ) . Status ) ;
ok ( completionValue = = ( ULONG_PTR ) & o , " Invalid completion value: %lx \n " , completionValue ) ;
2008-06-02 22:14:26 +02:00
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 ] ) ;
2007-11-09 23:11:31 +01:00
}
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
2008-06-02 22:14:26 +02:00
memset ( send_buf , 0 , TEST_BUF_LEN ) ;
memset ( recv_buf , 0xde , TEST_BUF_LEN ) ;
WriteFile ( hPipeClt , send_buf , 2 , & read , NULL ) ;
2007-11-09 23:11:31 +01:00
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
2008-06-02 22:14:26 +02:00
ReadFile ( hPipeSrv , recv_buf , 2 , & read , & o ) ;
2007-11-09 23:11:31 +01:00
count = get_pending_msgs ( h ) ;
ok ( count = = 1 , " Unexpected msg count: %ld \n " , count ) ;
if ( get_msg ( h ) )
{
ok ( completionKey = = CKEY_SECOND , " Invalid completion key: %lx \n " , completionKey ) ;
ok ( ioSb . Information = = 2 , " Invalid ioSb.Information: %ld \n " , ioSb . Information ) ;
ok ( U ( ioSb ) . Status = = STATUS_SUCCESS , " Invalid ioSb.Status: %x \n " , U ( ioSb ) . Status ) ;
ok ( completionValue = = ( ULONG_PTR ) & o , " Invalid completion value: %lx \n " , completionValue ) ;
2008-06-02 22:14:26 +02:00
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 ] ) ;
2007-11-09 23:11:31 +01:00
}
2007-12-17 20:06:17 +01:00
2008-06-02 22:14:26 +02:00
ReadFile ( hPipeSrv , recv_buf , TEST_BUF_LEN , & read , & o ) ;
2007-12-17 20:06:17 +01:00
CloseHandle ( hPipeSrv ) ;
count = get_pending_msgs ( h ) ;
ok ( count = = 1 , " Unexpected msg count: %ld \n " , count ) ;
if ( get_msg ( h ) )
{
ok ( completionKey = = CKEY_SECOND , " Invalid completion key: %lx \n " , completionKey ) ;
ok ( ioSb . Information = = 0 , " Invalid ioSb.Information: %ld \n " , ioSb . Information ) ;
/* wine sends wrong status here */
todo_wine ok ( U ( ioSb ) . Status = = STATUS_PIPE_BROKEN , " Invalid ioSb.Status: %x \n " , U ( ioSb ) . Status ) ;
ok ( completionValue = = ( ULONG_PTR ) & o , " Invalid completion value: %lx \n " , completionValue ) ;
}
2007-11-09 23:11:31 +01:00
}
CloseHandle ( hPipeClt ) ;
}
2009-09-09 14:41:30 +02:00
static void test_file_basic_information ( void )
{
IO_STATUS_BLOCK io ;
FILE_BASIC_INFORMATION fbi ;
HANDLE h ;
int res ;
2009-09-24 18:51:42 +02:00
int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL ;
2009-09-09 14:41:30 +02:00
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
/* Check default first */
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
res = pNtQueryInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes, res %x \n " , res ) ;
2009-09-11 16:38:31 +02:00
ok ( ( fbi . FileAttributes & FILE_ATTRIBUTE_ARCHIVE ) = = FILE_ATTRIBUTE_ARCHIVE ,
" attribute %x not expected \n " , fbi . FileAttributes ) ;
2009-09-09 14:41:30 +02:00
/* Then SYSTEM */
/* Clear fbi to avoid setting times */
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
fbi . FileAttributes = FILE_ATTRIBUTE_SYSTEM ;
2010-07-27 22:20:35 +02:00
U ( io ) . Status = 0xdeadbeef ;
2009-09-09 14:41:30 +02:00
res = pNtSetInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
2010-07-27 22:20:35 +02:00
ok ( res = = STATUS_SUCCESS , " can't set system attribute, NtSetInformationFile returned %x \n " , res ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " can't set system attribute, io.Status is %x \n " , U ( io ) . Status ) ;
2009-09-09 14:41:30 +02:00
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
res = pNtQueryInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes \n " ) ;
2009-09-24 18:51:42 +02:00
todo_wine ok ( ( fbi . FileAttributes & attrib_mask ) = = FILE_ATTRIBUTE_SYSTEM , " attribute %x not FILE_ATTRIBUTE_SYSTEM \n " , fbi . FileAttributes ) ;
2009-09-09 14:41:30 +02:00
/* Then HIDDEN */
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
fbi . FileAttributes = FILE_ATTRIBUTE_HIDDEN ;
2010-07-27 22:20:35 +02:00
U ( io ) . Status = 0xdeadbeef ;
2009-09-09 14:41:30 +02:00
res = pNtSetInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
2010-07-27 22:20:35 +02:00
ok ( res = = STATUS_SUCCESS , " can't set system attribute, NtSetInformationFile returned %x \n " , res ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " can't set system attribute, io.Status is %x \n " , U ( io ) . Status ) ;
2009-09-09 14:41:30 +02:00
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
res = pNtQueryInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes \n " ) ;
2009-09-24 18:51:42 +02:00
todo_wine ok ( ( fbi . FileAttributes & attrib_mask ) = = FILE_ATTRIBUTE_HIDDEN , " attribute %x not FILE_ATTRIBUTE_HIDDEN \n " , fbi . FileAttributes ) ;
2009-09-09 14:41:30 +02:00
/* Check NORMAL last of all (to make sure we can clear attributes) */
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
fbi . FileAttributes = FILE_ATTRIBUTE_NORMAL ;
2010-07-27 22:20:35 +02:00
U ( io ) . Status = 0xdeadbeef ;
2009-09-09 14:41:30 +02:00
res = pNtSetInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
2010-07-27 22:20:35 +02:00
ok ( res = = STATUS_SUCCESS , " can't set normal attribute, NtSetInformationFile returned %x \n " , res ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " can't set normal attribute, io.Status is %x \n " , U ( io ) . Status ) ;
2009-09-09 14:41:30 +02:00
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
res = pNtQueryInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes \n " ) ;
2009-09-24 18:51:42 +02:00
todo_wine ok ( ( fbi . FileAttributes & attrib_mask ) = = FILE_ATTRIBUTE_NORMAL , " attribute %x not 0 \n " , fbi . FileAttributes ) ;
2009-09-09 14:41:30 +02:00
CloseHandle ( h ) ;
}
static void test_file_all_information ( void )
{
IO_STATUS_BLOCK io ;
/* FileAllInformation, like FileNameInformation, has a variable-length pathname
* buffer at the end . Vista objects with STATUS_BUFFER_OVERFLOW if you
* don ' t leave enough room there .
*/
struct {
FILE_ALL_INFORMATION fai ;
WCHAR buf [ 256 ] ;
} fai_buf ;
HANDLE h ;
int res ;
2009-09-24 18:51:42 +02:00
int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL ;
2009-09-09 14:41:30 +02:00
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
/* Check default first */
res = pNtQueryInformationFile ( h , & io , & fai_buf . fai , sizeof fai_buf , FileAllInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes, res %x \n " , res ) ;
2009-09-11 16:38:31 +02:00
ok ( ( fai_buf . fai . BasicInformation . FileAttributes & FILE_ATTRIBUTE_ARCHIVE ) = = FILE_ATTRIBUTE_ARCHIVE ,
" attribute %x not expected \n " , fai_buf . fai . BasicInformation . FileAttributes ) ;
2009-09-09 14:41:30 +02:00
/* Then SYSTEM */
/* Clear fbi to avoid setting times */
memset ( & fai_buf . fai . BasicInformation , 0 , sizeof ( fai_buf . fai . BasicInformation ) ) ;
fai_buf . fai . BasicInformation . FileAttributes = FILE_ATTRIBUTE_SYSTEM ;
2010-07-27 22:20:35 +02:00
U ( io ) . Status = 0xdeadbeef ;
2009-09-09 14:41:30 +02:00
res = pNtSetInformationFile ( h , & io , & fai_buf . fai , sizeof fai_buf , FileAllInformation ) ;
2010-07-27 22:20:35 +02:00
ok ( res = = STATUS_INVALID_INFO_CLASS | | broken ( res = = STATUS_NOT_IMPLEMENTED ) , " shouldn't be able to set FileAllInformation, res %x \n " , res ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " shouldn't be able to set FileAllInformation, io.Status is %x \n " , U ( io ) . Status ) ;
U ( io ) . Status = 0xdeadbeef ;
2009-09-09 14:41:30 +02:00
res = pNtSetInformationFile ( h , & io , & fai_buf . fai . BasicInformation , sizeof fai_buf . fai . BasicInformation , FileBasicInformation ) ;
2010-07-27 22:20:35 +02:00
ok ( res = = STATUS_SUCCESS , " can't set system attribute, res: %x \n " , res ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " can't set system attribute, io.Status: %x \n " , U ( io ) . Status ) ;
2009-09-09 14:41:30 +02:00
memset ( & fai_buf . fai , 0 , sizeof ( fai_buf . fai ) ) ;
res = pNtQueryInformationFile ( h , & io , & fai_buf . fai , sizeof fai_buf , FileAllInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes, res %x \n " , res ) ;
2009-09-24 18:51:42 +02:00
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 ) ;
2009-09-09 14:41:30 +02:00
/* Then HIDDEN */
memset ( & fai_buf . fai . BasicInformation , 0 , sizeof ( fai_buf . fai . BasicInformation ) ) ;
fai_buf . fai . BasicInformation . FileAttributes = FILE_ATTRIBUTE_HIDDEN ;
2010-07-27 22:20:35 +02:00
U ( io ) . Status = 0xdeadbeef ;
2009-09-09 14:41:30 +02:00
res = pNtSetInformationFile ( h , & io , & fai_buf . fai . BasicInformation , sizeof fai_buf . fai . BasicInformation , FileBasicInformation ) ;
2010-07-27 22:20:35 +02:00
ok ( res = = STATUS_SUCCESS , " can't set system attribute, res: %x \n " , res ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " can't set system attribute, io.Status: %x \n " , U ( io ) . Status ) ;
2009-09-09 14:41:30 +02:00
memset ( & fai_buf . fai , 0 , sizeof ( fai_buf . fai ) ) ;
res = pNtQueryInformationFile ( h , & io , & fai_buf . fai , sizeof fai_buf , FileAllInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes \n " ) ;
2009-09-24 18:51:42 +02:00
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 ) ;
2009-09-09 14:41:30 +02:00
/* Check NORMAL last of all (to make sure we can clear attributes) */
memset ( & fai_buf . fai . BasicInformation , 0 , sizeof ( fai_buf . fai . BasicInformation ) ) ;
fai_buf . fai . BasicInformation . FileAttributes = FILE_ATTRIBUTE_NORMAL ;
2010-07-27 22:20:35 +02:00
U ( io ) . Status = 0xdeadbeef ;
2009-09-09 14:41:30 +02:00
res = pNtSetInformationFile ( h , & io , & fai_buf . fai . BasicInformation , sizeof fai_buf . fai . BasicInformation , FileBasicInformation ) ;
2010-07-27 22:20:35 +02:00
ok ( res = = STATUS_SUCCESS , " can't set system attribute, res: %x \n " , res ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " can't set system attribute, io.Status: %x \n " , U ( io ) . Status ) ;
2009-09-09 14:41:30 +02:00
memset ( & fai_buf . fai , 0 , sizeof ( fai_buf . fai ) ) ;
res = pNtQueryInformationFile ( h , & io , & fai_buf . fai , sizeof fai_buf , FileAllInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes \n " ) ;
2009-09-24 18:51:42 +02:00
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 ) ;
2009-09-09 14:41:30 +02:00
CloseHandle ( h ) ;
}
static void test_file_both_information ( void )
{
IO_STATUS_BLOCK io ;
FILE_BOTH_DIR_INFORMATION fbi ;
HANDLE h ;
int res ;
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
memset ( & fbi , 0 , sizeof ( fbi ) ) ;
res = pNtQueryInformationFile ( h , & io , & fbi , sizeof fbi , FileBothDirectoryInformation ) ;
2009-09-24 18:51:42 +02:00
ok ( res = = STATUS_INVALID_INFO_CLASS | | res = = STATUS_NOT_IMPLEMENTED , " shouldn't be able to query FileBothDirectoryInformation, res %x \n " , res ) ;
2009-09-09 14:41:30 +02:00
CloseHandle ( h ) ;
}
2007-11-09 23:11:31 +01:00
static void test_iocompletion ( void )
{
HANDLE h = INVALID_HANDLE_VALUE ;
NTSTATUS res ;
res = pNtCreateIoCompletion ( & h , IO_COMPLETION_ALL_ACCESS , NULL , 0 ) ;
ok ( res = = 0 , " NtCreateIoCompletion anonymous failed: %x \n " , res ) ;
ok ( h & & h ! = INVALID_HANDLE_VALUE , " Invalid handle returned \n " ) ;
if ( h & & h ! = INVALID_HANDLE_VALUE )
{
test_iocp_setcompletion ( h ) ;
test_iocp_fileio ( h ) ;
pNtClose ( h ) ;
}
}
2009-11-12 15:10:14 +01:00
static void test_file_name_information ( void )
{
WCHAR * file_name , * volume_prefix , * expected ;
FILE_NAME_INFORMATION * info ;
2009-11-19 11:41:23 +01:00
ULONG old_redir = 1 , tmp ;
2009-11-12 15:10:14 +01:00
UINT file_name_size ;
IO_STATUS_BLOCK io ;
UINT info_size ;
HRESULT hr ;
HANDLE h ;
UINT len ;
2009-11-12 23:42:53 +01:00
/* GetVolumePathName is not present before w2k */
if ( ! pGetVolumePathNameW ) {
win_skip ( " GetVolumePathNameW not found \n " ) ;
return ;
}
2009-11-12 15:10:14 +01:00
file_name_size = GetSystemDirectoryW ( NULL , 0 ) ;
file_name = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * file_name ) ) ;
volume_prefix = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * volume_prefix ) ) ;
expected = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * volume_prefix ) ) ;
len = GetSystemDirectoryW ( file_name , file_name_size ) ;
ok ( len = = file_name_size - 1 ,
" GetSystemDirectoryW returned %u, expected %u. \n " ,
len , file_name_size - 1 ) ;
2009-11-12 23:42:53 +01:00
len = pGetVolumePathNameW ( file_name , volume_prefix , file_name_size ) ;
2009-11-12 15:10:14 +01:00
ok ( len , " GetVolumePathNameW failed. \n " ) ;
len = lstrlenW ( volume_prefix ) ;
if ( len & & volume_prefix [ len - 1 ] = = ' \\ ' ) - - len ;
memcpy ( expected , file_name + len , ( file_name_size - len - 1 ) * sizeof ( WCHAR ) ) ;
expected [ file_name_size - len - 1 ] = ' \0 ' ;
/* A bit more than we actually need, but it keeps the calculation simple. */
info_size = sizeof ( * info ) + ( file_name_size * sizeof ( WCHAR ) ) ;
info = HeapAlloc ( GetProcessHeap ( ) , 0 , info_size ) ;
2009-11-19 11:41:22 +01:00
if ( pRtlWow64EnableFsRedirectionEx ) pRtlWow64EnableFsRedirectionEx ( TRUE , & old_redir ) ;
2009-11-12 15:10:14 +01:00
h = CreateFileW ( file_name , GENERIC_READ ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
2009-11-19 11:41:22 +01:00
if ( pRtlWow64EnableFsRedirectionEx ) pRtlWow64EnableFsRedirectionEx ( old_redir , & tmp ) ;
2009-11-12 15:10:14 +01:00
ok ( h ! = INVALID_HANDLE_VALUE , " Failed to open file. \n " ) ;
2009-11-12 15:10:15 +01:00
hr = pNtQueryInformationFile ( h , & io , info , sizeof ( * info ) - 1 , FileNameInformation ) ;
ok ( hr = = STATUS_INFO_LENGTH_MISMATCH , " NtQueryInformationFile returned %#x. \n " , hr ) ;
2009-11-12 15:10:14 +01:00
memset ( info , 0xcc , info_size ) ;
hr = pNtQueryInformationFile ( h , & io , info , sizeof ( * info ) , FileNameInformation ) ;
ok ( hr = = STATUS_BUFFER_OVERFLOW , " NtQueryInformationFile returned %#x, expected %#x. \n " ,
hr , STATUS_BUFFER_OVERFLOW ) ;
ok ( U ( io ) . Status = = STATUS_BUFFER_OVERFLOW , " io.Status is %#x, expected %#x. \n " ,
U ( io ) . Status , STATUS_BUFFER_OVERFLOW ) ;
2009-12-09 12:19:48 +01:00
ok ( info - > FileNameLength = = lstrlenW ( expected ) * sizeof ( WCHAR ) , " info->FileNameLength is %u \n " , info - > FileNameLength ) ;
2009-11-12 15:10:14 +01:00
ok ( info - > FileName [ 2 ] = = 0xcccc , " info->FileName[2] is %#x, expected 0xcccc. \n " , info - > FileName [ 2 ] ) ;
ok ( CharLowerW ( ( LPWSTR ) ( UINT_PTR ) info - > FileName [ 1 ] ) = = CharLowerW ( ( LPWSTR ) ( UINT_PTR ) expected [ 1 ] ) ,
" info->FileName[1] is %p, expected %p. \n " ,
CharLowerW ( ( LPWSTR ) ( UINT_PTR ) info - > FileName [ 1 ] ) , CharLowerW ( ( LPWSTR ) ( UINT_PTR ) expected [ 1 ] ) ) ;
2009-12-09 12:19:48 +01:00
ok ( io . Information = = sizeof ( * info ) , " io.Information is %lu \n " , io . Information ) ;
2009-11-12 15:10:14 +01:00
memset ( info , 0xcc , info_size ) ;
hr = pNtQueryInformationFile ( h , & io , info , info_size , FileNameInformation ) ;
ok ( hr = = STATUS_SUCCESS , " NtQueryInformationFile returned %#x, expected %#x. \n " , hr , STATUS_SUCCESS ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status is %#x, expected %#x. \n " , U ( io ) . Status , STATUS_SUCCESS ) ;
2009-12-09 12:19:48 +01:00
ok ( info - > FileNameLength = = lstrlenW ( expected ) * sizeof ( WCHAR ) , " info->FileNameLength is %u \n " , info - > FileNameLength ) ;
ok ( info - > FileName [ info - > FileNameLength / sizeof ( WCHAR ) ] = = 0xcccc , " info->FileName[len] is %#x, expected 0xcccc. \n " ,
info - > FileName [ info - > FileNameLength / sizeof ( WCHAR ) ] ) ;
2009-11-12 15:10:14 +01:00
info - > FileName [ info - > FileNameLength / sizeof ( WCHAR ) ] = ' \0 ' ;
ok ( ! lstrcmpiW ( info - > FileName , expected ) , " info->FileName is %s, expected %s. \n " ,
wine_dbgstr_w ( info - > FileName ) , wine_dbgstr_w ( expected ) ) ;
ok ( io . Information = = FIELD_OFFSET ( FILE_NAME_INFORMATION , FileName ) + info - > FileNameLength ,
" io.Information is %lu, expected %u. \n " ,
io . Information , FIELD_OFFSET ( FILE_NAME_INFORMATION , FileName ) + info - > FileNameLength ) ;
2009-11-19 11:41:23 +01:00
CloseHandle ( h ) ;
HeapFree ( GetProcessHeap ( ) , 0 , info ) ;
HeapFree ( GetProcessHeap ( ) , 0 , expected ) ;
HeapFree ( GetProcessHeap ( ) , 0 , volume_prefix ) ;
if ( old_redir | | ! pGetSystemWow64DirectoryW | | ! ( file_name_size = pGetSystemWow64DirectoryW ( NULL , 0 ) ) )
{
skip ( " Not running on WoW64, skipping test. \n " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , file_name ) ;
return ;
}
h = CreateFileW ( file_name , GENERIC_READ ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( h ! = INVALID_HANDLE_VALUE , " Failed to open file. \n " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , file_name ) ;
file_name = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * file_name ) ) ;
volume_prefix = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * volume_prefix ) ) ;
expected = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * expected ) ) ;
len = pGetSystemWow64DirectoryW ( file_name , file_name_size ) ;
ok ( len = = file_name_size - 1 ,
" GetSystemWow64DirectoryW returned %u, expected %u. \n " ,
len , file_name_size - 1 ) ;
len = pGetVolumePathNameW ( file_name , volume_prefix , file_name_size ) ;
ok ( len , " GetVolumePathNameW failed. \n " ) ;
len = lstrlenW ( volume_prefix ) ;
if ( len & & volume_prefix [ len - 1 ] = = ' \\ ' ) - - len ;
memcpy ( expected , file_name + len , ( file_name_size - len - 1 ) * sizeof ( WCHAR ) ) ;
expected [ file_name_size - len - 1 ] = ' \0 ' ;
info_size = sizeof ( * info ) + ( file_name_size * sizeof ( WCHAR ) ) ;
info = HeapAlloc ( GetProcessHeap ( ) , 0 , info_size ) ;
memset ( info , 0xcc , info_size ) ;
hr = pNtQueryInformationFile ( h , & io , info , info_size , FileNameInformation ) ;
ok ( hr = = STATUS_SUCCESS , " NtQueryInformationFile returned %#x, expected %#x. \n " , hr , STATUS_SUCCESS ) ;
info - > FileName [ info - > FileNameLength / sizeof ( WCHAR ) ] = ' \0 ' ;
ok ( ! lstrcmpiW ( info - > FileName , expected ) , " info->FileName is %s, expected %s. \n " ,
wine_dbgstr_w ( info - > FileName ) , wine_dbgstr_w ( expected ) ) ;
2009-11-12 15:10:14 +01:00
CloseHandle ( h ) ;
HeapFree ( GetProcessHeap ( ) , 0 , info ) ;
HeapFree ( GetProcessHeap ( ) , 0 , expected ) ;
HeapFree ( GetProcessHeap ( ) , 0 , volume_prefix ) ;
HeapFree ( GetProcessHeap ( ) , 0 , file_name ) ;
}
2009-12-01 11:27:46 +01:00
static void test_file_all_name_information ( void )
{
WCHAR * file_name , * volume_prefix , * expected ;
FILE_ALL_INFORMATION * info ;
ULONG old_redir = 1 , tmp ;
UINT file_name_size ;
IO_STATUS_BLOCK io ;
UINT info_size ;
HRESULT hr ;
HANDLE h ;
UINT len ;
/* GetVolumePathName is not present before w2k */
if ( ! pGetVolumePathNameW ) {
win_skip ( " GetVolumePathNameW not found \n " ) ;
return ;
}
file_name_size = GetSystemDirectoryW ( NULL , 0 ) ;
file_name = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * file_name ) ) ;
volume_prefix = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * volume_prefix ) ) ;
expected = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * volume_prefix ) ) ;
len = GetSystemDirectoryW ( file_name , file_name_size ) ;
ok ( len = = file_name_size - 1 ,
" GetSystemDirectoryW returned %u, expected %u. \n " ,
len , file_name_size - 1 ) ;
len = pGetVolumePathNameW ( file_name , volume_prefix , file_name_size ) ;
ok ( len , " GetVolumePathNameW failed. \n " ) ;
len = lstrlenW ( volume_prefix ) ;
if ( len & & volume_prefix [ len - 1 ] = = ' \\ ' ) - - len ;
memcpy ( expected , file_name + len , ( file_name_size - len - 1 ) * sizeof ( WCHAR ) ) ;
expected [ file_name_size - len - 1 ] = ' \0 ' ;
/* A bit more than we actually need, but it keeps the calculation simple. */
info_size = sizeof ( * info ) + ( file_name_size * sizeof ( WCHAR ) ) ;
info = HeapAlloc ( GetProcessHeap ( ) , 0 , info_size ) ;
if ( pRtlWow64EnableFsRedirectionEx ) pRtlWow64EnableFsRedirectionEx ( TRUE , & old_redir ) ;
h = CreateFileW ( file_name , GENERIC_READ ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
if ( pRtlWow64EnableFsRedirectionEx ) pRtlWow64EnableFsRedirectionEx ( old_redir , & tmp ) ;
ok ( h ! = INVALID_HANDLE_VALUE , " Failed to open file. \n " ) ;
hr = pNtQueryInformationFile ( h , & io , info , sizeof ( * info ) - 1 , FileAllInformation ) ;
ok ( hr = = STATUS_INFO_LENGTH_MISMATCH , " NtQueryInformationFile returned %#x, expected %#x. \n " ,
hr , STATUS_INFO_LENGTH_MISMATCH ) ;
memset ( info , 0xcc , info_size ) ;
hr = pNtQueryInformationFile ( h , & io , info , sizeof ( * info ) , FileAllInformation ) ;
ok ( hr = = STATUS_BUFFER_OVERFLOW , " NtQueryInformationFile returned %#x, expected %#x. \n " ,
hr , STATUS_BUFFER_OVERFLOW ) ;
ok ( U ( io ) . Status = = STATUS_BUFFER_OVERFLOW , " io.Status is %#x, expected %#x. \n " ,
U ( io ) . Status , STATUS_BUFFER_OVERFLOW ) ;
ok ( info - > NameInformation . FileNameLength = = lstrlenW ( expected ) * sizeof ( WCHAR ) ,
2009-12-09 12:19:48 +01:00
" info->NameInformation.FileNameLength is %u \n " , info - > NameInformation . FileNameLength ) ;
2009-12-01 11:27:46 +01:00
ok ( info - > NameInformation . FileName [ 2 ] = = 0xcccc ,
" info->NameInformation.FileName[2] is %#x, expected 0xcccc. \n " , info - > NameInformation . FileName [ 2 ] ) ;
ok ( CharLowerW ( ( LPWSTR ) ( UINT_PTR ) info - > NameInformation . FileName [ 1 ] ) = = CharLowerW ( ( LPWSTR ) ( UINT_PTR ) expected [ 1 ] ) ,
" info->NameInformation.FileName[1] is %p, expected %p. \n " ,
CharLowerW ( ( LPWSTR ) ( UINT_PTR ) info - > NameInformation . FileName [ 1 ] ) , CharLowerW ( ( LPWSTR ) ( UINT_PTR ) expected [ 1 ] ) ) ;
2009-12-09 12:19:48 +01:00
ok ( io . Information = = sizeof ( * info ) , " io.Information is %lu \n " , io . Information ) ;
2009-12-01 11:27:46 +01:00
memset ( info , 0xcc , info_size ) ;
hr = pNtQueryInformationFile ( h , & io , info , info_size , FileAllInformation ) ;
ok ( hr = = STATUS_SUCCESS , " NtQueryInformationFile returned %#x, expected %#x. \n " , hr , STATUS_SUCCESS ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status is %#x, expected %#x. \n " , U ( io ) . Status , STATUS_SUCCESS ) ;
ok ( info - > NameInformation . FileNameLength = = lstrlenW ( expected ) * sizeof ( WCHAR ) ,
2009-12-09 12:19:48 +01:00
" info->NameInformation.FileNameLength is %u \n " , info - > NameInformation . FileNameLength ) ;
2009-12-01 11:27:46 +01:00
ok ( info - > NameInformation . FileName [ info - > NameInformation . FileNameLength / sizeof ( WCHAR ) ] = = 0xcccc ,
2009-12-09 12:19:48 +01:00
" info->NameInformation.FileName[len] is %#x, expected 0xcccc. \n " ,
info - > NameInformation . FileName [ info - > NameInformation . FileNameLength / sizeof ( WCHAR ) ] ) ;
2009-12-01 11:27:46 +01:00
info - > NameInformation . FileName [ info - > NameInformation . FileNameLength / sizeof ( WCHAR ) ] = ' \0 ' ;
ok ( ! lstrcmpiW ( info - > NameInformation . FileName , expected ) ,
" info->NameInformation.FileName is %s, expected %s. \n " ,
wine_dbgstr_w ( info - > NameInformation . FileName ) , wine_dbgstr_w ( expected ) ) ;
ok ( io . Information = = FIELD_OFFSET ( FILE_ALL_INFORMATION , NameInformation . FileName )
+ info - > NameInformation . FileNameLength ,
2009-12-09 12:19:48 +01:00
" io.Information is %lu \n " , io . Information ) ;
2009-12-01 11:27:46 +01:00
CloseHandle ( h ) ;
HeapFree ( GetProcessHeap ( ) , 0 , info ) ;
HeapFree ( GetProcessHeap ( ) , 0 , expected ) ;
HeapFree ( GetProcessHeap ( ) , 0 , volume_prefix ) ;
if ( old_redir | | ! pGetSystemWow64DirectoryW | | ! ( file_name_size = pGetSystemWow64DirectoryW ( NULL , 0 ) ) )
{
skip ( " Not running on WoW64, skipping test. \n " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , file_name ) ;
return ;
}
h = CreateFileW ( file_name , GENERIC_READ ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( h ! = INVALID_HANDLE_VALUE , " Failed to open file. \n " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , file_name ) ;
file_name = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * file_name ) ) ;
volume_prefix = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * volume_prefix ) ) ;
expected = HeapAlloc ( GetProcessHeap ( ) , 0 , file_name_size * sizeof ( * expected ) ) ;
len = pGetSystemWow64DirectoryW ( file_name , file_name_size ) ;
ok ( len = = file_name_size - 1 ,
" GetSystemWow64DirectoryW returned %u, expected %u. \n " ,
len , file_name_size - 1 ) ;
len = pGetVolumePathNameW ( file_name , volume_prefix , file_name_size ) ;
ok ( len , " GetVolumePathNameW failed. \n " ) ;
len = lstrlenW ( volume_prefix ) ;
if ( len & & volume_prefix [ len - 1 ] = = ' \\ ' ) - - len ;
memcpy ( expected , file_name + len , ( file_name_size - len - 1 ) * sizeof ( WCHAR ) ) ;
expected [ file_name_size - len - 1 ] = ' \0 ' ;
info_size = sizeof ( * info ) + ( file_name_size * sizeof ( WCHAR ) ) ;
info = HeapAlloc ( GetProcessHeap ( ) , 0 , info_size ) ;
memset ( info , 0xcc , info_size ) ;
hr = pNtQueryInformationFile ( h , & io , info , info_size , FileAllInformation ) ;
ok ( hr = = STATUS_SUCCESS , " NtQueryInformationFile returned %#x, expected %#x. \n " , hr , STATUS_SUCCESS ) ;
info - > NameInformation . FileName [ info - > NameInformation . FileNameLength / sizeof ( WCHAR ) ] = ' \0 ' ;
ok ( ! lstrcmpiW ( info - > NameInformation . FileName , expected ) , " info->NameInformation.FileName is %s, expected %s. \n " ,
wine_dbgstr_w ( info - > NameInformation . FileName ) , wine_dbgstr_w ( expected ) ) ;
CloseHandle ( h ) ;
HeapFree ( GetProcessHeap ( ) , 0 , info ) ;
HeapFree ( GetProcessHeap ( ) , 0 , expected ) ;
HeapFree ( GetProcessHeap ( ) , 0 , volume_prefix ) ;
HeapFree ( GetProcessHeap ( ) , 0 , file_name ) ;
}
2010-11-22 21:24:42 +01:00
static void test_query_volume_information_file ( void )
{
NTSTATUS status ;
HANDLE dir ;
WCHAR path [ MAX_PATH ] ;
OBJECT_ATTRIBUTES attr ;
IO_STATUS_BLOCK io ;
UNICODE_STRING nameW ;
FILE_FS_VOLUME_INFORMATION * ffvi ;
BYTE buf [ sizeof ( FILE_FS_VOLUME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ] ;
2010-11-24 00:43:24 +01:00
GetWindowsDirectoryW ( path , MAX_PATH ) ;
2010-11-22 21:24:42 +01:00
pRtlDosPathNameToNtPathName_U ( path , & nameW , NULL , NULL ) ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = 0 ;
attr . ObjectName = & nameW ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
status = pNtOpenFile ( & dir , SYNCHRONIZE | FILE_LIST_DIRECTORY , & attr , & io ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
pRtlFreeUnicodeString ( & nameW ) ;
ZeroMemory ( buf , sizeof ( buf ) ) ;
U ( io ) . Status = 0xdadadada ;
io . Information = 0xcacacaca ;
status = pNtQueryVolumeInformationFile ( dir , & io , buf , sizeof ( buf ) , FileFsVolumeInformation ) ;
ffvi = ( FILE_FS_VOLUME_INFORMATION * ) buf ;
todo_wine
{
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %d \n " , status ) ;
ok ( U ( io ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %d \n " , U ( io ) . Status ) ;
ok ( io . Information = = ( FIELD_OFFSET ( FILE_FS_VOLUME_INFORMATION , VolumeLabel ) + ffvi - > VolumeLabelLength ) ,
" expected %d, got %lu \n " , ( FIELD_OFFSET ( FILE_FS_VOLUME_INFORMATION , VolumeLabel ) + ffvi - > VolumeLabelLength ) ,
io . Information ) ;
ok ( ffvi - > VolumeCreationTime . QuadPart ! = 0 , " Missing VolumeCreationTime \n " ) ;
ok ( ffvi - > VolumeSerialNumber ! = 0 , " Missing VolumeSerialNumber \n " ) ;
ok ( ffvi - > SupportsObjects = = 1 , " expected 1, got %d \n " , ffvi - > SupportsObjects ) ;
}
2011-01-31 15:36:32 +01:00
ok ( ffvi - > VolumeLabelLength = = lstrlenW ( ffvi - > VolumeLabel ) * sizeof ( WCHAR ) , " got %d \n " , ffvi - > VolumeLabelLength ) ;
2010-11-22 21:24:42 +01:00
trace ( " VolumeSerialNumber: %x VolumeLabelName: %s \n " , ffvi - > VolumeSerialNumber , wine_dbgstr_w ( ffvi - > VolumeLabel ) ) ;
CloseHandle ( dir ) ;
}
2007-02-27 13:41:55 +01:00
START_TEST ( file )
{
2009-11-12 23:42:53 +01:00
HMODULE hkernel32 = GetModuleHandleA ( " kernel32.dll " ) ;
2007-02-27 13:41:55 +01:00
HMODULE hntdll = GetModuleHandleA ( " ntdll.dll " ) ;
2007-03-28 10:00:28 +02:00
if ( ! hntdll )
2007-02-27 13:41:55 +01:00
{
2007-03-28 10:00:28 +02:00
skip ( " not running on NT, skipping test \n " ) ;
return ;
2007-02-27 13:41:55 +01:00
}
2007-03-28 10:00:28 +02:00
2009-11-12 23:42:53 +01:00
pGetVolumePathNameW = ( void * ) GetProcAddress ( hkernel32 , " GetVolumePathNameW " ) ;
2009-11-19 11:41:23 +01:00
pGetSystemWow64DirectoryW = ( void * ) GetProcAddress ( hkernel32 , " GetSystemWow64DirectoryW " ) ;
2009-11-12 23:42:53 +01:00
2008-08-31 13:54:03 +02:00
pRtlFreeUnicodeString = ( void * ) GetProcAddress ( hntdll , " RtlFreeUnicodeString " ) ;
2007-03-28 10:00:28 +02:00
pRtlInitUnicodeString = ( void * ) GetProcAddress ( hntdll , " RtlInitUnicodeString " ) ;
2008-08-31 13:54:03 +02:00
pRtlDosPathNameToNtPathName_U = ( void * ) GetProcAddress ( hntdll , " RtlDosPathNameToNtPathName_U " ) ;
2009-11-19 11:41:22 +01:00
pRtlWow64EnableFsRedirectionEx = ( void * ) GetProcAddress ( hntdll , " RtlWow64EnableFsRedirectionEx " ) ;
2007-03-28 10:00:28 +02:00
pNtCreateMailslotFile = ( void * ) GetProcAddress ( hntdll , " NtCreateMailslotFile " ) ;
2009-12-08 12:19:05 +01:00
pNtCreateFile = ( void * ) GetProcAddress ( hntdll , " NtCreateFile " ) ;
2009-12-01 17:38:39 +01:00
pNtOpenFile = ( void * ) GetProcAddress ( hntdll , " NtOpenFile " ) ;
2008-08-31 13:54:03 +02:00
pNtDeleteFile = ( void * ) GetProcAddress ( hntdll , " NtDeleteFile " ) ;
2007-04-09 12:23:13 +02:00
pNtReadFile = ( void * ) GetProcAddress ( hntdll , " NtReadFile " ) ;
pNtWriteFile = ( void * ) GetProcAddress ( hntdll , " NtWriteFile " ) ;
2009-08-14 00:56:23 +02:00
pNtCancelIoFile = ( void * ) GetProcAddress ( hntdll , " NtCancelIoFile " ) ;
2009-08-08 22:32:34 +02:00
pNtCancelIoFileEx = ( void * ) GetProcAddress ( hntdll , " NtCancelIoFileEx " ) ;
2007-03-28 10:00:28 +02:00
pNtClose = ( void * ) GetProcAddress ( hntdll , " NtClose " ) ;
2007-11-09 23:11:31 +01:00
pNtCreateIoCompletion = ( void * ) GetProcAddress ( hntdll , " NtCreateIoCompletion " ) ;
pNtOpenIoCompletion = ( void * ) GetProcAddress ( hntdll , " NtOpenIoCompletion " ) ;
pNtQueryIoCompletion = ( void * ) GetProcAddress ( hntdll , " NtQueryIoCompletion " ) ;
pNtRemoveIoCompletion = ( void * ) GetProcAddress ( hntdll , " NtRemoveIoCompletion " ) ;
pNtSetIoCompletion = ( void * ) GetProcAddress ( hntdll , " NtSetIoCompletion " ) ;
pNtSetInformationFile = ( void * ) GetProcAddress ( hntdll , " NtSetInformationFile " ) ;
2009-09-09 14:41:30 +02:00
pNtQueryInformationFile = ( void * ) GetProcAddress ( hntdll , " NtQueryInformationFile " ) ;
2009-12-02 17:36:58 +01:00
pNtQueryDirectoryFile = ( void * ) GetProcAddress ( hntdll , " NtQueryDirectoryFile " ) ;
2010-11-22 21:24:42 +01:00
pNtQueryVolumeInformationFile = ( void * ) GetProcAddress ( hntdll , " NtQueryVolumeInformationFile " ) ;
2007-03-28 10:00:28 +02:00
2009-12-08 12:19:05 +01:00
create_file_test ( ) ;
2009-12-01 17:38:39 +01:00
open_file_test ( ) ;
2008-08-31 13:54:03 +02:00
delete_file_test ( ) ;
2007-04-09 12:23:13 +02:00
read_file_test ( ) ;
2011-01-12 01:09:32 +01:00
append_file_test ( ) ;
2007-03-28 10:00:28 +02:00
nt_mailslot_test ( ) ;
2007-11-09 23:11:31 +01:00
test_iocompletion ( ) ;
2009-09-09 14:41:30 +02:00
test_file_basic_information ( ) ;
test_file_all_information ( ) ;
test_file_both_information ( ) ;
2009-11-12 15:10:14 +01:00
test_file_name_information ( ) ;
2009-12-01 11:27:46 +01:00
test_file_all_name_information ( ) ;
2010-11-22 21:24:42 +01:00
test_query_volume_information_file ( ) ;
2007-02-27 13:41:55 +01:00
}