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
2011-03-22 12:38:44 +01:00
* Copyright 2011 Dmitry Timoshkov
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"
2018-09-27 10:30:52 +02:00
# include "winnls.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 ) ;
2017-02-15 22:12:59 +01:00
static NTSTATUS ( WINAPI * pNtFsControlFile ) ( HANDLE handle , HANDLE event , PIO_APC_ROUTINE apc , PVOID apc_context , PIO_STATUS_BLOCK io , ULONG code , PVOID in_buffer , ULONG in_size , PVOID out_buffer , ULONG out_size ) ;
2007-02-27 13:41:55 +01:00
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 ) ;
2018-09-30 23:59:46 +02:00
static NTSTATUS ( WINAPI * pNtRemoveIoCompletionEx ) ( HANDLE , FILE_IO_COMPLETION_INFORMATION * , ULONG , ULONG * , LARGE_INTEGER * , BOOLEAN ) ;
2013-08-20 13:20:39 +02:00
static NTSTATUS ( WINAPI * pNtSetIoCompletion ) ( HANDLE , ULONG_PTR , ULONG_PTR , NTSTATUS , SIZE_T ) ;
2007-11-09 23:11:31 +01:00
static NTSTATUS ( WINAPI * pNtSetInformationFile ) ( HANDLE , PIO_STATUS_BLOCK , PVOID , ULONG , FILE_INFORMATION_CLASS ) ;
2018-09-27 10:30:52 +02:00
static NTSTATUS ( WINAPI * pNtQueryAttributesFile ) ( const OBJECT_ATTRIBUTES * , FILE_BASIC_INFORMATION * ) ;
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 ) ;
2015-09-25 13:35:45 +02:00
static NTSTATUS ( WINAPI * pNtQueryFullAttributesFile ) ( const OBJECT_ATTRIBUTES * , FILE_NETWORK_OPEN_INFORMATION * ) ;
2017-03-01 12:05:53 +01:00
static NTSTATUS ( WINAPI * pNtFlushBuffersFile ) ( HANDLE , IO_STATUS_BLOCK * ) ;
2007-11-09 23:11:31 +01:00
2018-10-29 15:48:30 +01:00
static WCHAR fooW [ ] = { ' f ' , ' o ' , ' o ' , 0 } ;
2007-04-09 12:23:13 +02:00
static inline BOOL is_signaled ( HANDLE obj )
{
2013-08-23 08:03:45 +02:00
return WaitForSingleObject ( obj , 0 ) = = WAIT_OBJECT_0 ;
2007-04-09 12:23:13 +02:00
}
2008-06-02 22:14:26 +02:00
# define TEST_BUF_LEN 3
2007-04-09 12:23:13 +02:00
static HANDLE create_temp_file ( ULONG flags )
{
2013-08-23 06:59:55 +02:00
char path [ MAX_PATH ] , buffer [ MAX_PATH ] ;
2007-04-09 12:23:13 +02:00
HANDLE handle ;
2013-08-23 06:59:55 +02:00
GetTempPathA ( MAX_PATH , path ) ;
GetTempFileNameA ( path , " foo " , 0 , buffer ) ;
2007-04-09 12:23:13 +02:00
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-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 ;
}
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 } ;
2011-09-11 22:52:45 +02:00
static const WCHAR questionmarkInvalidNameW [ ] = { ' a ' , ' f ' , ' i ' , ' l ' , ' e ' , ' ? ' , 0 } ;
static const WCHAR pipeInvalidNameW [ ] = { ' a ' , ' | ' , ' b ' , 0 } ;
2015-09-25 13:35:45 +02:00
static const WCHAR pathInvalidNtW [ ] = { ' \\ ' , ' \\ ' , ' ? ' , ' \\ ' , 0 } ;
static const WCHAR pathInvalidNt2W [ ] = { ' \\ ' , ' ? ' , ' ? ' , ' \\ ' , 0 } ;
static const WCHAR pathInvalidDosW [ ] = { ' \\ ' , ' D ' , ' o ' , ' s ' , ' D ' , ' e ' , ' v ' , ' i ' , ' c ' , ' e ' , ' s ' , ' \\ ' , 0 } ;
2015-10-08 07:25:27 +02:00
static const char testdata [ ] = " Hello World " ;
2015-09-25 13:35:45 +02:00
FILE_NETWORK_OPEN_INFORMATION info ;
2009-12-08 12:19:05 +01:00
NTSTATUS status ;
2011-09-11 22:52:45 +02:00
HANDLE dir , file ;
2009-12-08 12:19:05 +01:00
WCHAR path [ MAX_PATH ] ;
OBJECT_ATTRIBUTES attr ;
IO_STATUS_BLOCK io ;
UNICODE_STRING nameW ;
2015-10-08 07:25:27 +02:00
LARGE_INTEGER offset ;
char buf [ 32 ] ;
DWORD ret ;
2009-12-08 12:19:05 +01:00
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 */
2015-10-08 07:25:27 +02:00
status = pNtCreateFile ( & dir , GENERIC_READ | GENERIC_WRITE , & attr , & io , NULL , 0 ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_OPEN , FILE_DIRECTORY_FILE , NULL , 0 ) ;
2009-12-08 12:19:05 +01:00
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
2015-10-08 07:25:27 +02:00
U ( io ) . Status = 0xdeadbeef ;
offset . QuadPart = 0 ;
status = pNtReadFile ( dir , NULL , NULL , NULL , & io , buf , sizeof ( buf ) , & offset , NULL ) ;
todo_wine
ok ( status = = STATUS_INVALID_DEVICE_REQUEST | | status = = STATUS_PENDING , " NtReadFile error %08x \n " , status ) ;
if ( status = = STATUS_PENDING )
{
ret = WaitForSingleObject ( dir , 1000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %u \n " , ret ) ;
ok ( U ( io ) . Status = = STATUS_INVALID_DEVICE_REQUEST ,
" expected STATUS_INVALID_DEVICE_REQUEST, got %08x \n " , U ( io ) . Status ) ;
}
U ( io ) . Status = 0xdeadbeef ;
offset . QuadPart = 0 ;
status = pNtWriteFile ( dir , NULL , NULL , NULL , & io , testdata , sizeof ( testdata ) , & offset , NULL ) ;
todo_wine
ok ( status = = STATUS_INVALID_DEVICE_REQUEST | | status = = STATUS_PENDING , " NtWriteFile error %08x \n " , status ) ;
if ( status = = STATUS_PENDING )
{
ret = WaitForSingleObject ( dir , 1000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %u \n " , ret ) ;
ok ( U ( io ) . Status = = STATUS_INVALID_DEVICE_REQUEST ,
" expected STATUS_INVALID_DEVICE_REQUEST, got %08x \n " , U ( io ) . Status ) ;
}
2009-12-08 12:19:05 +01:00
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 ) ;
2011-09-11 22:52:45 +02:00
/* Invalid chars in file/dirnames */
pRtlDosPathNameToNtPathName_U ( questionmarkInvalidNameW , & nameW , NULL , NULL ) ;
attr . ObjectName = & nameW ;
status = pNtCreateFile ( & dir , GENERIC_READ | SYNCHRONIZE , & attr , & io , NULL , 0 ,
FILE_SHARE_READ , FILE_CREATE ,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & file , GENERIC_WRITE | SYNCHRONIZE , & attr , & io , NULL , 0 ,
0 , FILE_CREATE ,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
2014-05-06 09:58:03 +02:00
pRtlFreeUnicodeString ( & nameW ) ;
2011-09-11 22:52:45 +02:00
pRtlDosPathNameToNtPathName_U ( pipeInvalidNameW , & nameW , NULL , NULL ) ;
attr . ObjectName = & nameW ;
status = pNtCreateFile ( & dir , GENERIC_READ | SYNCHRONIZE , & attr , & io , NULL , 0 ,
FILE_SHARE_READ , FILE_CREATE ,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtCreateFile ( & file , GENERIC_WRITE | SYNCHRONIZE , & attr , & io , NULL , 0 ,
0 , FILE_CREATE ,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
2014-05-06 09:58:03 +02:00
pRtlFreeUnicodeString ( & nameW ) ;
2015-09-25 13:35:45 +02:00
pRtlInitUnicodeString ( & nameW , pathInvalidNtW ) ;
status = pNtCreateFile ( & dir , GENERIC_READ | SYNCHRONIZE , & attr , & io , NULL , 0 ,
FILE_SHARE_READ , FILE_CREATE ,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtQueryFullAttributesFile ( & attr , & info ) ;
todo_wine ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" query %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
pRtlInitUnicodeString ( & nameW , pathInvalidNt2W ) ;
status = pNtCreateFile ( & dir , GENERIC_READ | SYNCHRONIZE , & attr , & io , NULL , 0 ,
FILE_SHARE_READ , FILE_CREATE ,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtQueryFullAttributesFile ( & attr , & info ) ;
2015-09-25 13:35:58 +02:00
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" query %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
2015-09-25 13:35:45 +02:00
pRtlInitUnicodeString ( & nameW , pathInvalidDosW ) ;
status = pNtCreateFile ( & dir , GENERIC_READ | SYNCHRONIZE , & attr , & io , NULL , 0 ,
FILE_SHARE_READ , FILE_CREATE ,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT , NULL , 0 ) ;
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
status = pNtQueryFullAttributesFile ( & attr , & info ) ;
2015-09-25 13:35:58 +02:00
ok ( status = = STATUS_OBJECT_NAME_INVALID ,
" query %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 )
{
2018-09-30 23:59:42 +02:00
static const WCHAR testdirW [ ] = { ' o ' , ' p ' , ' e ' , ' n ' , ' f ' , ' i ' , ' l ' , ' e ' , ' t ' , ' e ' , ' s ' , ' t ' , 0 } ;
2015-08-21 07:25:45 +02:00
static const char testdata [ ] = " Hello World " ;
2009-12-01 17:38:39 +01:00
NTSTATUS status ;
2015-05-27 05:12:53 +02:00
HANDLE dir , root , handle , file ;
WCHAR path [ MAX_PATH ] , tmpfile [ 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 ;
2015-08-21 07:25:45 +02:00
BOOL ret , restart = TRUE ;
DWORD numbytes ;
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 ;
2020-06-26 14:26:55 +02:00
attr . Attributes = 0 ;
2009-12-01 17:38:39 +01:00
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 ) ;
2018-09-30 23:59:42 +02:00
CloseHandle ( dir ) ;
GetTempPathW ( MAX_PATH , path ) ;
lstrcatW ( path , testdirW ) ;
CreateDirectoryW ( path , NULL ) ;
pRtlDosPathNameToNtPathName_U ( path , & nameW , NULL , NULL ) ;
attr . RootDirectory = 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 ) ;
GetTempFileNameW ( path , fooW , 0 , tmpfile ) ;
file = CreateFileW ( tmpfile , FILE_WRITE_DATA , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( file ! = INVALID_HANDLE_VALUE , " CreateFile error %d \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
ret = WriteFile ( file , testdata , sizeof ( testdata ) - 1 , & numbytes , NULL ) ;
ok ( ret , " WriteFile failed with error %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) - 1 , " failed to write all data \n " ) ;
CloseHandle ( file ) ;
2009-12-01 17:38:39 +01:00
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 ) ) ;
2018-09-30 23:59:42 +02:00
ok ( status = = STATUS_SUCCESS , " open %s failed %x \n " , wine_dbgstr_w ( info - > FileName ) , status ) ;
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 ) ;
2015-05-27 05:12:53 +02:00
pRtlDosPathNameToNtPathName_U ( tmpfile , & 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 ( & file , SYNCHRONIZE | FILE_LIST_DIRECTORY , & attr , & io ,
FILE_SHARE_READ , FILE_SYNCHRONOUS_IO_NONALERT ) ;
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( nameW . Buffer ) , status ) ;
pRtlFreeUnicodeString ( & nameW ) ;
2015-08-21 07:25:45 +02:00
numbytes = 0xdeadbeef ;
memset ( data , 0 , sizeof ( data ) ) ;
ret = ReadFile ( file , data , sizeof ( data ) , & numbytes , NULL ) ;
ok ( ret , " ReadFile failed with error %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) - 1 , " failed to read all data \n " ) ;
ok ( ! memcmp ( data , testdata , sizeof ( testdata ) - 1 ) , " testdata doesn't match \n " ) ;
nameW . Length = sizeof ( fooW ) - sizeof ( WCHAR ) ;
nameW . Buffer = fooW ;
attr . RootDirectory = file ;
attr . ObjectName = & nameW ;
status = pNtOpenFile ( & root , SYNCHRONIZE | FILE_LIST_DIRECTORY , & attr , & io ,
FILE_SHARE_READ , FILE_SYNCHRONOUS_IO_NONALERT ) ;
2015-08-21 07:26:44 +02:00
ok ( status = = STATUS_OBJECT_PATH_NOT_FOUND ,
" expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x \n " , status ) ;
2015-08-21 07:25:45 +02:00
2015-05-27 05:12:53 +02:00
nameW . Length = 0 ;
nameW . Buffer = NULL ;
attr . RootDirectory = file ;
attr . ObjectName = & nameW ;
status = pNtOpenFile ( & root , SYNCHRONIZE | FILE_LIST_DIRECTORY , & attr , & io ,
FILE_SHARE_READ , FILE_SYNCHRONOUS_IO_NONALERT ) ;
2015-08-21 07:26:44 +02:00
ok ( ! status , " open %s failed %x \n " , wine_dbgstr_w ( tmpfile ) , status ) ;
2015-05-27 05:12:53 +02:00
2015-08-21 07:25:45 +02:00
numbytes = SetFilePointer ( file , 0 , 0 , FILE_CURRENT ) ;
ok ( numbytes = = sizeof ( testdata ) - 1 , " SetFilePointer returned %u \n " , numbytes ) ;
numbytes = SetFilePointer ( root , 0 , 0 , FILE_CURRENT ) ;
2015-08-21 07:26:44 +02:00
ok ( numbytes = = 0 , " SetFilePointer returned %u \n " , numbytes ) ;
2015-08-21 07:25:45 +02:00
numbytes = 0xdeadbeef ;
memset ( data , 0 , sizeof ( data ) ) ;
ret = ReadFile ( root , data , sizeof ( data ) , & numbytes , NULL ) ;
2015-08-21 07:26:44 +02:00
ok ( ret , " ReadFile failed with error %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) - 1 , " failed to read all data \n " ) ;
ok ( ! memcmp ( data , testdata , sizeof ( testdata ) - 1 ) , " testdata doesn't match \n " ) ;
2015-08-21 07:25:45 +02:00
numbytes = SetFilePointer ( file , 0 , 0 , FILE_CURRENT ) ;
ok ( numbytes = = sizeof ( testdata ) - 1 , " SetFilePointer returned %u \n " , numbytes ) ;
numbytes = SetFilePointer ( root , 0 , 0 , FILE_CURRENT ) ;
2015-08-21 07:26:44 +02:00
ok ( numbytes = = sizeof ( testdata ) - 1 , " SetFilePointer returned %u \n " , numbytes ) ;
2015-08-21 07:25:45 +02:00
2015-05-27 05:12:53 +02:00
CloseHandle ( file ) ;
CloseHandle ( root ) ;
DeleteFileW ( tmpfile ) ;
2018-09-30 23:59:42 +02:00
RemoveDirectoryW ( path ) ;
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 ;
}
2018-06-21 23:06:11 +02:00
if ( ret + ARRAY_SIZE ( testdirW ) - 1 + ARRAY_SIZE ( subdirW ) - 1 > = MAX_PATH )
2008-08-31 13:54:03 +02:00
{
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 ) ;
}
2019-02-15 18:41:38 +01:00
# define TEST_OVERLAPPED_READ_SIZE 4096
2007-04-09 12:23:13 +02:00
static void read_file_test ( void )
{
2019-02-15 18:41:38 +01:00
DECLSPEC_ALIGN ( TEST_OVERLAPPED_READ_SIZE ) static unsigned char aligned_buffer [ TEST_OVERLAPPED_READ_SIZE ] ;
2007-04-09 12:23:13 +02:00
const char text [ ] = " foobar " ;
2017-03-28 13:19:25 +02:00
HANDLE handle ;
IO_STATUS_BLOCK iosb ;
2007-04-09 12:23:13 +02:00
NTSTATUS status ;
int apc_count = 0 ;
char buffer [ 128 ] ;
LARGE_INTEGER offset ;
HANDLE event = CreateEventA ( NULL , TRUE , FALSE , NULL ) ;
2009-08-08 22:32:34 +02:00
2007-04-09 12:23:13 +02:00
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 ) ;
2019-03-05 13:16:46 +01:00
ok ( status = = STATUS_PENDING | | broken ( status = = STATUS_SUCCESS ) /* before Vista */ ,
2019-03-05 13:16:45 +01:00
" wrong status %x. \n " , status ) ;
2011-08-26 11:59:49 +02:00
if ( status = = STATUS_PENDING ) WaitForSingleObject ( event , 1000 ) ;
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 ) ;
2016-01-08 10:38:36 +01:00
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
2007-04-09 12:23:13 +02:00
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 ) ;
2019-03-07 10:28:35 +01:00
ok ( status = = STATUS_PENDING
2019-03-07 10:28:34 +01:00
| | broken ( status = = STATUS_SUCCESS ) /* before Vista */ ,
" wrong status %x. \n " , status ) ;
2011-08-26 11:59:49 +02:00
if ( status = = STATUS_PENDING ) WaitForSingleObject ( event , 1000 ) ;
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 ) ;
2016-01-08 10:38:36 +01:00
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
2007-04-09 12:23:13 +02:00
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 ) ;
2020-04-20 01:06:00 +02:00
ok ( status = = STATUS_PENDING | | broken ( status = = STATUS_END_OF_FILE ) /* before Vista */ ,
" expected STATUS_PENDING, got %#x \n " , status ) ;
2008-09-11 14:18:46 +02:00
if ( status = = STATUS_PENDING ) /* vista */
{
2011-08-26 11:59:49 +02:00
WaitForSingleObject ( event , 1000 ) ;
2008-09-11 14:18:46 +02:00
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 ) ;
2016-01-08 10:38:36 +01:00
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
2008-09-11 14:18:46 +02:00
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not 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 ) ;
2011-08-26 11:59:49 +02:00
if ( status = = STATUS_PENDING ) WaitForSingleObject ( event , 1000 ) ;
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 ) ;
2016-01-08 10:38:36 +01:00
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
2007-04-09 12:23:13 +02:00
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 ) ;
2016-01-08 10:38:36 +01:00
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
2007-04-09 12:23:13 +02:00
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 ) ;
2013-10-30 06:24:45 +01:00
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 not signaled \n " ) ;
2007-04-09 12:23:13 +02:00
ok ( ! apc_count , " apc was called \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( ! apc_count , " apc was called \n " ) ;
CloseHandle ( handle ) ;
2019-02-15 18:41:38 +01:00
if ( ! ( handle = create_temp_file ( FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING ) ) )
return ;
apc_count = 0 ;
offset . QuadPart = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = 0 ;
ResetEvent ( event ) ;
status = pNtWriteFile ( handle , event , apc , & apc_count , & iosb ,
aligned_buffer , sizeof ( aligned_buffer ) , & offset , NULL ) ;
2019-03-05 13:16:46 +01:00
ok ( status = = STATUS_END_OF_FILE | | status = = STATUS_PENDING
2019-03-05 13:16:45 +01:00
| | broken ( status = = STATUS_SUCCESS ) /* before Vista */ ,
2019-02-15 18:41:38 +01:00
" Wrong status %x. \n " , status ) ;
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " Wrong status %x. \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = sizeof ( aligned_buffer ) , " Wrong info %lu. \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is not 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 ;
offset . QuadPart = 0 ;
U ( iosb ) . Status = 0xdeadbabe ;
iosb . Information = 0xdeadbeef ;
offset . QuadPart = 0 ;
ResetEvent ( event ) ;
status = pNtReadFile ( handle , event , apc , & apc_count , & iosb ,
aligned_buffer , sizeof ( aligned_buffer ) , & offset , NULL ) ;
2019-02-15 18:41:39 +01:00
ok ( status = = STATUS_PENDING , " Wrong status %x. \n " , status ) ;
2019-02-15 18:41:38 +01:00
WaitForSingleObject ( event , 1000 ) ;
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " Wrong status %x. \n " , U ( iosb ) . Status ) ;
ok ( iosb . Information = = sizeof ( aligned_buffer ) , " Wrong info %lu. \n " , iosb . Information ) ;
ok ( is_signaled ( event ) , " event is not signaled. \n " ) ;
ok ( ! apc_count , " apc was called. \n " ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called. \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( event ) ;
2007-04-09 12:23:13 +02:00
}
2011-01-12 01:09:32 +01:00
static void append_file_test ( void )
{
2013-09-20 09:00:37 +02:00
static const char text [ 6 ] = " foobar " ;
2011-01-12 01:09:32 +01:00
HANDLE handle ;
NTSTATUS status ;
IO_STATUS_BLOCK iosb ;
2013-09-20 09:00:37 +02:00
LARGE_INTEGER offset ;
char path [ MAX_PATH ] , buffer [ MAX_PATH ] , buf [ 16 ] ;
2013-10-07 07:39:27 +02:00
DWORD ret ;
2011-01-12 01:09:32 +01:00
2013-08-20 13:22:08 +02:00
GetTempPathA ( MAX_PATH , path ) ;
GetTempFileNameA ( path , " foo " , 0 , buffer ) ;
2013-09-20 09:00:37 +02:00
2013-11-05 22:44:42 +01:00
handle = CreateFileA ( buffer , FILE_WRITE_DATA , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
2013-09-20 09:00:37 +02:00
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFile error %d \n " , GetLastError ( ) ) ;
U ( iosb ) . Status = - 1 ;
iosb . Information = - 1 ;
2013-10-07 07:39:27 +02:00
status = pNtWriteFile ( handle , NULL , NULL , NULL , & iosb , text , 2 , NULL , NULL ) ;
2013-09-20 09:00:37 +02:00
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iosb ) . Status ) ;
2013-10-07 07:39:27 +02:00
ok ( iosb . Information = = 2 , " expected 2, got %lu \n " , iosb . Information ) ;
2013-09-20 09:00:37 +02:00
CloseHandle ( handle ) ;
2011-01-12 01:09:32 +01:00
/* It is possible to open a file with only FILE_APPEND_DATA access flags.
It matches the O_WRONLY | O_APPEND open ( ) posix behavior */
2013-11-05 22:44:42 +01:00
handle = CreateFileA ( buffer , FILE_APPEND_DATA , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
2013-09-20 09:00:37 +02:00
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFile error %d \n " , GetLastError ( ) ) ;
2011-01-12 01:09:32 +01:00
2013-09-20 09:00:37 +02:00
U ( iosb ) . Status = - 1 ;
iosb . Information = - 1 ;
2013-10-07 07:39:27 +02:00
offset . QuadPart = 1 ;
status = pNtWriteFile ( handle , NULL , NULL , NULL , & iosb , text + 2 , 2 , & offset , NULL ) ;
2013-09-20 09:00:37 +02:00
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iosb ) . Status ) ;
2013-10-07 07:39:27 +02:00
ok ( iosb . Information = = 2 , " expected 2, got %lu \n " , iosb . Information ) ;
ret = SetFilePointer ( handle , 0 , NULL , FILE_CURRENT ) ;
ok ( ret = = 4 , " expected 4, got %u \n " , ret ) ;
U ( iosb ) . Status = - 1 ;
iosb . Information = - 1 ;
offset . QuadPart = 3 ;
status = pNtWriteFile ( handle , NULL , NULL , NULL , & iosb , text + 4 , 2 , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iosb ) . Status ) ;
2013-10-07 07:39:27 +02:00
ok ( iosb . Information = = 2 , " expected 2, got %lu \n " , iosb . Information ) ;
ret = SetFilePointer ( handle , 0 , NULL , FILE_CURRENT ) ;
ok ( ret = = 6 , " expected 6, got %u \n " , ret ) ;
2011-01-12 01:09:32 +01:00
2013-09-20 09:00:37 +02:00
CloseHandle ( handle ) ;
2011-01-12 01:09:32 +01:00
2013-11-05 22:44:42 +01:00
handle = CreateFileA ( buffer , FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
2013-09-20 09:00:37 +02:00
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFile error %d \n " , GetLastError ( ) ) ;
2011-01-12 01:09:32 +01:00
2013-09-20 09:00:37 +02:00
memset ( buf , 0 , sizeof ( buf ) ) ;
U ( iosb ) . Status = - 1 ;
iosb . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtReadFile ( handle , 0 , NULL , NULL , & iosb , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtReadFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iosb ) . Status ) ;
2013-09-20 09:00:37 +02:00
ok ( iosb . Information = = 6 , " expected 6, got %lu \n " , iosb . Information ) ;
buf [ 6 ] = 0 ;
ok ( memcmp ( buf , text , 6 ) = = 0 , " wrong file contents: %s \n " , buf ) ;
U ( iosb ) . Status = - 1 ;
iosb . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtWriteFile ( handle , NULL , NULL , NULL , & iosb , text + 3 , 3 , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iosb ) . Status ) ;
2013-09-20 09:00:37 +02:00
ok ( iosb . Information = = 3 , " expected 3, got %lu \n " , iosb . Information ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
U ( iosb ) . Status = - 1 ;
iosb . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtReadFile ( handle , 0 , NULL , NULL , & iosb , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtReadFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iosb ) . Status ) ;
2013-09-20 09:00:37 +02:00
ok ( iosb . Information = = 6 , " expected 6, got %lu \n " , iosb . Information ) ;
buf [ 6 ] = 0 ;
ok ( memcmp ( buf , " barbar " , 6 ) = = 0 , " wrong file contents: %s \n " , buf ) ;
2011-01-12 01:09:32 +01:00
CloseHandle ( handle ) ;
2013-11-05 22:44:42 +01:00
DeleteFileA ( buffer ) ;
2011-01-12 01:09:32 +01:00
}
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 " ) ;
2011-07-26 03:54:31 +02:00
if ( rc = = STATUS_SUCCESS ) pNtClose ( hslot ) ;
2007-02-27 13:42:06 +01:00
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 " ) ;
}
2018-09-30 23:59:46 +02:00
static void WINAPI user_apc_proc ( ULONG_PTR arg )
{
unsigned int * apc_count = ( unsigned int * ) arg ;
+ + * apc_count ;
}
2018-09-30 23:59:45 +02:00
static void test_set_io_completion ( void )
2007-11-09 23:11:31 +01:00
{
2018-09-30 23:59:46 +02:00
FILE_IO_COMPLETION_INFORMATION info [ 2 ] = { { 0 } } ;
2018-09-30 23:59:43 +02:00
LARGE_INTEGER timeout = { { 0 } } ;
2018-09-30 23:59:46 +02:00
unsigned int apc_count ;
2018-09-30 23:59:43 +02:00
IO_STATUS_BLOCK iosb ;
ULONG_PTR key , value ;
2007-11-09 23:11:31 +01:00
NTSTATUS res ;
2010-04-21 11:00:26 +02:00
ULONG count ;
2013-08-20 13:20:39 +02:00
SIZE_T size = 3 ;
2018-09-30 23:59:45 +02:00
HANDLE h ;
2007-11-09 23:11:31 +01:00
2013-08-20 13:20:39 +02:00
if ( sizeof ( size ) > 4 ) size | = ( ULONGLONG ) 0x12345678 < < 32 ;
2018-09-30 23:59:45 +02:00
res = pNtCreateIoCompletion ( & h , IO_COMPLETION_ALL_ACCESS , NULL , 0 ) ;
ok ( res = = STATUS_SUCCESS , " NtCreateIoCompletion failed: %#x \n " , res ) ;
ok ( h & & h ! = INVALID_HANDLE_VALUE , " got invalid handle %p \n " , h ) ;
2018-09-30 23:59:46 +02:00
res = pNtRemoveIoCompletion ( h , & key , & value , & iosb , & timeout ) ;
ok ( res = = STATUS_TIMEOUT , " NtRemoveIoCompletion failed: %#x \n " , res ) ;
2013-08-20 13:20:39 +02:00
res = pNtSetIoCompletion ( h , CKEY_FIRST , CVALUE_FIRST , STATUS_INVALID_DEVICE_REQUEST , size ) ;
2007-11-09 23:11:31 +01:00
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
2018-09-30 23:59:43 +02:00
res = pNtRemoveIoCompletion ( h , & key , & value , & iosb , & timeout ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletion failed: %#x \n " , res ) ;
ok ( key = = CKEY_FIRST , " Invalid completion key: %#lx \n " , key ) ;
ok ( iosb . Information = = size , " Invalid iosb.Information: %lu \n " , iosb . Information ) ;
ok ( U ( iosb ) . Status = = STATUS_INVALID_DEVICE_REQUEST , " Invalid iosb.Status: %#x \n " , U ( iosb ) . Status ) ;
ok ( value = = CVALUE_FIRST , " Invalid completion value: %#lx \n " , value ) ;
2007-11-09 23:11:31 +01:00
count = get_pending_msgs ( h ) ;
2010-04-21 11:00:26 +02:00
ok ( ! count , " Unexpected msg count: %d \n " , count ) ;
2018-09-30 23:59:45 +02:00
2018-09-30 23:59:46 +02:00
if ( ! pNtRemoveIoCompletionEx )
{
skip ( " NtRemoveIoCompletionEx() not present \n " ) ;
pNtClose ( h ) ;
return ;
}
count = 0xdeadbeef ;
res = pNtRemoveIoCompletionEx ( h , info , 2 , & count , & timeout , FALSE ) ;
ok ( res = = STATUS_TIMEOUT , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 1 , " wrong count %u \n " , count ) ;
res = pNtSetIoCompletion ( h , 123 , 456 , 789 , size ) ;
ok ( res = = STATUS_SUCCESS , " NtSetIoCompletion failed: %#x \n " , res ) ;
count = 0xdeadbeef ;
res = pNtRemoveIoCompletionEx ( h , info , 2 , & count , & timeout , FALSE ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 1 , " wrong count %u \n " , count ) ;
ok ( info [ 0 ] . CompletionKey = = 123 , " wrong key %#lx \n " , info [ 0 ] . CompletionKey ) ;
ok ( info [ 0 ] . CompletionValue = = 456 , " wrong value %#lx \n " , info [ 0 ] . CompletionValue ) ;
ok ( info [ 0 ] . IoStatusBlock . Information = = size , " wrong information %#lx \n " ,
info [ 0 ] . IoStatusBlock . Information ) ;
ok ( U ( info [ 0 ] . IoStatusBlock ) . Status = = 789 , " wrong status %#x \n " , U ( info [ 0 ] . IoStatusBlock ) . Status ) ;
res = pNtSetIoCompletion ( h , 123 , 456 , 789 , size ) ;
ok ( res = = STATUS_SUCCESS , " NtSetIoCompletion failed: %#x \n " , res ) ;
res = pNtSetIoCompletion ( h , 12 , 34 , 56 , size ) ;
ok ( res = = STATUS_SUCCESS , " NtSetIoCompletion failed: %#x \n " , res ) ;
count = 0xdeadbeef ;
res = pNtRemoveIoCompletionEx ( h , info , 2 , & count , & timeout , FALSE ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 2 , " wrong count %u \n " , count ) ;
ok ( info [ 0 ] . CompletionKey = = 123 , " wrong key %#lx \n " , info [ 0 ] . CompletionKey ) ;
ok ( info [ 0 ] . CompletionValue = = 456 , " wrong value %#lx \n " , info [ 0 ] . CompletionValue ) ;
ok ( info [ 0 ] . IoStatusBlock . Information = = size , " wrong information %#lx \n " ,
info [ 0 ] . IoStatusBlock . Information ) ;
ok ( U ( info [ 0 ] . IoStatusBlock ) . Status = = 789 , " wrong status %#x \n " , U ( info [ 0 ] . IoStatusBlock ) . Status ) ;
ok ( info [ 1 ] . CompletionKey = = 12 , " wrong key %#lx \n " , info [ 1 ] . CompletionKey ) ;
ok ( info [ 1 ] . CompletionValue = = 34 , " wrong value %#lx \n " , info [ 1 ] . CompletionValue ) ;
ok ( info [ 1 ] . IoStatusBlock . Information = = size , " wrong information %#lx \n " ,
info [ 1 ] . IoStatusBlock . Information ) ;
ok ( U ( info [ 1 ] . IoStatusBlock ) . Status = = 56 , " wrong status %#x \n " , U ( info [ 1 ] . IoStatusBlock ) . Status ) ;
2018-11-18 03:06:18 +01:00
res = pNtSetIoCompletion ( h , 123 , 456 , 789 , size ) ;
ok ( res = = STATUS_SUCCESS , " NtSetIoCompletion failed: %#x \n " , res ) ;
res = pNtSetIoCompletion ( h , 12 , 34 , 56 , size ) ;
ok ( res = = STATUS_SUCCESS , " NtSetIoCompletion failed: %#x \n " , res ) ;
count = 0xdeadbeef ;
res = pNtRemoveIoCompletionEx ( h , info , 1 , & count , NULL , FALSE ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 1 , " wrong count %u \n " , count ) ;
ok ( info [ 0 ] . CompletionKey = = 123 , " wrong key %#lx \n " , info [ 0 ] . CompletionKey ) ;
ok ( info [ 0 ] . CompletionValue = = 456 , " wrong value %#lx \n " , info [ 0 ] . CompletionValue ) ;
ok ( info [ 0 ] . IoStatusBlock . Information = = size , " wrong information %#lx \n " ,
info [ 0 ] . IoStatusBlock . Information ) ;
ok ( U ( info [ 0 ] . IoStatusBlock ) . Status = = 789 , " wrong status %#x \n " , U ( info [ 0 ] . IoStatusBlock ) . Status ) ;
count = 0xdeadbeef ;
res = pNtRemoveIoCompletionEx ( h , info , 1 , & count , NULL , FALSE ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 1 , " wrong count %u \n " , count ) ;
ok ( info [ 0 ] . CompletionKey = = 12 , " wrong key %#lx \n " , info [ 0 ] . CompletionKey ) ;
ok ( info [ 0 ] . CompletionValue = = 34 , " wrong value %#lx \n " , info [ 0 ] . CompletionValue ) ;
ok ( info [ 0 ] . IoStatusBlock . Information = = size , " wrong information %#lx \n " ,
info [ 0 ] . IoStatusBlock . Information ) ;
ok ( U ( info [ 0 ] . IoStatusBlock ) . Status = = 56 , " wrong status %#x \n " , U ( info [ 0 ] . IoStatusBlock ) . Status ) ;
2018-09-30 23:59:46 +02:00
apc_count = 0 ;
QueueUserAPC ( user_apc_proc , GetCurrentThread ( ) , ( ULONG_PTR ) & apc_count ) ;
count = 0xdeadbeef ;
res = pNtRemoveIoCompletionEx ( h , info , 2 , & count , & timeout , FALSE ) ;
ok ( res = = STATUS_TIMEOUT , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 1 , " wrong count %u \n " , count ) ;
ok ( ! apc_count , " wrong apc count %d \n " , apc_count ) ;
res = pNtRemoveIoCompletionEx ( h , info , 2 , & count , & timeout , TRUE ) ;
ok ( res = = STATUS_USER_APC , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 1 , " wrong count %u \n " , count ) ;
ok ( apc_count = = 1 , " wrong apc count %u \n " , apc_count ) ;
apc_count = 0 ;
QueueUserAPC ( user_apc_proc , GetCurrentThread ( ) , ( ULONG_PTR ) & apc_count ) ;
res = pNtSetIoCompletion ( h , 123 , 456 , 789 , size ) ;
ok ( res = = STATUS_SUCCESS , " NtSetIoCompletion failed: %#x \n " , res ) ;
res = pNtRemoveIoCompletionEx ( h , info , 2 , & count , & timeout , TRUE ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletionEx failed: %#x \n " , res ) ;
ok ( count = = 1 , " wrong count %u \n " , count ) ;
ok ( ! apc_count , " wrong apc count %u \n " , apc_count ) ;
SleepEx ( 1 , TRUE ) ;
2018-09-30 23:59:45 +02:00
pNtClose ( h ) ;
2007-11-09 23:11:31 +01:00
}
2018-09-30 23:59:45 +02:00
static void test_file_io_completion ( void )
2007-11-09 23:11:31 +01:00
{
static const char pipe_name [ ] = " \\ \\ . \\ pipe \\ iocompletiontestnamedpipe " ;
2007-12-17 00:02:12 +01:00
IO_STATUS_BLOCK iosb ;
2018-09-30 23:59:44 +02:00
BYTE send_buf [ TEST_BUF_LEN ] , recv_buf [ TEST_BUF_LEN ] ;
2018-09-30 23:59:45 +02:00
FILE_COMPLETION_INFORMATION fci ;
2018-09-30 23:59:43 +02:00
LARGE_INTEGER timeout = { { 0 } } ;
2018-09-30 23:59:44 +02:00
HANDLE server , client ;
2018-09-30 23:59:43 +02:00
ULONG_PTR key , value ;
2018-09-30 23:59:44 +02:00
OVERLAPPED o = { 0 } ;
int apc_count = 0 ;
2007-12-17 00:02:12 +01:00
NTSTATUS res ;
2018-09-30 23:59:44 +02:00
DWORD read ;
long count ;
2018-09-30 23:59:45 +02:00
HANDLE h ;
res = pNtCreateIoCompletion ( & h , IO_COMPLETION_ALL_ACCESS , NULL , 0 ) ;
ok ( res = = STATUS_SUCCESS , " NtCreateIoCompletion failed: %#x \n " , res ) ;
ok ( h & & h ! = INVALID_HANDLE_VALUE , " got invalid handle %p \n " , h ) ;
fci . CompletionPort = h ;
fci . CompletionKey = CKEY_SECOND ;
2018-09-30 23:59:44 +02:00
server = CreateNamedPipeA ( pipe_name , PIPE_ACCESS_INBOUND ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
4 , 1024 , 1024 , 1000 , NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed: %u \n " , GetLastError ( ) ) ;
client = CreateFileA ( pipe_name , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING ,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED , NULL ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " CreateFile failed: %u \n " , GetLastError ( ) ) ;
U ( iosb ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( server , & iosb , & fci , sizeof ( fci ) , FileCompletionInformation ) ;
ok ( res = = STATUS_INVALID_PARAMETER , " NtSetInformationFile failed: %#x \n " , res ) ;
todo_wine
ok ( U ( iosb ) . Status = = 0xdeadbeef , " wrong status %#x \n " , U ( iosb ) . Status ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
server = CreateNamedPipeA ( pipe_name , PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
4 , 1024 , 1024 , 1000 , NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed: %u \n " , GetLastError ( ) ) ;
client = CreateFileA ( pipe_name , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING ,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED , NULL ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " CreateFile failed: %u \n " , GetLastError ( ) ) ;
U ( iosb ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( server , & iosb , & fci , sizeof ( fci ) , FileCompletionInformation ) ;
ok ( res = = STATUS_SUCCESS , " NtSetInformationFile failed: %#x \n " , res ) ;
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " wrong status %#x \n " , U ( iosb ) . Status ) ;
memset ( send_buf , 0 , TEST_BUF_LEN ) ;
memset ( recv_buf , 0xde , TEST_BUF_LEN ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
ReadFile ( server , recv_buf , TEST_BUF_LEN , & read , & o ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
WriteFile ( client , send_buf , TEST_BUF_LEN , & read , NULL ) ;
2007-12-17 00:02:12 +01:00
2018-09-30 23:59:44 +02:00
res = pNtRemoveIoCompletion ( h , & key , & value , & iosb , & timeout ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletion failed: %#x \n " , res ) ;
ok ( key = = CKEY_SECOND , " Invalid completion key: %#lx \n " , key ) ;
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 ( value = = ( ULONG_PTR ) & o , " Invalid completion value: %#lx \n " , value ) ;
ok ( ! memcmp ( send_buf , recv_buf , TEST_BUF_LEN ) ,
" Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x) \n " ,
recv_buf [ 0 ] , recv_buf [ 1 ] , recv_buf [ 2 ] , send_buf [ 0 ] , send_buf [ 1 ] , send_buf [ 2 ] ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
2007-12-17 00:02:12 +01:00
2018-09-30 23:59:44 +02:00
memset ( send_buf , 0 , TEST_BUF_LEN ) ;
memset ( recv_buf , 0xde , TEST_BUF_LEN ) ;
WriteFile ( client , send_buf , 2 , & read , NULL ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
ReadFile ( server , recv_buf , 2 , & read , & o ) ;
count = get_pending_msgs ( h ) ;
ok ( count = = 1 , " Unexpected msg count: %ld \n " , count ) ;
2007-12-17 00:02:12 +01:00
2018-09-30 23:59:44 +02:00
res = pNtRemoveIoCompletion ( h , & key , & value , & iosb , & timeout ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletion failed: %#x \n " , res ) ;
ok ( key = = CKEY_SECOND , " Invalid completion key: %#lx \n " , key ) ;
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 ( value = = ( ULONG_PTR ) & o , " Invalid completion value: %#lx \n " , value ) ;
ok ( ! memcmp ( send_buf , recv_buf , 2 ) ,
" Receive buffer (%02x %02x) did not match send buffer (%02x %02x) \n " ,
recv_buf [ 0 ] , recv_buf [ 1 ] , send_buf [ 0 ] , send_buf [ 1 ] ) ;
ReadFile ( server , recv_buf , TEST_BUF_LEN , & read , & o ) ;
CloseHandle ( server ) ;
count = get_pending_msgs ( h ) ;
ok ( count = = 1 , " Unexpected msg count: %ld \n " , count ) ;
2007-11-09 23:11:31 +01:00
2018-09-30 23:59:44 +02:00
res = pNtRemoveIoCompletion ( h , & key , & value , & iosb , & timeout ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletion failed: %#x \n " , res ) ;
ok ( key = = CKEY_SECOND , " Invalid completion key: %lx \n " , key ) ;
ok ( iosb . Information = = 0 , " Invalid iosb.Information: %ld \n " , iosb . Information ) ;
ok ( U ( iosb ) . Status = = STATUS_PIPE_BROKEN , " Invalid iosb.Status: %x \n " , U ( iosb ) . Status ) ;
ok ( value = = ( ULONG_PTR ) & o , " Invalid completion value: %lx \n " , value ) ;
CloseHandle ( client ) ;
2012-06-05 15:35:27 +02:00
/* test associating a completion port with a handle after an async is queued */
2018-09-30 23:59:44 +02:00
server = CreateNamedPipeA ( pipe_name , PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
4 , 1024 , 1024 , 1000 , NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed: %u \n " , GetLastError ( ) ) ;
client = CreateFileA ( pipe_name , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING ,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED , NULL ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " CreateFile failed: %u \n " , GetLastError ( ) ) ;
memset ( send_buf , 0 , TEST_BUF_LEN ) ;
memset ( recv_buf , 0xde , TEST_BUF_LEN ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
ReadFile ( server , recv_buf , TEST_BUF_LEN , & read , & o ) ;
2017-05-02 17:51:33 +02:00
2018-09-30 23:59:44 +02:00
U ( iosb ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( server , & iosb , & fci , sizeof ( fci ) , FileCompletionInformation ) ;
ok ( res = = STATUS_SUCCESS , " NtSetInformationFile failed: %x \n " , res ) ;
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " iosb.Status invalid: %x \n " , U ( iosb ) . Status ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
WriteFile ( client , send_buf , TEST_BUF_LEN , & read , NULL ) ;
res = pNtRemoveIoCompletion ( h , & key , & value , & iosb , & timeout ) ;
ok ( res = = STATUS_SUCCESS , " NtRemoveIoCompletion failed: %#x \n " , res ) ;
ok ( key = = CKEY_SECOND , " Invalid completion key: %#lx \n " , key ) ;
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 ( value = = ( ULONG_PTR ) & o , " Invalid completion value: %#lx \n " , value ) ;
ok ( ! memcmp ( send_buf , recv_buf , TEST_BUF_LEN ) ,
" Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x) \n " ,
recv_buf [ 0 ] , recv_buf [ 1 ] , recv_buf [ 2 ] , send_buf [ 0 ] , send_buf [ 1 ] , send_buf [ 2 ] ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
/* using APCs on handle with associated completion port is not allowed */
res = pNtReadFile ( server , NULL , apc , & apc_count , & iosb , recv_buf , sizeof ( recv_buf ) , NULL , NULL ) ;
ok ( res = = STATUS_INVALID_PARAMETER , " NtReadFile returned %x \n " , res ) ;
CloseHandle ( server ) ;
CloseHandle ( client ) ;
2017-05-02 17:51:33 +02:00
/* test associating a completion port with a handle after an async using APC is queued */
2018-09-30 23:59:44 +02:00
server = CreateNamedPipeA ( pipe_name , PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
4 , 1024 , 1024 , 1000 , NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed: %u \n " , GetLastError ( ) ) ;
client = CreateFileA ( pipe_name , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING ,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED , NULL ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " CreateFile failed: %u \n " , GetLastError ( ) ) ;
apc_count = 0 ;
memset ( send_buf , 0 , TEST_BUF_LEN ) ;
memset ( recv_buf , 0xde , TEST_BUF_LEN ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
res = pNtReadFile ( server , NULL , apc , & apc_count , & iosb , recv_buf , sizeof ( recv_buf ) , NULL , NULL ) ;
ok ( res = = STATUS_PENDING , " NtReadFile returned %x \n " , res ) ;
U ( iosb ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( server , & iosb , & fci , sizeof ( fci ) , FileCompletionInformation ) ;
ok ( res = = STATUS_SUCCESS , " NtSetInformationFile failed: %x \n " , res ) ;
ok ( U ( iosb ) . Status = = STATUS_SUCCESS , " iosb.Status invalid: %x \n " , U ( iosb ) . Status ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
WriteFile ( client , send_buf , TEST_BUF_LEN , & read , NULL ) ;
ok ( ! apc_count , " apc_count = %u \n " , apc_count ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
SleepEx ( 1 , TRUE ) ; /* alertable sleep */
ok ( apc_count = = 1 , " apc was not called \n " ) ;
count = get_pending_msgs ( h ) ;
ok ( ! count , " Unexpected msg count: %ld \n " , count ) ;
/* using APCs on handle with associated completion port is not allowed */
res = pNtReadFile ( server , NULL , apc , & apc_count , & iosb , recv_buf , sizeof ( recv_buf ) , NULL , NULL ) ;
ok ( res = = STATUS_INVALID_PARAMETER , " NtReadFile returned %x \n " , res ) ;
2012-06-05 15:35:27 +02:00
2018-09-30 23:59:44 +02:00
CloseHandle ( server ) ;
CloseHandle ( client ) ;
2018-09-30 23:59:45 +02:00
pNtClose ( h ) ;
2007-11-09 23:11:31 +01:00
}
2015-04-07 12:35:56 +02:00
static void test_file_full_size_information ( void )
{
IO_STATUS_BLOCK io ;
FILE_FS_FULL_SIZE_INFORMATION ffsi ;
FILE_FS_SIZE_INFORMATION fsi ;
HANDLE h ;
NTSTATUS res ;
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
memset ( & ffsi , 0 , sizeof ( ffsi ) ) ;
memset ( & fsi , 0 , sizeof ( fsi ) ) ;
/* Assume No Quota Settings configured on Wine Testbot */
res = pNtQueryVolumeInformationFile ( h , & io , & ffsi , sizeof ffsi , FileFsFullSizeInformation ) ;
todo_wine ok ( res = = STATUS_SUCCESS , " cannot get attributes, res %x \n " , res ) ;
res = pNtQueryVolumeInformationFile ( h , & io , & fsi , sizeof fsi , FileFsSizeInformation ) ;
ok ( res = = STATUS_SUCCESS , " cannot get attributes, res %x \n " , res ) ;
/* Test for FileFsSizeInformation */
ok ( fsi . TotalAllocationUnits . QuadPart > 0 ,
" [fsi] TotalAllocationUnits expected positive, got 0x%s \n " ,
2017-06-29 02:44:06 +02:00
wine_dbgstr_longlong ( fsi . TotalAllocationUnits . QuadPart ) ) ;
2015-04-07 12:35:56 +02:00
ok ( fsi . AvailableAllocationUnits . QuadPart > 0 ,
" [fsi] AvailableAllocationUnits expected positive, got 0x%s \n " ,
2017-06-29 02:44:06 +02:00
wine_dbgstr_longlong ( fsi . AvailableAllocationUnits . QuadPart ) ) ;
2015-04-07 12:35:56 +02:00
/* Assume file system is NTFS */
ok ( fsi . BytesPerSector = = 512 , " [fsi] BytesPerSector expected 512, got %d \n " , fsi . BytesPerSector ) ;
ok ( fsi . SectorsPerAllocationUnit = = 8 , " [fsi] SectorsPerAllocationUnit expected 8, got %d \n " , fsi . SectorsPerAllocationUnit ) ;
todo_wine
{
ok ( ffsi . TotalAllocationUnits . QuadPart > 0 ,
" [ffsi] TotalAllocationUnits expected positive, got negative value 0x%s \n " ,
2017-06-29 02:44:06 +02:00
wine_dbgstr_longlong ( ffsi . TotalAllocationUnits . QuadPart ) ) ;
2015-04-07 12:35:56 +02:00
ok ( ffsi . CallerAvailableAllocationUnits . QuadPart > 0 ,
" [ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s \n " ,
2017-06-29 02:44:06 +02:00
wine_dbgstr_longlong ( ffsi . CallerAvailableAllocationUnits . QuadPart ) ) ;
2015-04-07 12:35:56 +02:00
ok ( ffsi . ActualAvailableAllocationUnits . QuadPart > 0 ,
" [ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s \n " ,
2017-06-29 02:44:06 +02:00
wine_dbgstr_longlong ( ffsi . ActualAvailableAllocationUnits . QuadPart ) ) ;
2015-04-07 12:35:56 +02:00
ok ( ffsi . TotalAllocationUnits . QuadPart = = fsi . TotalAllocationUnits . QuadPart ,
" [ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s \n " ,
2017-06-29 02:44:06 +02:00
wine_dbgstr_longlong ( fsi . TotalAllocationUnits . QuadPart ) ,
wine_dbgstr_longlong ( ffsi . TotalAllocationUnits . QuadPart ) ) ;
2015-04-07 12:35:56 +02:00
ok ( ffsi . CallerAvailableAllocationUnits . QuadPart = = fsi . AvailableAllocationUnits . QuadPart ,
" [ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s \n " ,
2017-06-29 02:44:06 +02:00
wine_dbgstr_longlong ( fsi . AvailableAllocationUnits . QuadPart ) ,
wine_dbgstr_longlong ( ffsi . CallerAvailableAllocationUnits . QuadPart ) ) ;
2015-04-07 12:35:56 +02:00
}
/* Assume file system is NTFS */
todo_wine
{
ok ( ffsi . BytesPerSector = = 512 , " [ffsi] BytesPerSector expected 512, got %d \n " , ffsi . BytesPerSector ) ;
ok ( ffsi . SectorsPerAllocationUnit = = 8 , " [ffsi] SectorsPerAllocationUnit expected 8, got %d \n " , ffsi . SectorsPerAllocationUnit ) ;
}
CloseHandle ( h ) ;
}
2009-09-09 14:41:30 +02:00
static void test_file_basic_information ( void )
{
2019-08-09 08:50:33 +02:00
FILE_BASIC_INFORMATION fbi , fbi2 ;
2009-09-09 14:41:30 +02:00
IO_STATUS_BLOCK io ;
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
2019-08-09 08:50:33 +02:00
memset ( & fbi2 , 0 , sizeof ( fbi2 ) ) ;
fbi2 . LastWriteTime . QuadPart = - 1 ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( h , & io , & fbi2 , sizeof fbi2 , FileBasicInformation ) ;
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 ) ;
2019-08-09 08:50:34 +02:00
2019-08-09 08:50:33 +02:00
memset ( & fbi2 , 0 , sizeof ( fbi2 ) ) ;
res = pNtQueryInformationFile ( h , & io , & fbi2 , sizeof fbi2 , FileBasicInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes, res %x \n " , res ) ;
ok ( fbi2 . LastWriteTime . QuadPart = = fbi . LastWriteTime . QuadPart , " unexpected write time. \n " ) ;
memset ( & fbi2 , 0 , sizeof ( fbi2 ) ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( h , & io , & fbi2 , sizeof fbi2 , FileBasicInformation ) ;
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 ) ;
memset ( & fbi2 , 0 , sizeof ( fbi2 ) ) ;
res = pNtQueryInformationFile ( h , & io , & fbi2 , sizeof fbi2 , FileBasicInformation ) ;
ok ( res = = STATUS_SUCCESS , " can't get attributes, res %x \n " , res ) ;
ok ( fbi2 . LastWriteTime . QuadPart = = fbi . LastWriteTime . QuadPart , " unexpected write time. \n " ) ;
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 ) ;
}
2015-08-20 10:24:41 +02:00
static void delete_object ( WCHAR * path )
{
BOOL ret = DeleteFileW ( path ) ;
ok ( ret | | GetLastError ( ) = = ERROR_FILE_NOT_FOUND | | GetLastError ( ) = = ERROR_ACCESS_DENIED ,
" DeleteFileW failed with %u \n " , GetLastError ( ) ) ;
if ( ! ret & & GetLastError ( ) = = ERROR_ACCESS_DENIED )
{
ret = RemoveDirectoryW ( path ) ;
ok ( ret , " RemoveDirectoryW failed with %u \n " , GetLastError ( ) ) ;
}
}
2015-08-20 10:24:32 +02:00
static void test_file_rename_information ( void )
{
2015-08-20 10:24:41 +02:00
static const WCHAR foo_txtW [ ] = { ' \\ ' , ' f ' , ' o ' , ' o ' , ' . ' , ' t ' , ' x ' , ' t ' , 0 } ;
2015-08-20 10:24:32 +02:00
static const WCHAR fooW [ ] = { ' f ' , ' o ' , ' o ' , 0 } ;
2015-08-20 10:24:41 +02:00
WCHAR tmp_path [ MAX_PATH ] , oldpath [ MAX_PATH + 16 ] , newpath [ MAX_PATH + 16 ] , * filename , * p ;
2015-08-20 10:24:32 +02:00
FILE_RENAME_INFORMATION * fri ;
2015-08-20 10:24:41 +02:00
FILE_NAME_INFORMATION * fni ;
BOOL success , fileDeleted ;
2015-08-20 10:24:32 +02:00
UNICODE_STRING name_str ;
2015-08-20 10:24:41 +02:00
HANDLE handle , handle2 ;
2015-08-20 10:24:32 +02:00
IO_STATUS_BLOCK io ;
NTSTATUS res ;
GetTempPathW ( MAX_PATH , tmp_path ) ;
/* oldpath is a file, newpath doesn't exist */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
DeleteFileW ( newpath ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:32 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
2015-08-20 10:25:15 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-20 10:24:32 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( fileDeleted , " file should not exist \n " ) ;
2015-08-20 10:24:32 +02:00
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( ! fileDeleted , " file should exist \n " ) ;
2015-08-20 10:24:32 +02:00
2015-08-20 10:24:41 +02:00
fni = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ) ;
res = pNtQueryInformationFile ( handle , & io , fni , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) , FileNameInformation ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
fni - > FileName [ fni - > FileNameLength / sizeof ( WCHAR ) ] = 0 ;
2016-09-29 23:07:47 +02:00
ok ( ! lstrcmpiW ( fni - > FileName , newpath + 2 ) , " FileName expected %s, got %s \n " ,
2015-08-20 10:25:15 +02:00
wine_dbgstr_w ( newpath + 2 ) , wine_dbgstr_w ( fni - > FileName ) ) ;
2015-08-20 10:24:41 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , fni ) ;
2015-08-20 10:24:32 +02:00
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
2015-08-20 10:24:41 +02:00
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
2015-08-20 10:24:32 +02:00
/* oldpath is a file, newpath is a file, Replace = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:32 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-20 10:24:32 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
2015-08-20 10:24:41 +02:00
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
2015-08-20 10:24:32 +02:00
/* oldpath is a file, newpath is a file, Replace = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = TRUE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:32 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
2015-08-20 10:25:15 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-20 10:24:32 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( fileDeleted , " file should not exist \n " ) ;
2015-08-20 10:24:32 +02:00
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
2015-08-20 10:24:41 +02:00
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = TRUE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
DeleteFileW ( newpath ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
2015-08-20 10:25:15 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( fileDeleted , " file should not exist \n " ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( ! fileDeleted , " file should exist \n " ) ;
2015-08-20 10:24:41 +02:00
fni = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ) ;
res = pNtQueryInformationFile ( handle , & io , fni , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) , FileNameInformation ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
fni - > FileName [ fni - > FileNameLength / sizeof ( WCHAR ) ] = 0 ;
2016-09-29 23:07:47 +02:00
ok ( ! lstrcmpiW ( fni - > FileName , newpath + 2 ) , " FileName expected %s, got %s \n " ,
2015-08-20 10:25:15 +02:00
wine_dbgstr_w ( newpath + 2 ) , wine_dbgstr_w ( fni - > FileName ) ) ;
2015-08-20 10:24:41 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , fni ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
2015-08-20 10:24:32 +02:00
DeleteFileW ( oldpath ) ;
2015-08-20 10:24:41 +02:00
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
lstrcpyW ( newpath , oldpath ) ;
lstrcatW ( newpath , foo_txtW ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
2015-08-20 10:24:32 +02:00
DeleteFileW ( newpath ) ;
2015-08-20 10:24:41 +02:00
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
todo_wine ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
todo_wine ok ( ! fileDeleted , " file should exist \n " ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
todo_wine ok ( fileDeleted , " file should not exist \n " ) ;
2015-08-20 10:24:41 +02:00
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
2015-08-20 10:25:15 +02:00
if ( res = = STATUS_SUCCESS ) /* remove when Wine is fixed */
{
lstrcpyW ( oldpath , newpath ) ;
lstrcatW ( oldpath , foo_txtW ) ;
delete_object ( oldpath ) ;
}
2015-08-20 10:24:41 +02:00
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, Replace = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, Replace = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = TRUE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
2015-08-20 10:25:15 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( fileDeleted , " file should not exist \n " ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = TRUE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a directory, Replace = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a directory, Replace = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = TRUE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = TRUE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a directory, Replace = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a directory, Replace = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = TRUE ;
fri - > RootDirectory = NULL ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-20 10:25:15 +02:00
ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
for ( filename = newpath , p = newpath ; * p ; p + + )
if ( * p = = ' \\ ' ) filename = p + 1 ;
handle2 = CreateFileW ( tmp_path , 0 , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + lstrlenW ( filename ) * sizeof ( WCHAR ) ) ;
2020-03-06 03:47:12 +01:00
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = handle2 ;
2015-08-20 10:24:41 +02:00
fri - > FileNameLength = lstrlenW ( filename ) * sizeof ( WCHAR ) ;
memcpy ( fri - > FileName , filename , fri - > FileNameLength ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
2015-08-20 10:25:15 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( fileDeleted , " file should not exist \n " ) ;
2015-08-20 10:24:41 +02:00
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-20 10:25:15 +02:00
ok ( ! fileDeleted , " file should exist \n " ) ;
2015-08-20 10:24:41 +02:00
fni = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ) ;
res = pNtQueryInformationFile ( handle , & io , fni , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) , FileNameInformation ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
fni - > FileName [ fni - > FileNameLength / sizeof ( WCHAR ) ] = 0 ;
2020-03-20 18:15:24 +01:00
ok ( ! lstrcmpiW ( fni - > FileName , newpath + 2 ) , " FileName expected %s, got %s \n " ,
2015-08-20 10:24:41 +02:00
wine_dbgstr_w ( newpath + 2 ) , wine_dbgstr_w ( fni - > FileName ) ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fni ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
2020-03-06 03:47:14 +01:00
/* oldpath == newpath */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( oldpath , & name_str , NULL , NULL ) ;
fri = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
fri - > ReplaceIfExists = FALSE ;
fri - > RootDirectory = NULL ;
fri - > FileNameLength = name_str . Length ;
memcpy ( fri - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fri , sizeof ( FILE_RENAME_INFORMATION ) + fri - > FileNameLength , FileRenameInformation ) ;
2020-03-11 04:38:24 +01:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " got io status %#x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " got status %x \n " , res ) ;
2020-03-06 03:47:14 +01:00
ok ( GetFileAttributesW ( oldpath ) ! = INVALID_FILE_ATTRIBUTES , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fri ) ;
delete_object ( oldpath ) ;
2015-08-20 10:24:32 +02:00
}
2015-08-21 07:24:49 +02:00
static void test_file_link_information ( void )
{
static const WCHAR foo_txtW [ ] = { ' \\ ' , ' f ' , ' o ' , ' o ' , ' . ' , ' t ' , ' x ' , ' t ' , 0 } ;
static const WCHAR fooW [ ] = { ' f ' , ' o ' , ' o ' , 0 } ;
WCHAR tmp_path [ MAX_PATH ] , oldpath [ MAX_PATH + 16 ] , newpath [ MAX_PATH + 16 ] , * filename , * p ;
FILE_LINK_INFORMATION * fli ;
FILE_NAME_INFORMATION * fni ;
BOOL success , fileDeleted ;
UNICODE_STRING name_str ;
HANDLE handle , handle2 ;
IO_STATUS_BLOCK io ;
NTSTATUS res ;
GetTempPathW ( MAX_PATH , tmp_path ) ;
/* oldpath is a file, newpath doesn't exist */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
DeleteFileW ( newpath ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
2015-08-21 07:25:12 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-21 07:25:12 +02:00
ok ( ! fileDeleted , " file should exist \n " ) ;
2015-08-21 07:24:49 +02:00
fni = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ) ;
res = pNtQueryInformationFile ( handle , & io , fni , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) , FileNameInformation ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
fni - > FileName [ fni - > FileNameLength / sizeof ( WCHAR ) ] = 0 ;
2016-09-29 23:07:47 +02:00
ok ( ! lstrcmpiW ( fni - > FileName , oldpath + 2 ) , " FileName expected %s, got %s \n " ,
2015-08-21 07:24:49 +02:00
wine_dbgstr_w ( oldpath + 2 ) , wine_dbgstr_w ( fni - > FileName ) ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fni ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = TRUE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
2015-08-21 07:25:12 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = TRUE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
DeleteFileW ( newpath ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_FILE_IS_A_DIRECTORY , " res expected STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " file should not exist \n " ) ;
fni = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ) ;
res = pNtQueryInformationFile ( handle , & io , fni , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) , FileNameInformation ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
fni - > FileName [ fni - > FileNameLength / sizeof ( WCHAR ) ] = 0 ;
2016-09-29 23:07:47 +02:00
ok ( ! lstrcmpiW ( fni - > FileName , oldpath + 2 ) , " FileName expected %s, got %s \n " ,
2015-08-21 07:24:49 +02:00
wine_dbgstr_w ( oldpath + 2 ) , wine_dbgstr_w ( fni - > FileName ) ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fni ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
lstrcpyW ( newpath , oldpath ) ;
lstrcatW ( newpath , foo_txtW ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
DeleteFileW ( newpath ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_FILE_IS_A_DIRECTORY , " res expected STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " file should not exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION | | res = = STATUS_FILE_IS_A_DIRECTORY /* > Win XP */ ,
" res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION | | res = = STATUS_FILE_IS_A_DIRECTORY /* > Win XP */ ,
" res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = TRUE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_FILE_IS_A_DIRECTORY , " res expected STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = TRUE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_FILE_IS_A_DIRECTORY , " res expected STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION | | res = = STATUS_FILE_IS_A_DIRECTORY /* > Win XP */ ,
" res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = TRUE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_FILE_IS_A_DIRECTORY , " res expected STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( oldpath ) ;
success = CreateDirectoryW ( oldpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
handle2 = CreateFileW ( newpath , GENERIC_WRITE | DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = TRUE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_FILE_IS_A_DIRECTORY , " res expected STATUS_FILE_IS_A_DIRECTORY, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " res expected STATUS_OBJECT_NAME_COLLISION, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
success = CreateDirectoryW ( newpath , NULL ) ;
ok ( success ! = 0 , " failed to create temp directory \n " ) ;
pRtlDosPathNameToNtPathName_U ( newpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = TRUE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " io.Status expected 0xdeadbeef, got %x \n " , U ( io ) . Status ) ;
2015-08-21 07:25:12 +02:00
ok ( res = = STATUS_ACCESS_DENIED , " res expected STATUS_ACCESS_DENIED, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
/* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , newpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
DeleteFileW ( newpath ) ;
for ( filename = newpath , p = newpath ; * p ; p + + )
if ( * p = = ' \\ ' ) filename = p + 1 ;
handle2 = CreateFileW ( tmp_path , 0 , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_LINK_INFORMATION ) + lstrlenW ( filename ) * sizeof ( WCHAR ) ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = handle2 ;
fli - > FileNameLength = lstrlenW ( filename ) * sizeof ( WCHAR ) ;
memcpy ( fli - > FileName , filename , fli - > FileNameLength ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
2015-08-21 07:25:12 +02:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " io.Status expected STATUS_SUCCESS, got %x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
2015-08-21 07:24:49 +02:00
fileDeleted = GetFileAttributesW ( oldpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " file should exist \n " ) ;
fileDeleted = GetFileAttributesW ( newpath ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-21 07:25:12 +02:00
ok ( ! fileDeleted , " file should exist \n " ) ;
2015-08-21 07:24:49 +02:00
fni = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ) ;
res = pNtQueryInformationFile ( handle , & io , fni , sizeof ( FILE_NAME_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) , FileNameInformation ) ;
ok ( res = = STATUS_SUCCESS , " res expected STATUS_SUCCESS, got %x \n " , res ) ;
fni - > FileName [ fni - > FileNameLength / sizeof ( WCHAR ) ] = 0 ;
2016-09-29 23:07:47 +02:00
ok ( ! lstrcmpiW ( fni - > FileName , oldpath + 2 ) , " FileName expected %s, got %s \n " ,
2015-08-21 07:24:49 +02:00
wine_dbgstr_w ( oldpath + 2 ) , wine_dbgstr_w ( fni - > FileName ) ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fni ) ;
CloseHandle ( handle ) ;
CloseHandle ( handle2 ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
delete_object ( newpath ) ;
2020-03-11 04:38:22 +01:00
/* oldpath == newpath */
res = GetTempFileNameW ( tmp_path , fooW , 0 , oldpath ) ;
ok ( res ! = 0 , " failed to create temp file \n " ) ;
handle = CreateFileW ( oldpath , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " CreateFileW failed \n " ) ;
pRtlDosPathNameToNtPathName_U ( oldpath , & name_str , NULL , NULL ) ;
fli = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( FILE_RENAME_INFORMATION ) + name_str . Length ) ;
fli - > ReplaceIfExists = FALSE ;
fli - > RootDirectory = NULL ;
fli - > FileNameLength = name_str . Length ;
memcpy ( fli - > FileName , name_str . Buffer , name_str . Length ) ;
pRtlFreeUnicodeString ( & name_str ) ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
todo_wine ok ( U ( io ) . Status = = 0xdeadbeef , " got io status %#x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_OBJECT_NAME_COLLISION , " got status %x \n " , res ) ;
fli - > ReplaceIfExists = TRUE ;
U ( io ) . Status = 0xdeadbeef ;
res = pNtSetInformationFile ( handle , & io , fli , sizeof ( FILE_LINK_INFORMATION ) + fli - > FileNameLength , FileLinkInformation ) ;
2020-03-11 04:38:24 +01:00
ok ( U ( io ) . Status = = STATUS_SUCCESS , " got io status %#x \n " , U ( io ) . Status ) ;
ok ( res = = STATUS_SUCCESS , " got status %x \n " , res ) ;
2020-03-11 04:38:22 +01:00
ok ( GetFileAttributesW ( oldpath ) ! = INVALID_FILE_ATTRIBUTES , " file should exist \n " ) ;
CloseHandle ( handle ) ;
HeapFree ( GetProcessHeap ( ) , 0 , fli ) ;
delete_object ( oldpath ) ;
2015-08-21 07:24:49 +02:00
}
2009-09-09 14:41:30 +02:00
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 ) ;
}
2018-09-27 10:30:52 +02:00
static NTSTATUS nt_get_file_attrs ( const char * name , DWORD * attrs )
{
WCHAR nameW [ MAX_PATH ] ;
FILE_BASIC_INFORMATION info ;
UNICODE_STRING nt_name ;
OBJECT_ATTRIBUTES attr ;
NTSTATUS status ;
MultiByteToWideChar ( CP_ACP , 0 , name , - 1 , nameW , MAX_PATH ) ;
* attrs = INVALID_FILE_ATTRIBUTES ;
if ( ! pRtlDosPathNameToNtPathName_U ( nameW , & nt_name , NULL , NULL ) )
return STATUS_UNSUCCESSFUL ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = 0 ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . ObjectName = & nt_name ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
status = pNtQueryAttributesFile ( & attr , & info ) ;
pRtlFreeUnicodeString ( & nt_name ) ;
if ( status = = STATUS_SUCCESS )
* attrs = info . FileAttributes ;
return status ;
}
2013-08-12 17:09:13 +02:00
static void test_file_disposition_information ( void )
{
2013-09-24 10:12:39 +02:00
char tmp_path [ MAX_PATH ] , buffer [ MAX_PATH + 16 ] ;
2013-08-12 17:09:13 +02:00
DWORD dirpos ;
2018-09-27 10:30:52 +02:00
HANDLE handle , handle2 , handle3 ;
2013-08-12 17:09:13 +02:00
NTSTATUS res ;
IO_STATUS_BLOCK io ;
FILE_DISPOSITION_INFORMATION fdi ;
BOOL fileDeleted ;
2015-06-10 07:47:51 +02:00
DWORD fdi2 ;
2013-08-12 17:09:13 +02:00
2013-09-24 10:12:39 +02:00
GetTempPathA ( MAX_PATH , tmp_path ) ;
2015-06-10 07:47:51 +02:00
/* tests for info struct size */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
res = pNtSetInformationFile ( handle , & io , & fdi , 0 , FileDispositionInformation ) ;
todo_wine
ok ( res = = STATUS_INFO_LENGTH_MISMATCH , " expected STATUS_INFO_LENGTH_MISMATCH, got %x \n " , res ) ;
fdi2 = 0x100 ;
res = pNtSetInformationFile ( handle , & io , & fdi2 , sizeof ( fdi2 ) , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %x \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
DeleteFileA ( buffer ) ;
2013-08-12 17:09:13 +02:00
/* cannot set disposition on file not opened with delete access */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
handle = CreateFileA ( buffer , GENERIC_WRITE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
res = pNtQueryInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_INVALID_INFO_CLASS | | res = = STATUS_NOT_IMPLEMENTED , " Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x) \n " , res ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_ACCESS_DENIED , " unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x) \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
DeleteFileA ( buffer ) ;
/* can set disposition on file opened with proper access */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
2018-09-27 10:30:52 +02:00
/* file exists until all handles to it get closed */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , FILE_SHARE_DELETE , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
handle2 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " failed to open temp file \n " ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
res = nt_get_file_attrs ( buffer , & fdi2 ) ;
todo_wine
ok ( res = = STATUS_DELETE_PENDING , " got %#x \n " , res ) ;
/* can't open the deleted file */
handle3 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , 0 , 0 ) ;
todo_wine
ok ( handle3 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
if ( handle3 ! = INVALID_HANDLE_VALUE )
CloseHandle ( handle3 ) ;
todo_wine
ok ( GetLastError ( ) = = ERROR_ACCESS_DENIED , " got %u \n " , GetLastError ( ) ) ;
/* can't open the deleted file (wrong sharing mode) */
handle3 = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( handle3 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
todo_wine
ok ( GetLastError ( ) = = ERROR_ACCESS_DENIED , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
CloseHandle ( handle2 ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
/* file exists until all handles to it get closed */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , FILE_SHARE_DELETE , NULL , CREATE_ALWAYS , FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
/* can open the marked for delete file (proper sharing mode) */
handle2 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " failed to open temp file \n " ) ;
res = nt_get_file_attrs ( buffer , & fdi2 ) ;
ok ( res = = STATUS_SUCCESS , " got %#x \n " , res ) ;
/* can't open the marked for delete file (wrong sharing mode) */
handle3 = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( handle3 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_SHARING_VIOLATION , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
CloseHandle ( handle2 ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
2013-08-12 17:09:13 +02:00
2015-08-19 11:18:27 +02:00
/* cannot set disposition on readonly file */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
DeleteFileA ( buffer ) ;
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , FILE_ATTRIBUTE_READONLY , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_CANNOT_DELETE , " unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x) \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
SetFileAttributesA ( buffer , FILE_ATTRIBUTE_NORMAL ) ;
DeleteFileA ( buffer ) ;
2013-08-12 17:09:13 +02:00
/* cannot set disposition on readonly file */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , FILE_ATTRIBUTE_READONLY , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
todo_wine
ok ( res = = STATUS_CANNOT_DELETE , " unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x) \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
2015-08-19 11:18:01 +02:00
todo_wine
2013-08-12 17:09:13 +02:00
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
SetFileAttributesA ( buffer , FILE_ATTRIBUTE_NORMAL ) ;
DeleteFileA ( buffer ) ;
/* can set disposition on file and then reset it */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
fdi . DoDeleteFile = FALSE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
DeleteFileA ( buffer ) ;
2018-09-27 10:30:49 +02:00
/* can't reset disposition if delete-on-close flag is specified */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
fdi . DoDeleteFile = FALSE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
2018-09-27 10:30:49 +02:00
/* can't reset disposition on duplicated handle if delete-on-close flag is specified */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
2013-08-17 10:28:45 +02:00
ok ( DuplicateHandle ( GetCurrentProcess ( ) , handle , GetCurrentProcess ( ) , & handle2 , 0 , FALSE , DUPLICATE_SAME_ACCESS ) , " DuplicateHandle failed \n " ) ;
2013-08-12 17:09:13 +02:00
CloseHandle ( handle ) ;
2018-09-27 10:30:49 +02:00
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
2013-08-12 17:09:13 +02:00
fdi . DoDeleteFile = FALSE ;
res = pNtSetInformationFile ( handle2 , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
CloseHandle ( handle2 ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
2018-09-27 10:30:52 +02:00
/* DeleteFile fails for wrong sharing mode */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
fileDeleted = DeleteFileA ( buffer ) ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
ok ( GetLastError ( ) = = ERROR_SHARING_VIOLATION , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
2013-08-12 17:09:13 +02:00
DeleteFileA ( buffer ) ;
2018-09-27 10:30:52 +02:00
/* DeleteFile succeeds for proper sharing mode */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
handle = CreateFileA ( buffer , GENERIC_WRITE | DELETE , FILE_SHARE_DELETE , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to create temp file \n " ) ;
fileDeleted = DeleteFileA ( buffer ) ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " File shouldn't have been deleted \n " ) ;
res = nt_get_file_attrs ( buffer , & fdi2 ) ;
todo_wine
ok ( res = = STATUS_DELETE_PENDING , " got %#x \n " , res ) ;
/* can't open the deleted file */
handle2 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( handle2 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
todo_wine
ok ( GetLastError ( ) = = ERROR_ACCESS_DENIED , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
2013-08-12 17:09:13 +02:00
/* can set disposition on a directory opened with proper access */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
DeleteFileA ( buffer ) ;
ok ( CreateDirectoryA ( buffer , NULL ) , " CreateDirectory failed \n " ) ;
handle = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " Directory should have been deleted \n " ) ;
2018-09-27 10:30:49 +02:00
/* RemoveDirectory fails for wrong sharing mode */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
DeleteFileA ( buffer ) ;
ok ( CreateDirectoryA ( buffer , NULL ) , " CreateDirectory failed \n " ) ;
handle = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
2018-09-27 10:30:49 +02:00
fileDeleted = RemoveDirectoryA ( buffer ) ;
ok ( ! fileDeleted , " Directory shouldn't have been deleted \n " ) ;
ok ( GetLastError ( ) = = ERROR_SHARING_VIOLATION , " got %u \n " , GetLastError ( ) ) ;
2013-08-12 17:09:13 +02:00
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " Directory shouldn't have been deleted \n " ) ;
RemoveDirectoryA ( buffer ) ;
2018-09-27 10:30:52 +02:00
/* RemoveDirectory succeeds for proper sharing mode */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
DeleteFileA ( buffer ) ;
ok ( CreateDirectoryA ( buffer , NULL ) , " CreateDirectory failed \n " ) ;
handle = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
fileDeleted = RemoveDirectoryA ( buffer ) ;
ok ( fileDeleted , " Directory should have been deleted \n " ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " Directory shouldn't have been deleted \n " ) ;
res = nt_get_file_attrs ( buffer , & fdi2 ) ;
todo_wine
ok ( res = = STATUS_DELETE_PENDING , " got %#x \n " , res ) ;
/* can't open the deleted directory */
handle2 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
2020-07-08 12:47:46 +02:00
todo_wine
2018-09-27 10:30:52 +02:00
ok ( handle2 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
todo_wine
ok ( GetLastError ( ) = = ERROR_ACCESS_DENIED , " got %u \n " , GetLastError ( ) ) ;
2020-07-08 12:47:46 +02:00
if ( handle2 ! = INVALID_HANDLE_VALUE ) CloseHandle ( handle2 ) ;
2018-09-27 10:30:52 +02:00
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " Directory should have been deleted \n " ) ;
/* directory exists until all handles to it get closed */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
DeleteFileA ( buffer ) ;
ok ( CreateDirectoryA ( buffer , NULL ) , " CreateDirectory failed \n " ) ;
handle = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
handle2 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle2 , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_SUCCESS , " unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x) \n " , res ) ;
res = nt_get_file_attrs ( buffer , & fdi2 ) ;
todo_wine
ok ( res = = STATUS_DELETE_PENDING , " got %#x \n " , res ) ;
/* can't open the deleted directory */
handle3 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
todo_wine
ok ( handle3 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
if ( handle3 ! = INVALID_HANDLE_VALUE )
CloseHandle ( handle3 ) ;
todo_wine
ok ( GetLastError ( ) = = ERROR_ACCESS_DENIED , " got %u \n " , GetLastError ( ) ) ;
/* can't open the deleted directory (wrong sharing mode) */
handle3 = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle3 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
todo_wine
ok ( GetLastError ( ) = = ERROR_ACCESS_DENIED , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( handle2 ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " Directory shouldn't have been deleted \n " ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " Directory should have been deleted \n " ) ;
/* directory exists until all handles to it get closed */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
DeleteFileA ( buffer ) ;
ok ( CreateDirectoryA ( buffer , NULL ) , " CreateDirectory failed \n " ) ;
handle = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
/* can open the marked for delete directory (proper sharing mode) */
handle2 = CreateFileA ( buffer , DELETE , FILE_SHARE_DELETE , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle2 ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
/* can't open the marked for delete file (wrong sharing mode) */
handle3 = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle3 = = INVALID_HANDLE_VALUE , " CreateFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_SHARING_VIOLATION , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " Directory shouldn't have been deleted \n " ) ;
CloseHandle ( handle2 ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( fileDeleted , " Directory should have been deleted \n " ) ;
2018-10-02 09:52:18 +02:00
/* can open a non-empty directory with FILE_FLAG_DELETE_ON_CLOSE */
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
DeleteFileA ( buffer ) ;
ok ( CreateDirectoryA ( buffer , NULL ) , " CreateDirectory failed \n " ) ;
dirpos = lstrlenA ( buffer ) ;
lstrcpyA ( buffer + dirpos , " \\ tst " ) ;
handle2 = CreateFileA ( buffer , GENERIC_WRITE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
CloseHandle ( handle2 ) ;
buffer [ dirpos ] = ' \0 ' ;
handle = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
SetLastError ( 0xdeadbeef ) ;
CloseHandle ( handle ) ;
ok ( GetLastError ( ) = = 0xdeadbeef , " got %u \n " , GetLastError ( ) ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " Directory shouldn't have been deleted \n " ) ;
buffer [ dirpos ] = ' \\ ' ;
fileDeleted = DeleteFileA ( buffer ) ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
buffer [ dirpos ] = ' \0 ' ;
fileDeleted = RemoveDirectoryA ( buffer ) ;
ok ( fileDeleted , " Directory should have been deleted \n " ) ;
2013-08-12 17:09:13 +02:00
/* cannot set disposition on a non-empty directory */
2013-09-24 10:12:39 +02:00
GetTempFileNameA ( tmp_path , " dis " , 0 , buffer ) ;
2013-08-12 17:09:13 +02:00
DeleteFileA ( buffer ) ;
ok ( CreateDirectoryA ( buffer , NULL ) , " CreateDirectory failed \n " ) ;
handle = CreateFileA ( buffer , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 ) ;
ok ( handle ! = INVALID_HANDLE_VALUE , " failed to open a directory \n " ) ;
dirpos = lstrlenA ( buffer ) ;
lstrcpyA ( buffer + dirpos , " \\ tst " ) ;
handle2 = CreateFileA ( buffer , GENERIC_WRITE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
CloseHandle ( handle2 ) ;
fdi . DoDeleteFile = TRUE ;
res = pNtSetInformationFile ( handle , & io , & fdi , sizeof fdi , FileDispositionInformation ) ;
ok ( res = = STATUS_DIRECTORY_NOT_EMPTY , " unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x) \n " , res ) ;
2018-10-02 09:52:18 +02:00
fileDeleted = DeleteFileA ( buffer ) ;
ok ( fileDeleted , " File should have been deleted \n " ) ;
2013-08-12 17:09:13 +02:00
buffer [ dirpos ] = ' \0 ' ;
CloseHandle ( handle ) ;
fileDeleted = GetFileAttributesA ( buffer ) = = INVALID_FILE_ATTRIBUTES & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ;
ok ( ! fileDeleted , " Directory shouldn't have been deleted \n " ) ;
2018-10-02 09:52:18 +02:00
fileDeleted = RemoveDirectoryA ( buffer ) ;
ok ( fileDeleted , " Directory should have been deleted \n " ) ;
2013-08-12 17:09:13 +02:00
}
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 ) ;
}
2018-10-25 14:55:57 +02:00
# define test_completion_flags(a,b) _test_completion_flags(__LINE__,a,b)
static void _test_completion_flags ( unsigned line , HANDLE handle , DWORD expected_flags )
{
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info ;
IO_STATUS_BLOCK io ;
NTSTATUS status ;
info . Flags = 0xdeadbeef ;
status = pNtQueryInformationFile ( handle , & io , & info , sizeof ( info ) ,
FileIoCompletionNotificationInformation ) ;
ok_ ( __FILE__ , line ) ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
ok_ ( __FILE__ , line ) ( io . Status = = STATUS_SUCCESS , " Status = %x \n " , io . Status ) ;
ok_ ( __FILE__ , line ) ( io . Information = = sizeof ( info ) , " Information = %lu \n " , io . Information ) ;
/* FILE_SKIP_SET_USER_EVENT_ON_FAST_IO is not supported on win2k3 */
ok_ ( __FILE__ , line ) ( ( info . Flags & ~ FILE_SKIP_SET_USER_EVENT_ON_FAST_IO ) = = expected_flags ,
" got %08x \n " , info . Flags ) ;
}
2017-02-17 05:14:59 +01:00
static void test_file_completion_information ( void )
{
2019-02-20 19:50:15 +01:00
DECLSPEC_ALIGN ( TEST_OVERLAPPED_READ_SIZE ) static unsigned char aligned_buf [ TEST_OVERLAPPED_READ_SIZE ] ;
2017-02-17 05:14:59 +01:00
static const char buf [ ] = " testdata " ;
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info ;
OVERLAPPED ov , * pov ;
IO_STATUS_BLOCK io ;
NTSTATUS status ;
DWORD num_bytes ;
HANDLE port , h ;
ULONG_PTR key ;
BOOL ret ;
int i ;
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) - 1 , FileIoCompletionNotificationInformation ) ;
2018-10-25 14:55:24 +02:00
ok ( status = = STATUS_INFO_LENGTH_MISMATCH | | broken ( status = = STATUS_INVALID_INFO_CLASS /* XP */ ) ,
2017-02-17 05:14:59 +01:00
" expected STATUS_INFO_LENGTH_MISMATCH, got %08x \n " , status ) ;
2018-10-25 14:55:24 +02:00
if ( status ! = STATUS_INFO_LENGTH_MISMATCH )
2017-02-17 05:14:59 +01:00
{
2018-10-25 14:55:24 +02:00
win_skip ( " FileIoCompletionNotificationInformation class not supported \n " ) ;
2017-02-17 05:14:59 +01:00
CloseHandle ( h ) ;
return ;
}
info . Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " expected STATUS_INVALID_PARAMETER, got %08x \n " , status ) ;
CloseHandle ( h ) ;
if ( ! ( h = create_temp_file ( FILE_FLAG_OVERLAPPED ) ) ) return ;
info . Flags = FILE_SKIP_SET_EVENT_ON_HANDLE ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
2018-10-25 14:55:57 +02:00
test_completion_flags ( h , FILE_SKIP_SET_EVENT_ON_HANDLE ) ;
2017-02-17 05:14:59 +01:00
info . Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
2018-10-25 14:55:57 +02:00
test_completion_flags ( h , FILE_SKIP_SET_EVENT_ON_HANDLE ) ;
info . Flags = 0 ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
test_completion_flags ( h , FILE_SKIP_SET_EVENT_ON_HANDLE ) ;
info . Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
test_completion_flags ( h , FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ) ;
info . Flags = 0xdeadbeef ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
test_completion_flags ( h , FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ) ;
2017-02-17 05:14:59 +01:00
CloseHandle ( h ) ;
if ( ! ( h = create_temp_file ( FILE_FLAG_OVERLAPPED ) ) ) return ;
2018-10-25 14:55:57 +02:00
test_completion_flags ( h , 0 ) ;
2017-02-17 05:14:59 +01:00
memset ( & ov , 0 , sizeof ( ov ) ) ;
ov . hEvent = CreateEventA ( NULL , TRUE , FALSE , NULL ) ;
port = CreateIoCompletionPort ( h , NULL , 0xdeadbeef , 0 ) ;
ok ( port ! = NULL , " CreateIoCompletionPort failed, error %u \n " , GetLastError ( ) ) ;
for ( i = 0 ; i < 10 ; i + + )
{
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( h , buf , sizeof ( buf ) , & num_bytes , & ov ) ;
2019-03-05 13:16:46 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* Before Vista */ ,
2019-03-05 13:16:45 +01:00
" Unexpected result %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2017-02-17 05:14:59 +01:00
if ( ret | | GetLastError ( ) ! = ERROR_IO_PENDING ) break ;
ret = GetOverlappedResult ( h , & ov , & num_bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult failed, error %u \n " , GetLastError ( ) ) ;
ret = GetQueuedCompletionStatus ( port , & num_bytes , & key , & pov , 1000 ) ;
ok ( ret , " GetQueuedCompletionStatus failed, error %u \n " , GetLastError ( ) ) ;
ret = FALSE ;
}
if ( ret )
{
ok ( num_bytes = = sizeof ( buf ) , " expected sizeof(buf), got %u \n " , num_bytes ) ;
key = 0 ;
pov = NULL ;
ret = GetQueuedCompletionStatus ( port , & num_bytes , & key , & pov , 1000 ) ;
ok ( ret , " GetQueuedCompletionStatus failed, error %u \n " , GetLastError ( ) ) ;
ok ( key = = 0xdeadbeef , " expected 0xdeadbeef, got %lx \n " , key ) ;
ok ( pov = = & ov , " expected %p, got %p \n " , & ov , pov ) ;
}
info . Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
2018-10-25 14:55:57 +02:00
test_completion_flags ( h , FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ) ;
2017-02-17 05:14:59 +01:00
for ( i = 0 ; i < 10 ; i + + )
{
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( h , buf , sizeof ( buf ) , & num_bytes , & ov ) ;
2019-03-05 13:16:46 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* Before Vista */ ,
2019-03-05 13:16:45 +01:00
" Unexpected result %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2017-02-17 05:14:59 +01:00
if ( ret | | GetLastError ( ) ! = ERROR_IO_PENDING ) break ;
ret = GetOverlappedResult ( h , & ov , & num_bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult failed, error %u \n " , GetLastError ( ) ) ;
ret = FALSE ;
}
if ( ret )
{
ok ( num_bytes = = sizeof ( buf ) , " expected sizeof(buf), got %u \n " , num_bytes ) ;
pov = ( void * ) 0xdeadbeef ;
ret = GetQueuedCompletionStatus ( port , & num_bytes , & key , & pov , 500 ) ;
ok ( ! ret , " GetQueuedCompletionStatus succeeded \n " ) ;
ok ( pov = = NULL , " expected NULL, got %p \n " , pov ) ;
}
info . Flags = 0 ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
2018-10-25 14:55:57 +02:00
test_completion_flags ( h , FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ) ;
2017-02-17 05:14:59 +01:00
for ( i = 0 ; i < 10 ; i + + )
{
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( h , buf , sizeof ( buf ) , & num_bytes , & ov ) ;
2019-03-05 13:16:46 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* Before Vista */ ,
2019-03-05 13:16:45 +01:00
" Unexpected result %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2017-02-17 05:14:59 +01:00
if ( ret | | GetLastError ( ) ! = ERROR_IO_PENDING ) break ;
ret = GetOverlappedResult ( h , & ov , & num_bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult failed, error %u \n " , GetLastError ( ) ) ;
ret = GetQueuedCompletionStatus ( port , & num_bytes , & key , & pov , 1000 ) ;
ok ( ret , " GetQueuedCompletionStatus failed, error %u \n " , GetLastError ( ) ) ;
ret = FALSE ;
}
if ( ret )
{
ok ( num_bytes = = sizeof ( buf ) , " expected sizeof(buf), got %u \n " , num_bytes ) ;
pov = ( void * ) 0xdeadbeef ;
ret = GetQueuedCompletionStatus ( port , & num_bytes , & key , & pov , 1000 ) ;
ok ( ! ret , " GetQueuedCompletionStatus succeeded \n " ) ;
ok ( pov = = NULL , " expected NULL, got %p \n " , pov ) ;
}
2019-02-20 19:50:15 +01:00
CloseHandle ( port ) ;
CloseHandle ( h ) ;
if ( ! ( h = create_temp_file ( FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING ) ) )
return ;
port = CreateIoCompletionPort ( h , NULL , 0xdeadbeef , 0 ) ;
ok ( port ! = NULL , " CreateIoCompletionPort failed, error %u. \n " , GetLastError ( ) ) ;
info . Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ;
status = pNtSetInformationFile ( h , & io , & info , sizeof ( info ) , FileIoCompletionNotificationInformation ) ;
ok ( status = = STATUS_SUCCESS , " Expected STATUS_SUCCESS, got %#x. \n " , status ) ;
test_completion_flags ( h , FILE_SKIP_COMPLETION_PORT_ON_SUCCESS ) ;
ret = WriteFile ( h , aligned_buf , sizeof ( aligned_buf ) , & num_bytes , & ov ) ;
if ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING )
{
ret = GetOverlappedResult ( h , & ov , & num_bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult failed, error %u. \n " , GetLastError ( ) ) ;
ok ( num_bytes = = sizeof ( aligned_buf ) , " expected sizeof(aligned_buf), got %u. \n " , num_bytes ) ;
ret = GetQueuedCompletionStatus ( port , & num_bytes , & key , & pov , 1000 ) ;
ok ( ret , " GetQueuedCompletionStatus failed, error %u. \n " , GetLastError ( ) ) ;
}
ok ( num_bytes = = sizeof ( aligned_buf ) , " expected sizeof(buf), got %u. \n " , num_bytes ) ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( h , aligned_buf , sizeof ( aligned_buf ) , & num_bytes , & ov ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING , " Unexpected result, ret %#x, error %u. \n " ,
ret , GetLastError ( ) ) ;
ret = GetOverlappedResult ( h , & ov , & num_bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult failed, error %u. \n " , GetLastError ( ) ) ;
ret = GetQueuedCompletionStatus ( port , & num_bytes , & key , & pov , 1000 ) ;
2019-02-21 15:10:14 +01:00
ok ( ret , " GetQueuedCompletionStatus failed, error %u. \n " , GetLastError ( ) ) ;
2019-02-20 19:50:15 +01:00
2017-02-17 05:14:59 +01:00
CloseHandle ( ov . hEvent ) ;
CloseHandle ( port ) ;
CloseHandle ( h ) ;
}
2017-02-16 18:17:05 +01:00
static void test_file_id_information ( void )
{
BY_HANDLE_FILE_INFORMATION info ;
FILE_ID_INFORMATION fid ;
IO_STATUS_BLOCK io ;
NTSTATUS status ;
DWORD * dwords ;
HANDLE h ;
BOOL ret ;
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
memset ( & fid , 0x11 , sizeof ( fid ) ) ;
status = pNtQueryInformationFile ( h , & io , & fid , sizeof ( fid ) , FileIdInformation ) ;
if ( status = = STATUS_NOT_IMPLEMENTED | | status = = STATUS_INVALID_INFO_CLASS )
{
2017-02-16 18:17:51 +01:00
win_skip ( " FileIdInformation not supported \n " ) ;
2017-02-16 18:17:05 +01:00
CloseHandle ( h ) ;
return ;
}
memset ( & info , 0x22 , sizeof ( info ) ) ;
ret = GetFileInformationByHandle ( h , & info ) ;
ok ( ret , " GetFileInformationByHandle failed \n " ) ;
dwords = ( DWORD * ) & fid . VolumeSerialNumber ;
ok ( dwords [ 0 ] = = info . dwVolumeSerialNumber , " expected %08x, got %08x \n " ,
info . dwVolumeSerialNumber , dwords [ 0 ] ) ;
ok ( dwords [ 1 ] ! = 0x11111111 , " expected != 0x11111111 \n " ) ;
dwords = ( DWORD * ) & fid . FileId ;
ok ( dwords [ 0 ] = = info . nFileIndexLow , " expected %08x, got %08x \n " , info . nFileIndexLow , dwords [ 0 ] ) ;
ok ( dwords [ 1 ] = = info . nFileIndexHigh , " expected %08x, got %08x \n " , info . nFileIndexHigh , dwords [ 1 ] ) ;
ok ( dwords [ 2 ] = = 0 , " expected 0, got %08x \n " , dwords [ 2 ] ) ;
ok ( dwords [ 3 ] = = 0 , " expected 0, got %08x \n " , dwords [ 3 ] ) ;
CloseHandle ( h ) ;
}
2017-03-07 17:01:52 +01:00
static void test_file_access_information ( void )
{
FILE_ACCESS_INFORMATION info ;
IO_STATUS_BLOCK io ;
NTSTATUS status ;
HANDLE h ;
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
status = pNtQueryInformationFile ( h , & io , & info , sizeof ( info ) - 1 , FileAccessInformation ) ;
ok ( status = = STATUS_INFO_LENGTH_MISMATCH , " expected STATUS_INFO_LENGTH_MISMATCH, got %08x \n " , status ) ;
status = pNtQueryInformationFile ( ( HANDLE ) 0xdeadbeef , & io , & info , sizeof ( info ) , FileAccessInformation ) ;
ok ( status = = STATUS_INVALID_HANDLE , " expected STATUS_INVALID_HANDLE, got %08x \n " , status ) ;
memset ( & info , 0x11 , sizeof ( info ) ) ;
status = pNtQueryInformationFile ( h , & io , & info , sizeof ( info ) , FileAccessInformation ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
ok ( info . AccessFlags = = 0x13019f , " got %08x \n " , info . AccessFlags ) ;
CloseHandle ( h ) ;
}
2019-09-26 20:34:33 +02:00
static void test_file_attribute_tag_information ( void )
{
FILE_ATTRIBUTE_TAG_INFORMATION info ;
FILE_BASIC_INFORMATION fbi = { } ;
IO_STATUS_BLOCK io ;
NTSTATUS status ;
HANDLE h ;
if ( ! ( h = create_temp_file ( 0 ) ) ) return ;
status = pNtQueryInformationFile ( h , & io , & info , sizeof ( info ) - 1 , FileAttributeTagInformation ) ;
ok ( status = = STATUS_INFO_LENGTH_MISMATCH , " got %#x \n " , status ) ;
status = pNtQueryInformationFile ( ( HANDLE ) 0xdeadbeef , & io , & info , sizeof ( info ) , FileAttributeTagInformation ) ;
ok ( status = = STATUS_INVALID_HANDLE , " got %#x \n " , status ) ;
memset ( & info , 0x11 , sizeof ( info ) ) ;
status = pNtQueryInformationFile ( h , & io , & info , sizeof ( info ) , FileAttributeTagInformation ) ;
ok ( status = = STATUS_SUCCESS , " got %#x \n " , status ) ;
info . FileAttributes & = ~ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED ;
ok ( info . FileAttributes = = FILE_ATTRIBUTE_ARCHIVE , " got attributes %#x \n " , info . FileAttributes ) ;
ok ( ! info . ReparseTag , " got reparse tag %#x \n " , info . ReparseTag ) ;
fbi . FileAttributes = FILE_ATTRIBUTE_SYSTEM ;
status = pNtSetInformationFile ( h , & io , & fbi , sizeof ( fbi ) , FileBasicInformation ) ;
ok ( status = = STATUS_SUCCESS , " got %#x \n " , status ) ;
memset ( & info , 0x11 , sizeof ( info ) ) ;
status = pNtQueryInformationFile ( h , & io , & info , sizeof ( info ) , FileAttributeTagInformation ) ;
ok ( status = = STATUS_SUCCESS , " got %#x \n " , status ) ;
todo_wine ok ( info . FileAttributes = = FILE_ATTRIBUTE_SYSTEM , " got attributes %#x \n " , info . FileAttributes ) ;
ok ( ! info . ReparseTag , " got reparse tag %#x \n " , info . ReparseTag ) ;
fbi . FileAttributes = FILE_ATTRIBUTE_HIDDEN ;
status = pNtSetInformationFile ( h , & io , & fbi , sizeof fbi , FileBasicInformation ) ;
ok ( status = = STATUS_SUCCESS , " got %#x \n " , status ) ;
memset ( & info , 0x11 , sizeof ( info ) ) ;
status = pNtQueryInformationFile ( h , & io , & info , sizeof ( info ) , FileAttributeTagInformation ) ;
ok ( status = = STATUS_SUCCESS , " got %#x \n " , status ) ;
todo_wine ok ( info . FileAttributes = = FILE_ATTRIBUTE_HIDDEN , " got attributes %#x \n " , info . FileAttributes ) ;
ok ( ! info . ReparseTag , " got reparse tag %#x \n " , info . ReparseTag ) ;
CloseHandle ( h ) ;
}
2018-10-29 15:48:30 +01:00
static void test_file_mode ( void )
{
UNICODE_STRING file_name , pipe_dev_name , mountmgr_dev_name , mailslot_dev_name ;
WCHAR tmp_path [ MAX_PATH ] , dos_file_name [ MAX_PATH ] ;
FILE_MODE_INFORMATION mode ;
OBJECT_ATTRIBUTES attr ;
IO_STATUS_BLOCK io ;
HANDLE file ;
unsigned i ;
DWORD res , access ;
NTSTATUS status ;
const struct {
UNICODE_STRING * file_name ;
ULONG options ;
ULONG mode ;
BOOL todo ;
} option_tests [ ] = {
{ & file_name , 0 , 0 } ,
{ & file_name , FILE_NON_DIRECTORY_FILE , 0 } ,
{ & file_name , FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY , FILE_SEQUENTIAL_ONLY } ,
{ & file_name , FILE_WRITE_THROUGH , FILE_WRITE_THROUGH } ,
{ & file_name , FILE_SYNCHRONOUS_IO_ALERT , FILE_SYNCHRONOUS_IO_ALERT } ,
{ & file_name , FILE_NO_INTERMEDIATE_BUFFERING , FILE_NO_INTERMEDIATE_BUFFERING } ,
{ & file_name , FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE , FILE_SYNCHRONOUS_IO_NONALERT } ,
{ & file_name , FILE_DELETE_ON_CLOSE , 0 } ,
{ & file_name , FILE_RANDOM_ACCESS | FILE_NO_COMPRESSION , 0 } ,
{ & pipe_dev_name , 0 , 0 } ,
2018-10-29 15:49:47 +01:00
{ & pipe_dev_name , FILE_SYNCHRONOUS_IO_ALERT , FILE_SYNCHRONOUS_IO_ALERT } ,
2018-10-29 15:48:30 +01:00
{ & mailslot_dev_name , 0 , 0 } ,
{ & mailslot_dev_name , FILE_SYNCHRONOUS_IO_ALERT , FILE_SYNCHRONOUS_IO_ALERT , TRUE } ,
{ & mountmgr_dev_name , 0 , 0 } ,
2018-10-29 15:48:44 +01:00
{ & mountmgr_dev_name , FILE_SYNCHRONOUS_IO_ALERT , FILE_SYNCHRONOUS_IO_ALERT }
2018-10-29 15:48:30 +01:00
} ;
static WCHAR pipe_devW [ ] = { ' \\ ' , ' ? ' , ' ? ' , ' \\ ' , ' P ' , ' I ' , ' P ' , ' E ' , ' \\ ' } ;
static WCHAR mailslot_devW [ ] = { ' \\ ' , ' ? ' , ' ? ' , ' \\ ' , ' M ' , ' A ' , ' I ' , ' L ' , ' S ' , ' L ' , ' O ' , ' T ' , ' \\ ' } ;
static WCHAR mountmgr_devW [ ] =
{ ' \\ ' , ' ? ' , ' ? ' , ' \\ ' , ' M ' , ' o ' , ' u ' , ' n ' , ' t ' , ' P ' , ' o ' , ' i ' , ' n ' , ' t ' , ' M ' , ' a ' , ' n ' , ' a ' , ' g ' , ' e ' , ' r ' } ;
GetTempPathW ( MAX_PATH , tmp_path ) ;
res = GetTempFileNameW ( tmp_path , fooW , 0 , dos_file_name ) ;
ok ( res , " GetTempFileNameW failed: %u \n " , GetLastError ( ) ) ;
pRtlDosPathNameToNtPathName_U ( dos_file_name , & file_name , NULL , NULL ) ;
pipe_dev_name . Buffer = pipe_devW ;
pipe_dev_name . Length = sizeof ( pipe_devW ) ;
pipe_dev_name . MaximumLength = sizeof ( pipe_devW ) ;
mailslot_dev_name . Buffer = mailslot_devW ;
mailslot_dev_name . Length = sizeof ( mailslot_devW ) ;
mailslot_dev_name . MaximumLength = sizeof ( mailslot_devW ) ;
mountmgr_dev_name . Buffer = mountmgr_devW ;
mountmgr_dev_name . Length = sizeof ( mountmgr_devW ) ;
mountmgr_dev_name . MaximumLength = sizeof ( mountmgr_devW ) ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = 0 ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
for ( i = 0 ; i < ARRAY_SIZE ( option_tests ) ; i + + )
{
attr . ObjectName = option_tests [ i ] . file_name ;
access = SYNCHRONIZE ;
if ( option_tests [ i ] . file_name = = & file_name )
{
file = CreateFileW ( dos_file_name , GENERIC_READ | GENERIC_WRITE , 0 , NULL , CREATE_ALWAYS , 0 , 0 ) ;
ok ( file ! = INVALID_HANDLE_VALUE , " CreateFile failed: %u \n " , GetLastError ( ) ) ;
CloseHandle ( file ) ;
access | = GENERIC_WRITE | DELETE ;
}
status = pNtOpenFile ( & file , access , & attr , & io , 0 , option_tests [ i ] . options ) ;
ok ( status = = STATUS_SUCCESS , " [%u] NtOpenFile failed: %x \n " , i , status ) ;
memset ( & mode , 0xcc , sizeof ( mode ) ) ;
status = pNtQueryInformationFile ( file , & io , & mode , sizeof ( mode ) , FileModeInformation ) ;
ok ( status = = STATUS_SUCCESS , " [%u] can't get FileModeInformation: %x \n " , i , status ) ;
todo_wine_if ( option_tests [ i ] . todo )
ok ( mode . Mode = = option_tests [ i ] . mode , " [%u] Mode = %x, expected %x \n " ,
i , mode . Mode , option_tests [ i ] . mode ) ;
pNtClose ( file ) ;
if ( option_tests [ i ] . file_name = = & file_name )
DeleteFileW ( dos_file_name ) ;
}
2019-01-18 17:18:31 +01:00
pRtlFreeUnicodeString ( & file_name ) ;
2018-10-29 15:48:30 +01:00
}
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 ;
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 ) ;
2020-03-27 16:32:33 +01:00
todo_wine ok ( ffvi - > VolumeCreationTime . QuadPart ! = 0 , " Missing VolumeCreationTime \n " ) ;
2020-04-08 23:06:05 +02:00
ok ( ffvi - > VolumeSerialNumber ! = 0 , " Missing VolumeSerialNumber \n " ) ;
2010-11-22 21:24:42 +01:00
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 ) ;
}
2013-03-25 16:07:33 +01:00
static void test_query_attribute_information_file ( void )
{
NTSTATUS status ;
HANDLE dir ;
WCHAR path [ MAX_PATH ] ;
OBJECT_ATTRIBUTES attr ;
IO_STATUS_BLOCK io ;
UNICODE_STRING nameW ;
FILE_FS_ATTRIBUTE_INFORMATION * ffai ;
BYTE buf [ sizeof ( FILE_FS_ATTRIBUTE_INFORMATION ) + MAX_PATH * sizeof ( WCHAR ) ] ;
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 ;
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 ) , FileFsAttributeInformation ) ;
ffai = ( FILE_FS_ATTRIBUTE_INFORMATION * ) buf ;
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 ) ;
2020-03-26 00:15:19 +01:00
ok ( ffai - > FileSystemAttributes ! = 0 , " Missing FileSystemAttributes \n " ) ;
2013-03-25 16:07:33 +01:00
ok ( ffai - > MaximumComponentNameLength ! = 0 , " Missing MaximumComponentNameLength \n " ) ;
ok ( ffai - > FileSystemNameLength ! = 0 , " Missing FileSystemNameLength \n " ) ;
2020-03-26 00:15:19 +01:00
trace ( " FileSystemAttributes: %x MaximumComponentNameLength: %x FileSystemName: %s \n " ,
ffai - > FileSystemAttributes , ffai - > MaximumComponentNameLength ,
2013-03-25 16:07:33 +01:00
wine_dbgstr_wn ( ffai - > FileSystemName , ffai - > FileSystemNameLength / sizeof ( WCHAR ) ) ) ;
CloseHandle ( dir ) ;
}
2011-03-22 12:38:44 +01:00
static void test_NtCreateFile ( void )
{
static const struct test_data
{
DWORD disposition , attrib_in , status , result , attrib_out , needs_cleanup ;
} td [ ] =
{
/* 0*/ { FILE_CREATE , FILE_ATTRIBUTE_READONLY , 0 , FILE_CREATED , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY , FALSE } ,
/* 1*/ { FILE_CREATE , 0 , STATUS_OBJECT_NAME_COLLISION , 0 , 0 , TRUE } ,
/* 2*/ { FILE_CREATE , 0 , 0 , FILE_CREATED , FILE_ATTRIBUTE_ARCHIVE , FALSE } ,
/* 3*/ { FILE_OPEN , FILE_ATTRIBUTE_READONLY , 0 , FILE_OPENED , FILE_ATTRIBUTE_ARCHIVE , TRUE } ,
/* 4*/ { FILE_OPEN , FILE_ATTRIBUTE_READONLY , STATUS_OBJECT_NAME_NOT_FOUND , 0 , 0 , FALSE } ,
/* 5*/ { FILE_OPEN_IF , 0 , 0 , FILE_CREATED , FILE_ATTRIBUTE_ARCHIVE , FALSE } ,
2011-03-30 11:08:39 +02:00
/* 6*/ { FILE_OPEN_IF , FILE_ATTRIBUTE_READONLY , 0 , FILE_OPENED , FILE_ATTRIBUTE_ARCHIVE , TRUE } ,
/* 7*/ { FILE_OPEN_IF , FILE_ATTRIBUTE_READONLY , 0 , FILE_CREATED , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY , FALSE } ,
/* 8*/ { FILE_OPEN_IF , 0 , 0 , FILE_OPENED , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY , FALSE } ,
/* 9*/ { FILE_OVERWRITE , 0 , STATUS_ACCESS_DENIED , 0 , 0 , TRUE } ,
/*10*/ { FILE_OVERWRITE , 0 , STATUS_OBJECT_NAME_NOT_FOUND , 0 , 0 , FALSE } ,
/*11*/ { FILE_CREATE , 0 , 0 , FILE_CREATED , FILE_ATTRIBUTE_ARCHIVE , FALSE } ,
/*12*/ { FILE_OVERWRITE , FILE_ATTRIBUTE_READONLY , 0 , FILE_OVERWRITTEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY , FALSE } ,
/*13*/ { FILE_OVERWRITE_IF , 0 , STATUS_ACCESS_DENIED , 0 , 0 , TRUE } ,
/*14*/ { FILE_OVERWRITE_IF , 0 , 0 , FILE_CREATED , FILE_ATTRIBUTE_ARCHIVE , FALSE } ,
/*15*/ { FILE_OVERWRITE_IF , FILE_ATTRIBUTE_READONLY , 0 , FILE_OVERWRITTEN , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY , FALSE } ,
/*16*/ { FILE_SUPERSEDE , 0 , 0 , FILE_SUPERSEDED , FILE_ATTRIBUTE_ARCHIVE , FALSE } ,
/*17*/ { FILE_SUPERSEDE , FILE_ATTRIBUTE_READONLY , 0 , FILE_SUPERSEDED , FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY , TRUE } ,
/*18*/ { FILE_SUPERSEDE , 0 , 0 , FILE_CREATED , FILE_ATTRIBUTE_ARCHIVE , TRUE }
2011-03-22 12:38:44 +01:00
} ;
static const WCHAR fooW [ ] = { ' f ' , ' o ' , ' o ' , 0 } ;
NTSTATUS status ;
HANDLE handle ;
WCHAR path [ MAX_PATH ] ;
OBJECT_ATTRIBUTES attr ;
IO_STATUS_BLOCK io ;
UNICODE_STRING nameW ;
DWORD ret , i ;
2013-08-20 13:22:08 +02:00
GetTempPathW ( MAX_PATH , path ) ;
GetTempFileNameW ( path , fooW , 0 , path ) ;
2011-03-22 12:38:44 +01:00
DeleteFileW ( path ) ;
pRtlDosPathNameToNtPathName_U ( path , & nameW , NULL , NULL ) ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = NULL ;
attr . ObjectName = & nameW ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
2018-06-21 23:06:11 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( td ) ; i + + )
2011-03-22 12:38:44 +01:00
{
status = pNtCreateFile ( & handle , GENERIC_READ , & attr , & io , NULL ,
td [ i ] . attrib_in , FILE_SHARE_READ | FILE_SHARE_WRITE ,
td [ i ] . disposition , 0 , NULL , 0 ) ;
2011-03-30 11:08:39 +02:00
ok ( status = = td [ i ] . status , " %d: expected %#x got %#x \n " , i , td [ i ] . status , status ) ;
2011-03-22 12:38:44 +01:00
if ( ! status )
{
ok ( io . Information = = td [ i ] . result , " %d: expected %#x got %#lx \n " , i , td [ i ] . result , io . Information ) ;
ret = GetFileAttributesW ( path ) ;
ret & = ~ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED ;
/* FIXME: leave only 'else' case below once Wine is fixed */
if ( ret ! = td [ i ] . attrib_out )
{
todo_wine
ok ( ret = = td [ i ] . attrib_out , " %d: expected %#x got %#x \n " , i , td [ i ] . attrib_out , ret ) ;
SetFileAttributesW ( path , td [ i ] . attrib_out ) ;
}
else
ok ( ret = = td [ i ] . attrib_out , " %d: expected %#x got %#x \n " , i , td [ i ] . attrib_out , ret ) ;
CloseHandle ( handle ) ;
}
if ( td [ i ] . needs_cleanup )
{
SetFileAttributesW ( path , FILE_ATTRIBUTE_ARCHIVE ) ;
DeleteFileW ( path ) ;
}
}
2014-05-06 09:58:03 +02:00
pRtlFreeUnicodeString ( & nameW ) ;
2011-03-22 12:38:44 +01:00
SetFileAttributesW ( path , FILE_ATTRIBUTE_ARCHIVE ) ;
DeleteFileW ( path ) ;
}
2013-08-20 13:23:16 +02:00
static void test_read_write ( void )
{
2013-09-06 10:03:03 +02:00
static const char contents [ 14 ] = " 1234567890abcd " ;
2013-08-20 13:23:16 +02:00
char buf [ 256 ] ;
2017-01-26 00:51:24 +01:00
HANDLE hfile , event ;
2013-08-20 13:23:16 +02:00
OVERLAPPED ovl ;
IO_STATUS_BLOCK iob ;
2013-09-06 10:03:03 +02:00
DWORD ret , bytes , status , off ;
2013-08-20 13:23:16 +02:00
LARGE_INTEGER offset ;
2013-09-06 10:03:03 +02:00
LONG i ;
2013-08-20 13:23:16 +02:00
2017-01-26 00:51:24 +01:00
event = CreateEventA ( NULL , TRUE , FALSE , NULL ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-21 11:33:46 +02:00
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtReadFile ( INVALID_HANDLE_VALUE , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_OBJECT_TYPE_MISMATCH | | status = = STATUS_INVALID_HANDLE , " expected STATUS_OBJECT_TYPE_MISMATCH, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-08-21 11:33:46 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
2017-01-26 00:51:24 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtReadFile ( INVALID_HANDLE_VALUE , 0 , NULL , NULL , & iob , NULL , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_OBJECT_TYPE_MISMATCH | | status = = STATUS_INVALID_HANDLE , " expected STATUS_OBJECT_TYPE_MISMATCH, got %#x \n " , status ) ;
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-21 11:33:46 +02:00
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtWriteFile ( INVALID_HANDLE_VALUE , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_OBJECT_TYPE_MISMATCH | | status = = STATUS_INVALID_HANDLE , " expected STATUS_OBJECT_TYPE_MISMATCH, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-08-21 11:33:46 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
2017-01-26 00:51:35 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtWriteFile ( INVALID_HANDLE_VALUE , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_OBJECT_TYPE_MISMATCH | | status = = STATUS_INVALID_HANDLE , " expected STATUS_OBJECT_TYPE_MISMATCH, got %#x \n " , status ) ;
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
2013-08-20 13:23:16 +02:00
hfile = create_temp_file ( 0 ) ;
if ( ! hfile ) return ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-21 11:33:46 +02:00
iob . Information = - 1 ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , NULL , sizeof ( contents ) , NULL , NULL ) ;
ok ( status = = STATUS_INVALID_USER_BUFFER , " expected STATUS_INVALID_USER_BUFFER, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-08-21 11:33:46 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
2017-01-26 00:51:35 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
SetEvent ( event ) ;
status = pNtWriteFile ( hfile , event , NULL , NULL , & iob , NULL , sizeof ( contents ) , NULL , NULL ) ;
ok ( status = = STATUS_INVALID_USER_BUFFER , " expected STATUS_INVALID_USER_BUFFER, got %#x \n " , status ) ;
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
ok ( ! is_signaled ( event ) , " event is not signaled \n " ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-21 11:33:46 +02:00
iob . Information = - 1 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , NULL , sizeof ( contents ) , NULL , NULL ) ;
ok ( status = = STATUS_ACCESS_VIOLATION , " expected STATUS_ACCESS_VIOLATION, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-08-21 11:33:46 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
2017-01-26 00:51:24 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
SetEvent ( event ) ;
status = pNtReadFile ( hfile , event , NULL , NULL , & iob , NULL , sizeof ( contents ) , NULL , NULL ) ;
ok ( status = = STATUS_ACCESS_VIOLATION , " expected STATUS_ACCESS_VIOLATION, got %#x \n " , status ) ;
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
SetEvent ( event ) ;
status = pNtReadFile ( hfile , event , NULL , NULL , & iob , ( void * ) 0xdeadbeef , sizeof ( contents ) , NULL , NULL ) ;
ok ( status = = STATUS_ACCESS_VIOLATION , " expected STATUS_ACCESS_VIOLATION, got %#x \n " , status ) ;
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
ok ( is_signaled ( event ) , " event is not signaled \n " ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
2013-09-06 10:03:03 +02:00
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , contents , 7 , NULL , NULL ) ;
2013-08-20 13:23:16 +02:00
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-09-06 10:03:03 +02:00
ok ( iob . Information = = 7 , " expected 7, got %lu \n " , iob . Information ) ;
SetFilePointer ( hfile , 0 , NULL , FILE_BEGIN ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-09-06 10:03:03 +02:00
iob . Information = - 1 ;
offset . QuadPart = ( LONGLONG ) - 1 /* FILE_WRITE_TO_END_OF_FILE */ ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , contents + 7 , sizeof ( contents ) - 7 , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-09-06 10:03:03 +02:00
ok ( iob . Information = = sizeof ( contents ) - 7 , " expected sizeof(contents)-7, got %lu \n " , iob . Information ) ;
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
2013-09-18 08:53:02 +02:00
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( INVALID_HANDLE_VALUE , buf , 0 , & bytes , NULL ) ;
ok ( ! ret , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_HANDLE , " expected ERROR_INVALID_HANDLE, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , 0 , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( GetLastError ( ) = = 0xdeadbeef , " expected 0xdeadbeef, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2013-08-20 13:23:16 +02:00
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( GetLastError ( ) = = 0xdeadbeef , " expected 0xdeadbeef, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
SetFilePointer ( hfile , 0 , NULL , FILE_BEGIN ) ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = sizeof ( contents ) , " bytes %u \n " , bytes ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
for ( i = - 20 ; i < - 1 ; i + + )
{
if ( i = = - 2 ) continue ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-09-06 10:03:03 +02:00
iob . Information = - 1 ;
offset . QuadPart = ( LONGLONG ) i ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , contents , sizeof ( contents ) , & offset , NULL ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " %d: expected STATUS_INVALID_PARAMETER, got %#x \n " , i , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-09-06 10:03:03 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %ld \n " , iob . Information ) ;
}
2013-08-20 13:23:16 +02:00
SetFilePointer ( hfile , sizeof ( contents ) - 4 , NULL , FILE_BEGIN ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
2013-08-23 06:35:04 +02:00
offset . QuadPart = ( LONGLONG ) - 2 /* FILE_USE_FILE_POINTER_POSITION */ ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , " DCBA " , 4 , & offset , NULL ) ;
2013-08-20 13:23:16 +02:00
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = 4 , " expected 4, got %lu \n " , iob . Information ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-09-06 10:03:03 +02:00
iob . Information = - 1 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , NULL , NULL ) ;
ok ( status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , U ( iob ) . Status ) ;
2013-09-06 10:03:03 +02:00
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
2013-08-20 13:23:16 +02:00
SetFilePointer ( hfile , 0 , NULL , FILE_BEGIN ) ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = sizeof ( contents ) , " bytes %u \n " , bytes ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) - 4 ) , " file contents mismatch \n " ) ;
ok ( ! memcmp ( buf + sizeof ( contents ) - 4 , " DCBA " , 4 ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
SetFilePointer ( hfile , 0 , NULL , FILE_BEGIN ) ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hfile , contents , sizeof ( contents ) , & bytes , NULL ) ;
ok ( ret , " WriteFile error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = sizeof ( contents ) , " bytes %u \n " , bytes ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-10-11 06:39:39 +02:00
/* test reading beyond EOF */
bytes = - 1 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( GetLastError ( ) = = 0xdeadbeef , " expected 0xdeadbeef, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2013-10-29 08:10:02 +01:00
bytes = - 1 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , 0 , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( GetLastError ( ) = = 0xdeadbeef , " expected 0xdeadbeef, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
bytes = - 1 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , NULL , 0 , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( GetLastError ( ) = = 0xdeadbeef , " expected 0xdeadbeef, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2013-10-11 06:39:39 +02:00
S ( U ( ovl ) ) . Offset = sizeof ( contents ) ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = - 1 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , & ovl ) ;
ok ( ! ret , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_HANDLE_EOF , " expected ERROR_HANDLE_EOF, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 0 , " expected 0, got %lu \n " , ovl . InternalHigh ) ;
2013-10-29 08:10:02 +01:00
S ( U ( ovl ) ) . Offset = sizeof ( contents ) ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = - 1 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , 0 , & bytes , & ovl ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( GetLastError ( ) = = 0xdeadbeef , " expected 0xdeadbeef, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 0 , " expected 0, got %lu \n " , ovl . InternalHigh ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , NULL , NULL ) ;
ok ( status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
2013-10-29 08:10:02 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , 0 , NULL , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtReadFile error %#x \n " , status ) ;
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-10-11 06:39:39 +02:00
iob . Information = - 1 ;
offset . QuadPart = sizeof ( contents ) ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , U ( iob ) . Status ) ;
2013-10-11 06:39:39 +02:00
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
2013-10-29 08:10:02 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
offset . QuadPart = sizeof ( contents ) ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , 0 , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtReadFile error %#x \n " , status ) ;
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-10-11 06:39:39 +02:00
iob . Information = - 1 ;
offset . QuadPart = ( LONGLONG ) - 2 /* FILE_USE_FILE_POINTER_POSITION */ ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , U ( iob ) . Status ) ;
2013-10-11 06:39:39 +02:00
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
2013-10-29 08:10:02 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
offset . QuadPart = ( LONGLONG ) - 2 /* FILE_USE_FILE_POINTER_POSITION */ ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , 0 , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtReadFile error %#x \n " , status ) ;
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
2013-09-06 10:03:03 +02:00
for ( i = - 20 ; i < 0 ; i + + )
{
if ( i = = - 2 ) continue ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-09-06 10:03:03 +02:00
iob . Information = - 1 ;
offset . QuadPart = ( LONGLONG ) i ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " %d: expected STATUS_INVALID_PARAMETER, got %#x \n " , i , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-09-06 10:03:03 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %ld \n " , iob . Information ) ;
}
2013-08-20 13:23:16 +02:00
SetFilePointer ( hfile , 0 , NULL , FILE_BEGIN ) ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , NULL ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = sizeof ( contents ) , " bytes %u \n " , bytes ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtReadFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , iob . Information ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
offset . QuadPart = sizeof ( contents ) - 4 ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , " DCBA " , 4 , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtWriteFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = 4 , " expected 4, got %lu \n " , iob . Information ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_SUCCESS , " NtReadFile error %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , iob . Information ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) - 4 ) , " file contents mismatch \n " ) ;
ok ( ! memcmp ( buf + sizeof ( contents ) - 4 , " DCBA " , 4 ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
S ( U ( ovl ) ) . Offset = sizeof ( contents ) - 4 ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . hEvent = 0 ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hfile , " ABCD " , 4 , & bytes , & ovl ) ;
ok ( ret , " WriteFile error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 4 , " bytes %u \n " , bytes ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
S ( U ( ovl ) ) . Offset = 0 ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , & ovl ) ;
ok ( ret , " ReadFile error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = sizeof ( contents ) , " bytes %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , ovl . InternalHigh ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) - 4 ) , " file contents mismatch \n " ) ;
ok ( ! memcmp ( buf + sizeof ( contents ) - 4 , " ABCD " , 4 ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = sizeof ( contents ) , " expected sizeof(contents), got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
CloseHandle ( hfile ) ;
hfile = create_temp_file ( FILE_FLAG_OVERLAPPED ) ;
if ( ! hfile ) return ;
2013-09-18 08:53:02 +02:00
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( INVALID_HANDLE_VALUE , buf , 0 , & bytes , NULL ) ;
ok ( ! ret , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_HANDLE , " expected ERROR_INVALID_HANDLE, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
S ( U ( ovl ) ) . Offset = 0 ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
/* ReadFile return value depends on Windows version and testing it is not practical */
2013-10-11 06:39:44 +02:00
ReadFile ( hfile , buf , 0 , & bytes , & ovl ) ;
2013-09-18 08:53:02 +02:00
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 0 , " expected 0, got %lu \n " , ovl . InternalHigh ) ;
2013-08-20 13:23:16 +02:00
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hfile , contents , sizeof ( contents ) , & bytes , NULL ) ;
ok ( ! ret , " WriteFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_PARAMETER , " expected ERROR_INVALID_PARAMETER, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , contents , sizeof ( contents ) , NULL , NULL ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " expected STATUS_INVALID_PARAMETER, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %ld \n " , iob . Information ) ;
2013-09-06 10:03:03 +02:00
for ( i = - 20 ; i < - 1 ; i + + )
{
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-09-06 10:03:03 +02:00
iob . Information = - 1 ;
offset . QuadPart = ( LONGLONG ) i ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , contents , sizeof ( contents ) , & offset , NULL ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " %d: expected STATUS_INVALID_PARAMETER, got %#x \n " , i , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-09-06 10:03:03 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %ld \n " , iob . Information ) ;
}
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-21 11:33:05 +02:00
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , contents , sizeof ( contents ) , & offset , NULL ) ;
2019-03-05 13:16:46 +01:00
ok ( status = = STATUS_PENDING | | broken ( status = = STATUS_SUCCESS ) /* before Vista */ ,
2019-03-05 13:16:45 +01:00
" expected STATUS_PENDING, got %#x. \n " , status ) ;
2014-03-21 14:12:10 +01:00
if ( status = = STATUS_PENDING )
{
ret = WaitForSingleObject ( hfile , 3000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %d \n " , ret ) ;
}
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-08-21 11:33:05 +02:00
ok ( iob . Information = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , iob . Information ) ;
2013-08-20 13:23:16 +02:00
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , NULL ) ;
ok ( ! ret , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_PARAMETER , " expected ERROR_INVALID_PARAMETER, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , NULL , NULL ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " expected STATUS_INVALID_PARAMETER, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %ld \n " , iob . Information ) ;
2013-09-06 10:03:03 +02:00
for ( i = - 20 ; i < 0 ; i + + )
{
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-09-06 10:03:03 +02:00
iob . Information = - 1 ;
offset . QuadPart = ( LONGLONG ) i ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
ok ( status = = STATUS_INVALID_PARAMETER , " %d: expected STATUS_INVALID_PARAMETER, got %#x \n " , i , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-09-06 10:03:03 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %ld \n " , iob . Information ) ;
}
2013-08-23 06:35:04 +02:00
2013-10-11 06:39:39 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
/* test reading beyond EOF */
2013-08-23 06:35:04 +02:00
offset . QuadPart = sizeof ( contents ) ;
2013-08-20 13:23:16 +02:00
S ( U ( ovl ) ) . Offset = offset . u . LowPart ;
S ( U ( ovl ) ) . OffsetHigh = offset . u . HighPart ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , & ovl ) ;
ok ( ! ret , " ReadFile should fail \n " ) ;
2013-10-07 09:36:31 +02:00
ret = GetLastError ( ) ;
2020-04-20 01:06:00 +02:00
ok ( ret = = ERROR_IO_PENDING | | broken ( ret = = ERROR_HANDLE_EOF ) /* before Vista */ ,
" expected ERROR_IO_PENDING, got %d \n " , ret ) ;
2013-08-20 13:23:16 +02:00
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-10-07 09:36:31 +02:00
if ( ret = = ERROR_IO_PENDING )
{
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = GetOverlappedResult ( hfile , & ovl , & bytes , TRUE ) ;
ok ( ! ret , " GetOverlappedResult should report FALSE \n " ) ;
ok ( GetLastError ( ) = = ERROR_HANDLE_EOF , " expected ERROR_HANDLE_EOF, got %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 0 , " expected 0, read %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 0 , " expected 0, got %lu \n " , ovl . InternalHigh ) ;
}
2013-08-20 13:23:16 +02:00
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-10-29 08:10:02 +01:00
offset . QuadPart = sizeof ( contents ) ;
S ( U ( ovl ) ) . Offset = offset . u . LowPart ;
S ( U ( ovl ) ) . OffsetHigh = offset . u . HighPart ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , 0 , & bytes , & ovl ) ;
2019-03-07 10:28:35 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* before Vista */ ,
2019-03-07 10:28:34 +01:00
" Unexpected result, ret %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2013-10-29 08:10:02 +01:00
ret = GetLastError ( ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
if ( ret = = ERROR_IO_PENDING )
{
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = GetOverlappedResult ( hfile , & ovl , & bytes , TRUE ) ;
2019-04-02 21:17:13 +02:00
ok ( ret , " GetOverlappedResult returned FALSE with %u (expected TRUE) \n " , GetLastError ( ) ) ;
2013-10-29 08:10:02 +01:00
ok ( bytes = = 0 , " expected 0, read %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 0 , " expected 0, got %lu \n " , ovl . InternalHigh ) ;
}
offset . QuadPart = sizeof ( contents ) ;
S ( U ( ovl ) ) . Offset = offset . u . LowPart ;
S ( U ( ovl ) ) . OffsetHigh = offset . u . HighPart ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , NULL , 0 , & bytes , & ovl ) ;
2019-03-07 10:28:35 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* before Vista */ ,
2019-03-07 10:28:34 +01:00
" Unexpected result, ret %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2013-10-29 08:10:02 +01:00
ret = GetLastError ( ) ;
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
if ( ret = = ERROR_IO_PENDING )
{
bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = GetOverlappedResult ( hfile , & ovl , & bytes , TRUE ) ;
2019-04-02 21:17:13 +02:00
ok ( ret , " GetOverlappedResult returned FALSE with %u (expected TRUE) \n " , GetLastError ( ) ) ;
2013-10-29 08:10:02 +01:00
ok ( bytes = = 0 , " expected 0, read %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 0 , " expected 0, got %lu \n " , ovl . InternalHigh ) ;
}
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
offset . QuadPart = sizeof ( contents ) ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
2013-10-07 09:36:31 +02:00
if ( status = = STATUS_PENDING )
{
2014-03-21 14:12:10 +01:00
ret = WaitForSingleObject ( hfile , 3000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %d \n " , ret ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , U ( iob ) . Status ) ;
2013-10-07 09:36:31 +02:00
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
}
else
{
ok ( status = = STATUS_END_OF_FILE , " expected STATUS_END_OF_FILE, got %#x \n " , status ) ;
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = - 1 , " expected -1, got %#x \n " , U ( iob ) . Status ) ;
2013-10-07 09:36:31 +02:00
ok ( iob . Information = = - 1 , " expected -1, got %lu \n " , iob . Information ) ;
}
2013-08-20 13:23:16 +02:00
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
2013-10-29 08:10:02 +01:00
U ( iob ) . Status = - 1 ;
iob . Information = - 1 ;
offset . QuadPart = sizeof ( contents ) ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , 0 , & offset , NULL ) ;
2019-03-07 10:28:35 +01:00
ok ( status = = STATUS_PENDING | | broken ( status = = STATUS_SUCCESS ) /* before Vista */ ,
2019-03-07 10:28:34 +01:00
" expected STATUS_PENDING, got %#x. \n " , status ) ;
2013-10-29 08:10:02 +01:00
if ( status = = STATUS_PENDING )
{
2014-03-21 14:12:10 +01:00
ret = WaitForSingleObject ( hfile , 3000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %d \n " , ret ) ;
2013-10-29 08:10:02 +01:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
}
else
{
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
ok ( iob . Information = = 0 , " expected 0, got %lu \n " , iob . Information ) ;
}
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
S ( U ( ovl ) ) . Offset = 0 ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , & ovl ) ;
2019-03-07 10:28:35 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* before Vista */ ,
2019-03-07 10:28:34 +01:00
" Unexpected result, ret %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2013-10-07 09:36:31 +02:00
if ( ! ret )
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2019-03-07 10:28:34 +01:00
else
ok ( bytes = = 14 , " bytes %u \n " , bytes ) ;
2013-08-20 13:23:16 +02:00
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , ovl . InternalHigh ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
bytes = 0xdeadbeef ;
ret = GetOverlappedResult ( hfile , & ovl , & bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = sizeof ( contents ) , " bytes %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , ovl . InternalHigh ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
SetFilePointer ( hfile , sizeof ( contents ) - 4 , NULL , FILE_BEGIN ) ;
SetEndOfFile ( hfile ) ;
SetFilePointer ( hfile , 0 , NULL , FILE_BEGIN ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
2013-09-06 10:03:03 +02:00
offset . QuadPart = ( LONGLONG ) - 1 /* FILE_WRITE_TO_END_OF_FILE */ ;
2013-08-20 13:23:16 +02:00
status = pNtWriteFile ( hfile , 0 , NULL , NULL , & iob , " DCBA " , 4 , & offset , NULL ) ;
2019-03-05 13:16:46 +01:00
ok ( status = = STATUS_PENDING | | broken ( status = = STATUS_SUCCESS ) /* before Vista */ ,
2019-03-05 13:16:45 +01:00
" expected STATUS_PENDING, got %#x. \n " , status ) ;
2014-03-21 14:12:10 +01:00
if ( status = = STATUS_PENDING )
{
ret = WaitForSingleObject ( hfile , 3000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %d \n " , ret ) ;
}
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = 4 , " expected 4, got %lu \n " , iob . Information ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-10-15 01:33:48 +02:00
U ( iob ) . Status = - 1 ;
2013-08-20 13:23:16 +02:00
iob . Information = - 1 ;
offset . QuadPart = 0 ;
status = pNtReadFile ( hfile , 0 , NULL , NULL , & iob , buf , sizeof ( buf ) , & offset , NULL ) ;
2019-03-07 10:28:35 +01:00
ok ( status = = STATUS_PENDING | | broken ( status = = STATUS_SUCCESS ) /* before Vista */ ,
2019-03-07 10:28:34 +01:00
" expected STATUS_PENDING, got %#x. \n " , status ) ;
2014-03-21 14:12:10 +01:00
if ( status = = STATUS_PENDING )
{
ret = WaitForSingleObject ( hfile , 3000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %d \n " , ret ) ;
}
2013-10-15 01:33:48 +02:00
ok ( U ( iob ) . Status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x \n " , U ( iob ) . Status ) ;
2013-08-20 13:23:16 +02:00
ok ( iob . Information = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , iob . Information ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
ok ( ! memcmp ( contents , buf , sizeof ( contents ) - 4 ) , " file contents mismatch \n " ) ;
ok ( ! memcmp ( buf + sizeof ( contents ) - 4 , " DCBA " , 4 ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
S ( U ( ovl ) ) . Offset = sizeof ( contents ) - 4 ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hfile , " ABCD " , 4 , & bytes , & ovl ) ;
2019-03-05 13:16:46 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* before Vista */ ,
2019-03-05 13:16:45 +01:00
" Unexpected result %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2013-10-07 09:36:31 +02:00
if ( ! ret )
{
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2015-05-14 13:02:02 +02:00
ret = WaitForSingleObject ( hfile , 3000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %d \n " , ret ) ;
2013-10-07 09:36:31 +02:00
}
else ok ( bytes = = 4 , " bytes %u \n " , bytes ) ;
2013-08-20 13:23:16 +02:00
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 4 , " expected 4, got %lu \n " , ovl . InternalHigh ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
bytes = 0xdeadbeef ;
ret = GetOverlappedResult ( hfile , & ovl , & bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = 4 , " bytes %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = 4 , " expected 4, got %lu \n " , ovl . InternalHigh ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
S ( U ( ovl ) ) . Offset = 0 ;
S ( U ( ovl ) ) . OffsetHigh = 0 ;
ovl . Internal = - 1 ;
ovl . InternalHigh = - 1 ;
ovl . hEvent = 0 ;
bytes = 0 ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buf , sizeof ( buf ) , & bytes , & ovl ) ;
2019-03-07 10:28:35 +01:00
ok ( ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING ) | | broken ( ret ) /* before Vista */ ,
2019-03-07 10:28:34 +01:00
" Unexpected result %#x, GetLastError() %u. \n " , ret , GetLastError ( ) ) ;
2013-10-07 09:36:31 +02:00
if ( ! ret )
{
ok ( bytes = = 0 , " bytes %u \n " , bytes ) ;
2015-05-14 13:02:02 +02:00
ret = WaitForSingleObject ( hfile , 3000 ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject error %d \n " , ret ) ;
2013-10-07 09:36:31 +02:00
}
else ok ( bytes = = 14 , " bytes %u \n " , bytes ) ;
2013-08-20 13:23:16 +02:00
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , ovl . InternalHigh ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2013-08-20 13:23:16 +02:00
bytes = 0xdeadbeef ;
ret = GetOverlappedResult ( hfile , & ovl , & bytes , TRUE ) ;
ok ( ret , " GetOverlappedResult error %d \n " , GetLastError ( ) ) ;
ok ( bytes = = sizeof ( contents ) , " bytes %u \n " , bytes ) ;
ok ( ( NTSTATUS ) ovl . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , ovl . Internal ) ;
ok ( ovl . InternalHigh = = sizeof ( contents ) , " expected sizeof(contents), got %lu \n " , ovl . InternalHigh ) ;
ok ( ! memcmp ( contents , buf , sizeof ( contents ) - 4 ) , " file contents mismatch \n " ) ;
ok ( ! memcmp ( buf + sizeof ( contents ) - 4 , " ABCD " , 4 ) , " file contents mismatch \n " ) ;
2013-09-06 10:03:03 +02:00
off = SetFilePointer ( hfile , 0 , NULL , FILE_CURRENT ) ;
ok ( off = = 0 , " expected 0, got %u \n " , off ) ;
2017-01-26 00:51:24 +01:00
CloseHandle ( event ) ;
2013-08-20 13:23:16 +02:00
CloseHandle ( hfile ) ;
}
2017-02-15 22:12:59 +01:00
static void test_ioctl ( void )
{
HANDLE event = CreateEventA ( NULL , TRUE , FALSE , NULL ) ;
2017-10-05 14:30:36 +02:00
FILE_PIPE_PEEK_BUFFER peek_buf ;
2017-02-15 22:12:59 +01:00
IO_STATUS_BLOCK iosb ;
HANDLE file ;
NTSTATUS status ;
file = create_temp_file ( FILE_FLAG_OVERLAPPED ) ;
2017-03-12 20:46:28 +01:00
ok ( file ! = INVALID_HANDLE_VALUE , " could not create temp file \n " ) ;
2017-02-15 22:12:59 +01:00
SetEvent ( event ) ;
status = pNtFsControlFile ( file , event , NULL , NULL , & iosb , 0xdeadbeef , 0 , 0 , 0 , 0 ) ;
todo_wine
ok ( status = = STATUS_INVALID_DEVICE_REQUEST , " NtFsControlFile returned %x \n " , status ) ;
ok ( ! is_signaled ( event ) , " event is signaled \n " ) ;
status = pNtFsControlFile ( file , ( HANDLE ) 0xdeadbeef , NULL , NULL , & iosb , 0xdeadbeef , 0 , 0 , 0 , 0 ) ;
ok ( status = = STATUS_INVALID_HANDLE , " NtFsControlFile returned %x \n " , status ) ;
2017-10-05 14:30:36 +02:00
memset ( & iosb , 0x55 , sizeof ( iosb ) ) ;
2018-09-27 10:30:46 +02:00
status = pNtFsControlFile ( file , NULL , NULL , NULL , & iosb , FSCTL_PIPE_PEEK , NULL , 0 ,
2017-10-05 14:30:36 +02:00
& peek_buf , sizeof ( peek_buf ) ) ;
todo_wine
ok ( status = = STATUS_INVALID_DEVICE_REQUEST , " NtFsControlFile failed: %x \n " , status ) ;
ok ( iosb . Status = = 0x55555555 , " iosb.Status = %x \n " , iosb . Status ) ;
2017-02-15 22:12:59 +01:00
CloseHandle ( event ) ;
CloseHandle ( file ) ;
}
2017-03-01 12:05:53 +01:00
static void test_flush_buffers_file ( void )
{
char path [ MAX_PATH ] , buffer [ MAX_PATH ] ;
HANDLE hfile , hfileread ;
NTSTATUS status ;
IO_STATUS_BLOCK io_status_block ;
GetTempPathA ( MAX_PATH , path ) ;
GetTempFileNameA ( path , " foo " , 0 , buffer ) ;
hfile = CreateFileA ( buffer , GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ , NULL , CREATE_ALWAYS ,
FILE_ATTRIBUTE_NORMAL , 0 ) ;
ok ( hfile ! = INVALID_HANDLE_VALUE , " failed to create temp file. \n " ) ;
hfileread = CreateFileA ( buffer , GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE , NULL ,
OPEN_EXISTING , 0 , NULL ) ;
ok ( hfileread ! = INVALID_HANDLE_VALUE , " could not open temp file, error %d. \n " , GetLastError ( ) ) ;
status = pNtFlushBuffersFile ( hfile , NULL ) ;
ok ( status = = STATUS_ACCESS_VIOLATION , " expected STATUS_ACCESS_VIOLATION, got %#x. \n " , status ) ;
status = pNtFlushBuffersFile ( hfile , ( IO_STATUS_BLOCK * ) 0xdeadbeaf ) ;
ok ( status = = STATUS_ACCESS_VIOLATION , " expected STATUS_ACCESS_VIOLATION, got %#x. \n " , status ) ;
2020-06-09 19:00:07 +02:00
io_status_block . Information = 0xdeadbeef ;
io_status_block . Status = 0xdeadbeef ;
2017-03-01 12:05:53 +01:00
status = pNtFlushBuffersFile ( hfile , & io_status_block ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x. \n " , status ) ;
2020-06-09 19:00:07 +02:00
ok ( io_status_block . Status = = STATUS_SUCCESS , " Got unexpected io_status_block.Status %#x. \n " ,
io_status_block . Status ) ;
ok ( ! io_status_block . Information , " Got unexpected io_status_block.Information %#lx. \n " ,
io_status_block . Information ) ;
2017-03-01 12:05:53 +01:00
status = pNtFlushBuffersFile ( hfileread , & io_status_block ) ;
ok ( status = = STATUS_ACCESS_DENIED , " expected STATUS_ACCESS_DENIED, got %#x. \n " , status ) ;
2020-06-09 19:00:07 +02:00
io_status_block . Information = 0xdeadbeef ;
io_status_block . Status = 0xdeadbeef ;
2017-03-01 12:05:53 +01:00
status = pNtFlushBuffersFile ( NULL , & io_status_block ) ;
ok ( status = = STATUS_INVALID_HANDLE , " expected STATUS_INVALID_HANDLE, got %#x. \n " , status ) ;
2020-06-09 19:00:07 +02:00
ok ( io_status_block . Status = = 0xdeadbeef , " Got unexpected io_status_block.Status %#x. \n " ,
io_status_block . Status ) ;
ok ( io_status_block . Information = = 0xdeadbeef , " Got unexpected io_status_block.Information %#lx. \n " ,
io_status_block . Information ) ;
2017-03-01 12:05:53 +01:00
CloseHandle ( hfileread ) ;
2017-03-03 16:21:07 +01:00
CloseHandle ( hfile ) ;
hfile = CreateFileA ( buffer , FILE_APPEND_DATA , FILE_SHARE_READ | FILE_SHARE_WRITE , NULL ,
OPEN_EXISTING , 0 , NULL ) ;
ok ( hfile ! = INVALID_HANDLE_VALUE , " could not open temp file, error %d. \n " , GetLastError ( ) ) ;
status = pNtFlushBuffersFile ( hfile , & io_status_block ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x. \n " , status ) ;
2020-06-09 19:00:07 +02:00
io_status_block . Information = 0xdeadbeef ;
io_status_block . Status = 0xdeadbeef ;
status = pNtFlushBuffersFile ( ( HANDLE ) 0xdeadbeef , & io_status_block ) ;
ok ( status = = STATUS_INVALID_HANDLE , " expected STATUS_INVALID_HANDLE, got %#x. \n " , status ) ;
ok ( io_status_block . Status = = 0xdeadbeef , " Got unexpected io_status_block.Status %#x. \n " ,
io_status_block . Status ) ;
ok ( io_status_block . Information = = 0xdeadbeef , " Got unexpected io_status_block.Information %#lx. \n " ,
io_status_block . Information ) ;
2017-03-01 12:05:53 +01:00
CloseHandle ( hfile ) ;
DeleteFileA ( buffer ) ;
}
2019-04-09 17:53:53 +02:00
static void test_file_readonly_access ( void )
{
static const DWORD default_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ;
static const WCHAR fooW [ ] = { ' f ' , ' o ' , ' o ' , 0 } ;
WCHAR path [ MAX_PATH ] ;
OBJECT_ATTRIBUTES attr ;
UNICODE_STRING nameW ;
IO_STATUS_BLOCK io ;
HANDLE handle ;
NTSTATUS status ;
DWORD ret ;
/* Set up */
GetTempPathW ( MAX_PATH , path ) ;
GetTempFileNameW ( path , fooW , 0 , path ) ;
DeleteFileW ( path ) ;
pRtlDosPathNameToNtPathName_U ( path , & nameW , NULL , NULL ) ;
attr . Length = sizeof ( attr ) ;
attr . RootDirectory = NULL ;
attr . ObjectName = & nameW ;
attr . Attributes = OBJ_CASE_INSENSITIVE ;
attr . SecurityDescriptor = NULL ;
attr . SecurityQualityOfService = NULL ;
status = pNtCreateFile ( & handle , FILE_GENERIC_WRITE , & attr , & io , NULL , FILE_ATTRIBUTE_READONLY , default_sharing ,
FILE_CREATE , 0 , NULL , 0 ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x. \n " , status ) ;
CloseHandle ( handle ) ;
/* NtCreateFile FILE_GENERIC_WRITE */
status = pNtCreateFile ( & handle , FILE_GENERIC_WRITE , & attr , & io , NULL , FILE_ATTRIBUTE_NORMAL , default_sharing ,
FILE_OPEN , FILE_NON_DIRECTORY_FILE , NULL , 0 ) ;
ok ( status = = STATUS_ACCESS_DENIED , " expected STATUS_ACCESS_DENIED, got %#x. \n " , status ) ;
/* NtCreateFile DELETE without FILE_DELETE_ON_CLOSE */
status = pNtCreateFile ( & handle , DELETE , & attr , & io , NULL , FILE_ATTRIBUTE_NORMAL , default_sharing , FILE_OPEN ,
FILE_NON_DIRECTORY_FILE , NULL , 0 ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x. \n " , status ) ;
CloseHandle ( handle ) ;
/* NtCreateFile DELETE with FILE_DELETE_ON_CLOSE */
status = pNtCreateFile ( & handle , SYNCHRONIZE | DELETE , & attr , & io , NULL , FILE_ATTRIBUTE_NORMAL , default_sharing ,
FILE_OPEN , FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE , NULL , 0 ) ;
ok ( status = = STATUS_CANNOT_DELETE , " expected STATUS_CANNOT_DELETE, got %#x. \n " , status ) ;
/* NtOpenFile GENERIC_WRITE */
status = pNtOpenFile ( & handle , GENERIC_WRITE , & attr , & io , default_sharing , FILE_NON_DIRECTORY_FILE ) ;
ok ( status = = STATUS_ACCESS_DENIED , " expected STATUS_ACCESS_DENIED, got %#x. \n " , status ) ;
/* NtOpenFile DELETE without FILE_DELETE_ON_CLOSE */
status = pNtOpenFile ( & handle , DELETE , & attr , & io , default_sharing , FILE_NON_DIRECTORY_FILE ) ;
ok ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#x. \n " , status ) ;
CloseHandle ( handle ) ;
/* NtOpenFile DELETE with FILE_DELETE_ON_CLOSE */
status = pNtOpenFile ( & handle , DELETE , & attr , & io , default_sharing , FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE ) ;
ok ( status = = STATUS_CANNOT_DELETE , " expected STATUS_CANNOT_DELETE, got %#x. \n " , status ) ;
ret = GetFileAttributesW ( path ) ;
ok ( ret & FILE_ATTRIBUTE_READONLY , " got wrong attribute: %#x. \n " , ret ) ;
/* Clean up */
pRtlFreeUnicodeString ( & nameW ) ;
SetFileAttributesW ( path , FILE_ATTRIBUTE_NORMAL ) ;
DeleteFileW ( path ) ;
}
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 " ) ;
2017-02-15 22:12:59 +01:00
pNtFsControlFile = ( void * ) GetProcAddress ( hntdll , " NtFsControlFile " ) ;
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 " ) ;
2018-09-30 23:59:46 +02:00
pNtRemoveIoCompletionEx = ( void * ) GetProcAddress ( hntdll , " NtRemoveIoCompletionEx " ) ;
2007-11-09 23:11:31 +01:00
pNtSetIoCompletion = ( void * ) GetProcAddress ( hntdll , " NtSetIoCompletion " ) ;
pNtSetInformationFile = ( void * ) GetProcAddress ( hntdll , " NtSetInformationFile " ) ;
2018-09-27 10:30:52 +02:00
pNtQueryAttributesFile = ( void * ) GetProcAddress ( hntdll , " NtQueryAttributesFile " ) ;
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 " ) ;
2015-09-25 13:35:45 +02:00
pNtQueryFullAttributesFile = ( void * ) GetProcAddress ( hntdll , " NtQueryFullAttributesFile " ) ;
2017-03-01 12:05:53 +01:00
pNtFlushBuffersFile = ( void * ) GetProcAddress ( hntdll , " NtFlushBuffersFile " ) ;
2007-03-28 10:00:28 +02:00
2013-08-20 13:23:16 +02:00
test_read_write ( ) ;
2011-03-22 12:38:44 +01:00
test_NtCreateFile ( ) ;
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 ( ) ;
2018-09-30 23:59:45 +02:00
test_set_io_completion ( ) ;
test_file_io_completion ( ) ;
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 ( ) ;
2015-04-07 12:35:56 +02:00
test_file_full_size_information ( ) ;
2009-12-01 11:27:46 +01:00
test_file_all_name_information ( ) ;
2015-08-20 10:24:32 +02:00
test_file_rename_information ( ) ;
2015-08-21 07:24:49 +02:00
test_file_link_information ( ) ;
2013-08-12 17:09:13 +02:00
test_file_disposition_information ( ) ;
2017-02-17 05:14:59 +01:00
test_file_completion_information ( ) ;
2017-02-16 18:17:05 +01:00
test_file_id_information ( ) ;
2017-03-07 17:01:52 +01:00
test_file_access_information ( ) ;
2019-09-26 20:34:33 +02:00
test_file_attribute_tag_information ( ) ;
2018-10-29 15:48:30 +01:00
test_file_mode ( ) ;
2019-04-09 17:53:53 +02:00
test_file_readonly_access ( ) ;
2010-11-22 21:24:42 +01:00
test_query_volume_information_file ( ) ;
2013-03-25 16:07:33 +01:00
test_query_attribute_information_file ( ) ;
2017-02-15 22:12:59 +01:00
test_ioctl ( ) ;
2017-03-01 12:05:53 +01:00
test_flush_buffers_file ( ) ;
2007-02-27 13:41:55 +01:00
}