1 /* Unit test suite for Ntdll file functions
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2011 Dmitry Timoshkov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * We use function pointers here as there is no import library for NTDLL on
31 /* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
32 * definition errors when we get to winnt.h
34 #define WIN32_NO_STATUS
36 #include "wine/test.h"
42 #ifndef IO_COMPLETION_ALL_ACCESS
43 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
46 static BOOL (WINAPI
* pGetVolumePathNameW
)(LPCWSTR
, LPWSTR
, DWORD
);
47 static UINT (WINAPI
*pGetSystemWow64DirectoryW
)( LPWSTR
, UINT
);
49 static VOID (WINAPI
*pRtlFreeUnicodeString
)( PUNICODE_STRING
);
50 static VOID (WINAPI
*pRtlInitUnicodeString
)( PUNICODE_STRING
, LPCWSTR
);
51 static BOOL (WINAPI
*pRtlDosPathNameToNtPathName_U
)( LPCWSTR
, PUNICODE_STRING
, PWSTR
*, CURDIR
* );
52 static NTSTATUS (WINAPI
*pRtlWow64EnableFsRedirectionEx
)( ULONG
, ULONG
* );
54 static NTSTATUS (WINAPI
*pNtCreateMailslotFile
)( PHANDLE
, ULONG
, POBJECT_ATTRIBUTES
, PIO_STATUS_BLOCK
,
55 ULONG
, ULONG
, ULONG
, PLARGE_INTEGER
);
56 static NTSTATUS (WINAPI
*pNtCreateFile
)(PHANDLE
,ACCESS_MASK
,POBJECT_ATTRIBUTES
,PIO_STATUS_BLOCK
,PLARGE_INTEGER
,ULONG
,ULONG
,ULONG
,ULONG
,PVOID
,ULONG
);
57 static NTSTATUS (WINAPI
*pNtOpenFile
)(PHANDLE
,ACCESS_MASK
,POBJECT_ATTRIBUTES
,PIO_STATUS_BLOCK
,ULONG
,ULONG
);
58 static NTSTATUS (WINAPI
*pNtDeleteFile
)(POBJECT_ATTRIBUTES ObjectAttributes
);
59 static NTSTATUS (WINAPI
*pNtReadFile
)(HANDLE hFile
, HANDLE hEvent
,
60 PIO_APC_ROUTINE apc
, void* apc_user
,
61 PIO_STATUS_BLOCK io_status
, void* buffer
, ULONG length
,
62 PLARGE_INTEGER offset
, PULONG key
);
63 static NTSTATUS (WINAPI
*pNtWriteFile
)(HANDLE hFile
, HANDLE hEvent
,
64 PIO_APC_ROUTINE apc
, void* apc_user
,
65 PIO_STATUS_BLOCK io_status
,
66 const void* buffer
, ULONG length
,
67 PLARGE_INTEGER offset
, PULONG key
);
68 static NTSTATUS (WINAPI
*pNtCancelIoFile
)(HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
69 static NTSTATUS (WINAPI
*pNtCancelIoFileEx
)(HANDLE hFile
, PIO_STATUS_BLOCK iosb
, PIO_STATUS_BLOCK io_status
);
70 static NTSTATUS (WINAPI
*pNtClose
)( PHANDLE
);
71 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
);
73 static NTSTATUS (WINAPI
*pNtCreateIoCompletion
)(PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
, ULONG
);
74 static NTSTATUS (WINAPI
*pNtOpenIoCompletion
)(PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
);
75 static NTSTATUS (WINAPI
*pNtQueryIoCompletion
)(HANDLE
, IO_COMPLETION_INFORMATION_CLASS
, PVOID
, ULONG
, PULONG
);
76 static NTSTATUS (WINAPI
*pNtRemoveIoCompletion
)(HANDLE
, PULONG_PTR
, PULONG_PTR
, PIO_STATUS_BLOCK
, PLARGE_INTEGER
);
77 static NTSTATUS (WINAPI
*pNtRemoveIoCompletionEx
)(HANDLE
,FILE_IO_COMPLETION_INFORMATION
*,ULONG
,ULONG
*,LARGE_INTEGER
*,BOOLEAN
);
78 static NTSTATUS (WINAPI
*pNtSetIoCompletion
)(HANDLE
, ULONG_PTR
, ULONG_PTR
, NTSTATUS
, SIZE_T
);
79 static NTSTATUS (WINAPI
*pNtSetInformationFile
)(HANDLE
, PIO_STATUS_BLOCK
, PVOID
, ULONG
, FILE_INFORMATION_CLASS
);
80 static NTSTATUS (WINAPI
*pNtQueryAttributesFile
)(const OBJECT_ATTRIBUTES
*,FILE_BASIC_INFORMATION
*);
81 static NTSTATUS (WINAPI
*pNtQueryInformationFile
)(HANDLE
, PIO_STATUS_BLOCK
, PVOID
, ULONG
, FILE_INFORMATION_CLASS
);
82 static NTSTATUS (WINAPI
*pNtQueryDirectoryFile
)(HANDLE
,HANDLE
,PIO_APC_ROUTINE
,PVOID
,PIO_STATUS_BLOCK
,
83 PVOID
,ULONG
,FILE_INFORMATION_CLASS
,BOOLEAN
,PUNICODE_STRING
,BOOLEAN
);
84 static NTSTATUS (WINAPI
*pNtQueryVolumeInformationFile
)(HANDLE
,PIO_STATUS_BLOCK
,PVOID
,ULONG
,FS_INFORMATION_CLASS
);
85 static NTSTATUS (WINAPI
*pNtQueryFullAttributesFile
)(const OBJECT_ATTRIBUTES
*, FILE_NETWORK_OPEN_INFORMATION
*);
86 static NTSTATUS (WINAPI
*pNtFlushBuffersFile
)(HANDLE
, IO_STATUS_BLOCK
*);
87 static NTSTATUS (WINAPI
*pNtQueryEaFile
)(HANDLE
,PIO_STATUS_BLOCK
,PVOID
,ULONG
,BOOLEAN
,PVOID
,ULONG
,PULONG
,BOOLEAN
);
89 static WCHAR fooW
[] = {'f','o','o',0};
91 static inline BOOL
is_signaled( HANDLE obj
)
93 return WaitForSingleObject( obj
, 0 ) == WAIT_OBJECT_0
;
96 #define TEST_BUF_LEN 3
98 static HANDLE
create_temp_file( ULONG flags
)
100 char path
[MAX_PATH
], buffer
[MAX_PATH
];
103 GetTempPathA( MAX_PATH
, path
);
104 GetTempFileNameA( path
, "foo", 0, buffer
);
105 handle
= CreateFileA(buffer
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
106 flags
| FILE_FLAG_DELETE_ON_CLOSE
, 0);
107 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
108 return (handle
== INVALID_HANDLE_VALUE
) ? 0 : handle
;
111 #define CVALUE_FIRST 0xfffabbcc
112 #define CKEY_FIRST 0x1030341
113 #define CKEY_SECOND 0x132E46
115 static ULONG
get_pending_msgs(HANDLE h
)
120 res
= pNtQueryIoCompletion( h
, IoCompletionBasicInformation
, &a
, sizeof(a
), &req
);
121 ok( res
== STATUS_SUCCESS
, "NtQueryIoCompletion failed: %lx\n", res
);
122 if (res
!= STATUS_SUCCESS
) return -1;
123 ok( req
== sizeof(a
), "Unexpected response size: %lx\n", req
);
127 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
131 trace( "apc called block %p iosb.status %lx iosb.info %Iu\n",
132 iosb
, iosb
->Status
, iosb
->Information
);
134 ok( !reserved
, "reserved is not 0: %lx\n", reserved
);
137 static void create_file_test(void)
139 static const WCHAR systemrootW
[] = {'\\','S','y','s','t','e','m','R','o','o','t',
140 '\\','f','a','i','l','i','n','g',0};
141 static const WCHAR questionmarkInvalidNameW
[] = {'a','f','i','l','e','?',0};
142 static const WCHAR pipeInvalidNameW
[] = {'a','|','b',0};
143 static const WCHAR pathInvalidNtW
[] = {'\\','\\','?','\\',0};
144 static const WCHAR pathInvalidNt2W
[] = {'\\','?','?','\\',0};
145 static const WCHAR pathInvalidDosW
[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
146 static const char testdata
[] = "Hello World";
147 FILE_NETWORK_OPEN_INFORMATION info
;
150 WCHAR path
[MAX_PATH
];
151 OBJECT_ATTRIBUTES attr
;
153 UNICODE_STRING nameW
;
154 LARGE_INTEGER offset
;
158 GetCurrentDirectoryW( MAX_PATH
, path
);
159 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
160 attr
.Length
= sizeof(attr
);
161 attr
.RootDirectory
= 0;
162 attr
.ObjectName
= &nameW
;
163 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
164 attr
.SecurityDescriptor
= NULL
;
165 attr
.SecurityQualityOfService
= NULL
;
167 /* try various open modes and options on directories */
168 status
= pNtCreateFile( &dir
, GENERIC_READ
|GENERIC_WRITE
, &attr
, &io
, NULL
, 0,
169 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, FILE_DIRECTORY_FILE
, NULL
, 0 );
170 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
172 io
.Status
= 0xdeadbeef;
174 status
= pNtReadFile( dir
, NULL
, NULL
, NULL
, &io
, buf
, sizeof(buf
), &offset
, NULL
);
175 ok( status
== STATUS_INVALID_DEVICE_REQUEST
|| status
== STATUS_PENDING
, "NtReadFile error %08lx\n", status
);
176 if (status
== STATUS_PENDING
)
178 ret
= WaitForSingleObject( dir
, 1000 );
179 ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %lu\n", ret
);
180 ok( io
.Status
== STATUS_INVALID_DEVICE_REQUEST
,
181 "expected STATUS_INVALID_DEVICE_REQUEST, got %08lx\n", io
.Status
);
184 io
.Status
= 0xdeadbeef;
186 status
= pNtWriteFile( dir
, NULL
, NULL
, NULL
, &io
, testdata
, sizeof(testdata
), &offset
, NULL
);
188 ok( status
== STATUS_INVALID_DEVICE_REQUEST
|| status
== STATUS_PENDING
, "NtWriteFile error %08lx\n", status
);
189 if (status
== STATUS_PENDING
)
191 ret
= WaitForSingleObject( dir
, 1000 );
192 ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %lu\n", ret
);
193 ok( io
.Status
== STATUS_INVALID_DEVICE_REQUEST
,
194 "expected STATUS_INVALID_DEVICE_REQUEST, got %08lx\n", io
.Status
);
199 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
200 FILE_CREATE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
201 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
202 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
204 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
205 FILE_OPEN_IF
, FILE_DIRECTORY_FILE
, NULL
, 0 );
206 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
209 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
210 FILE_SUPERSEDE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
211 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
213 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
214 FILE_OVERWRITE
, FILE_DIRECTORY_FILE
, NULL
, 0 );
215 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
217 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
218 FILE_OVERWRITE_IF
, FILE_DIRECTORY_FILE
, NULL
, 0 );
219 ok( status
== STATUS_INVALID_PARAMETER
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
221 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
222 FILE_OPEN
, 0, NULL
, 0 );
223 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
226 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
227 FILE_CREATE
, 0, NULL
, 0 );
228 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
229 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
231 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
232 FILE_OPEN_IF
, 0, NULL
, 0 );
233 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
236 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
237 FILE_SUPERSEDE
, 0, NULL
, 0 );
238 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
239 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
241 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
242 FILE_OVERWRITE
, 0, NULL
, 0 );
243 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
244 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
246 status
= pNtCreateFile( &dir
, GENERIC_READ
, &attr
, &io
, NULL
, 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
247 FILE_OVERWRITE_IF
, 0, NULL
, 0 );
248 ok( status
== STATUS_OBJECT_NAME_COLLISION
|| status
== STATUS_ACCESS_DENIED
,
249 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
251 pRtlFreeUnicodeString( &nameW
);
253 pRtlInitUnicodeString( &nameW
, systemrootW
);
254 attr
.Length
= sizeof(attr
);
255 attr
.RootDirectory
= NULL
;
256 attr
.ObjectName
= &nameW
;
257 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
258 attr
.SecurityDescriptor
= NULL
;
259 attr
.SecurityQualityOfService
= NULL
;
261 status
= pNtCreateFile( &dir
, FILE_APPEND_DATA
, &attr
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0,
262 FILE_OPEN_IF
, FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
264 ok( status
== STATUS_INVALID_PARAMETER
,
265 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
267 /* Invalid chars in file/dirnames */
268 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW
, &nameW
, NULL
, NULL
);
269 attr
.ObjectName
= &nameW
;
270 status
= pNtCreateFile(&dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
271 FILE_SHARE_READ
, FILE_CREATE
,
272 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
273 ok(status
== STATUS_OBJECT_NAME_INVALID
,
274 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
276 status
= pNtCreateFile(&file
, GENERIC_WRITE
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
278 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
279 ok(status
== STATUS_OBJECT_NAME_INVALID
,
280 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
281 pRtlFreeUnicodeString(&nameW
);
283 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW
, &nameW
, NULL
, NULL
);
284 attr
.ObjectName
= &nameW
;
285 status
= pNtCreateFile(&dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
286 FILE_SHARE_READ
, FILE_CREATE
,
287 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
288 ok(status
== STATUS_OBJECT_NAME_INVALID
,
289 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
291 status
= pNtCreateFile(&file
, GENERIC_WRITE
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
293 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
294 ok(status
== STATUS_OBJECT_NAME_INVALID
,
295 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
296 pRtlFreeUnicodeString(&nameW
);
298 pRtlInitUnicodeString( &nameW
, pathInvalidNtW
);
299 status
= pNtCreateFile( &dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
300 FILE_SHARE_READ
, FILE_CREATE
,
301 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
302 ok( status
== STATUS_OBJECT_NAME_INVALID
,
303 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
305 status
= pNtQueryFullAttributesFile( &attr
, &info
);
306 todo_wine
ok( status
== STATUS_OBJECT_NAME_INVALID
,
307 "query %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
309 pRtlInitUnicodeString( &nameW
, pathInvalidNt2W
);
310 status
= pNtCreateFile( &dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
311 FILE_SHARE_READ
, FILE_CREATE
,
312 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
313 ok( status
== STATUS_OBJECT_NAME_INVALID
,
314 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
316 status
= pNtQueryFullAttributesFile( &attr
, &info
);
317 ok( status
== STATUS_OBJECT_NAME_INVALID
,
318 "query %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
320 pRtlInitUnicodeString( &nameW
, pathInvalidDosW
);
321 status
= pNtCreateFile( &dir
, GENERIC_READ
|SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
322 FILE_SHARE_READ
, FILE_CREATE
,
323 FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
324 ok( status
== STATUS_OBJECT_NAME_INVALID
,
325 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
327 status
= pNtQueryFullAttributesFile( &attr
, &info
);
328 ok( status
== STATUS_OBJECT_NAME_INVALID
,
329 "query %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
332 static void open_file_test(void)
334 static const WCHAR testdirW
[] = {'o','p','e','n','f','i','l','e','t','e','s','t',0};
335 static const char testdata
[] = "Hello World";
337 HANDLE dir
, root
, handle
, file
;
338 WCHAR path
[MAX_PATH
], tmpfile
[MAX_PATH
];
340 OBJECT_ATTRIBUTES attr
;
342 UNICODE_STRING nameW
;
344 BOOL ret
, restart
= TRUE
;
347 len
= GetWindowsDirectoryW( path
, MAX_PATH
);
348 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
349 attr
.Length
= sizeof(attr
);
350 attr
.RootDirectory
= 0;
351 attr
.ObjectName
= &nameW
;
353 attr
.SecurityDescriptor
= NULL
;
354 attr
.SecurityQualityOfService
= NULL
;
355 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
356 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
357 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
358 pRtlFreeUnicodeString( &nameW
);
360 path
[3] = 0; /* root of the drive */
361 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
362 status
= pNtOpenFile( &root
, GENERIC_READ
, &attr
, &io
,
363 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
364 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
365 pRtlFreeUnicodeString( &nameW
);
367 /* test opening system dir with RootDirectory set to windows dir */
368 GetSystemDirectoryW( path
, MAX_PATH
);
369 while (path
[len
] == '\\') len
++;
370 nameW
.Buffer
= path
+ len
;
371 nameW
.Length
= lstrlenW(path
+ len
) * sizeof(WCHAR
);
372 attr
.RootDirectory
= dir
;
373 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
374 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
375 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
376 CloseHandle( handle
);
378 /* try uppercase name */
379 for (i
= len
; path
[i
]; i
++) if (path
[i
] >= 'a' && path
[i
] <= 'z') path
[i
] -= 'a' - 'A';
380 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
381 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
382 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
383 CloseHandle( handle
);
385 /* try with leading backslash */
387 nameW
.Length
+= sizeof(WCHAR
);
388 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
389 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
390 ok( status
== STATUS_INVALID_PARAMETER
||
391 status
== STATUS_OBJECT_NAME_INVALID
||
392 status
== STATUS_OBJECT_PATH_SYNTAX_BAD
,
393 "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
394 if (!status
) CloseHandle( handle
);
396 /* try with empty name */
398 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
399 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
400 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
401 CloseHandle( handle
);
404 attr
.RootDirectory
= 0;
405 wcscat( path
, L
"\\cmd.exe" );
406 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
407 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
408 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
409 ok( status
== STATUS_NOT_A_DIRECTORY
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
410 CloseHandle( handle
);
411 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
412 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_NON_DIRECTORY_FILE
);
413 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
414 CloseHandle( handle
);
415 pRtlFreeUnicodeString( &nameW
);
417 wcscat( path
, L
"\\" );
418 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
419 status
= NtOpenFile( &handle
, FILE_LIST_DIRECTORY
| SYNCHRONIZE
, &attr
, &io
,
420 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
421 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
);
422 ok( status
== STATUS_NOT_A_DIRECTORY
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
423 CloseHandle( handle
);
424 pRtlFreeUnicodeString( &nameW
);
426 wcscat( path
, L
"\\cmd.exe" );
427 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
428 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
429 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
);
430 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
431 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
432 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_NON_DIRECTORY_FILE
);
433 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
434 pRtlFreeUnicodeString( &nameW
);
436 GetTempPathW( MAX_PATH
, path
);
437 lstrcatW( path
, testdirW
);
438 CreateDirectoryW( path
, NULL
);
440 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
441 attr
.RootDirectory
= NULL
;
442 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
443 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
444 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
445 pRtlFreeUnicodeString( &nameW
);
447 GetTempFileNameW( path
, fooW
, 0, tmpfile
);
448 file
= CreateFileW( tmpfile
, FILE_WRITE_DATA
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
449 ok( file
!= INVALID_HANDLE_VALUE
, "CreateFile error %ld\n", GetLastError() );
450 numbytes
= 0xdeadbeef;
451 ret
= WriteFile( file
, testdata
, sizeof(testdata
) - 1, &numbytes
, NULL
);
452 ok( ret
, "WriteFile failed with error %lu\n", GetLastError() );
453 ok( numbytes
== sizeof(testdata
) - 1, "failed to write all data\n" );
456 /* try open by file id */
458 while (!pNtQueryDirectoryFile( dir
, NULL
, NULL
, NULL
, &io
, data
, sizeof(data
),
459 FileIdBothDirectoryInformation
, TRUE
, NULL
, restart
))
461 FILE_ID_BOTH_DIRECTORY_INFORMATION
*info
= (FILE_ID_BOTH_DIRECTORY_INFORMATION
*)data
;
465 if (!info
->FileId
.QuadPart
) continue;
467 nameW
.Buffer
= (WCHAR
*)&info
->FileId
;
468 nameW
.Length
= sizeof(info
->FileId
);
469 info
->FileName
[info
->FileNameLength
/sizeof(WCHAR
)] = 0;
470 attr
.RootDirectory
= dir
;
471 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
472 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
474 FILE_OPEN_BY_FILE_ID
|
475 ((info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ? FILE_DIRECTORY_FILE
: 0) );
476 ok( status
== STATUS_SUCCESS
, "open %s failed %lx\n", wine_dbgstr_w(info
->FileName
), status
);
479 BYTE buf
[sizeof(FILE_ALL_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
481 if (!pNtQueryInformationFile( handle
, &io
, buf
, sizeof(buf
), FileAllInformation
))
483 FILE_ALL_INFORMATION
*fai
= (FILE_ALL_INFORMATION
*)buf
;
485 /* check that it's the same file/directory */
487 /* don't check the size for directories */
488 if (!(info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
489 ok( info
->EndOfFile
.QuadPart
== fai
->StandardInformation
.EndOfFile
.QuadPart
,
490 "mismatched file size for %s\n", wine_dbgstr_w(info
->FileName
));
492 ok( info
->CreationTime
.QuadPart
== fai
->BasicInformation
.CreationTime
.QuadPart
,
493 "mismatched creation time for %s\n", wine_dbgstr_w(info
->FileName
));
495 CloseHandle( handle
);
497 /* try same thing from drive root */
498 attr
.RootDirectory
= root
;
499 status
= pNtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
,
500 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
501 FILE_OPEN_BY_FILE_ID
|
502 ((info
->FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ? FILE_DIRECTORY_FILE
: 0) );
503 ok( status
== STATUS_SUCCESS
|| status
== STATUS_NOT_IMPLEMENTED
,
504 "open %s failed %lx\n", wine_dbgstr_w(info
->FileName
), status
);
505 if (!status
) CloseHandle( handle
);
512 pRtlDosPathNameToNtPathName_U( tmpfile
, &nameW
, NULL
, NULL
);
513 attr
.Length
= sizeof(attr
);
514 attr
.RootDirectory
= 0;
515 attr
.ObjectName
= &nameW
;
516 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
517 attr
.SecurityDescriptor
= NULL
;
518 attr
.SecurityQualityOfService
= NULL
;
519 status
= pNtOpenFile( &file
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
520 FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_NONALERT
);
521 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
522 pRtlFreeUnicodeString( &nameW
);
524 numbytes
= 0xdeadbeef;
525 memset( data
, 0, sizeof(data
) );
526 ret
= ReadFile( file
, data
, sizeof(data
), &numbytes
, NULL
);
527 ok( ret
, "ReadFile failed with error %lu\n", GetLastError() );
528 ok( numbytes
== sizeof(testdata
) - 1, "failed to read all data\n" );
529 ok( !memcmp( data
, testdata
, sizeof(testdata
) - 1 ), "testdata doesn't match\n" );
531 nameW
.Length
= sizeof(fooW
) - sizeof(WCHAR
);
533 attr
.RootDirectory
= file
;
534 attr
.ObjectName
= &nameW
;
535 status
= pNtOpenFile( &root
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
536 FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_NONALERT
);
537 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
,
538 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08lx\n", status
);
542 attr
.RootDirectory
= file
;
543 attr
.ObjectName
= &nameW
;
544 status
= pNtOpenFile( &root
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
545 FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_NONALERT
);
546 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(tmpfile
), status
);
548 numbytes
= SetFilePointer( file
, 0, 0, FILE_CURRENT
);
549 ok( numbytes
== sizeof(testdata
) - 1, "SetFilePointer returned %lu\n", numbytes
);
550 numbytes
= SetFilePointer( root
, 0, 0, FILE_CURRENT
);
551 ok( numbytes
== 0, "SetFilePointer returned %lu\n", numbytes
);
553 numbytes
= 0xdeadbeef;
554 memset( data
, 0, sizeof(data
) );
555 ret
= ReadFile( root
, data
, sizeof(data
), &numbytes
, NULL
);
556 ok( ret
, "ReadFile failed with error %lu\n", GetLastError() );
557 ok( numbytes
== sizeof(testdata
) - 1, "failed to read all data\n" );
558 ok( !memcmp( data
, testdata
, sizeof(testdata
) - 1 ), "testdata doesn't match\n" );
560 numbytes
= SetFilePointer( file
, 0, 0, FILE_CURRENT
);
561 ok( numbytes
== sizeof(testdata
) - 1, "SetFilePointer returned %lu\n", numbytes
);
562 numbytes
= SetFilePointer( root
, 0, 0, FILE_CURRENT
);
563 ok( numbytes
== sizeof(testdata
) - 1, "SetFilePointer returned %lu\n", numbytes
);
567 DeleteFileW( tmpfile
);
568 RemoveDirectoryW( path
);
571 static void delete_file_test(void)
574 OBJECT_ATTRIBUTES attr
;
575 UNICODE_STRING nameW
;
576 WCHAR pathW
[MAX_PATH
];
577 WCHAR pathsubW
[MAX_PATH
];
578 static const WCHAR testdirW
[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
579 static const WCHAR subdirW
[] = {'\\','s','u','b',0};
581 ret
= GetTempPathW(MAX_PATH
, pathW
);
584 ok(0, "couldn't get temp dir\n");
587 if (ret
+ ARRAY_SIZE(testdirW
)-1 + ARRAY_SIZE(subdirW
)-1 >= MAX_PATH
)
589 ok(0, "MAX_PATH exceeded in constructing paths\n");
593 lstrcatW(pathW
, testdirW
);
594 lstrcpyW(pathsubW
, pathW
);
595 lstrcatW(pathsubW
, subdirW
);
597 ret
= CreateDirectoryW(pathW
, NULL
);
598 ok(ret
== TRUE
, "couldn't create directory ntdeletefile\n");
599 if (!pRtlDosPathNameToNtPathName_U(pathW
, &nameW
, NULL
, NULL
))
601 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
605 attr
.Length
= sizeof(attr
);
606 attr
.RootDirectory
= 0;
607 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
608 attr
.ObjectName
= &nameW
;
609 attr
.SecurityDescriptor
= NULL
;
610 attr
.SecurityQualityOfService
= NULL
;
612 /* test NtDeleteFile on an empty directory */
613 ret
= pNtDeleteFile(&attr
);
614 ok(ret
== STATUS_SUCCESS
, "NtDeleteFile should succeed in removing an empty directory\n");
615 ret
= RemoveDirectoryW(pathW
);
616 ok(ret
== FALSE
, "expected to fail removing directory, NtDeleteFile should have removed it\n");
618 /* test NtDeleteFile on a non-empty directory */
619 ret
= CreateDirectoryW(pathW
, NULL
);
620 ok(ret
== TRUE
, "couldn't create directory ntdeletefile ?!\n");
621 ret
= CreateDirectoryW(pathsubW
, NULL
);
622 ok(ret
== TRUE
, "couldn't create directory subdir\n");
623 ret
= pNtDeleteFile(&attr
);
624 ok(ret
== STATUS_SUCCESS
, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
625 ret
= RemoveDirectoryW(pathsubW
);
626 ok(ret
== TRUE
, "expected to remove directory ntdeletefile\\sub\n");
627 ret
= RemoveDirectoryW(pathW
);
628 ok(ret
== TRUE
, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
630 pRtlFreeUnicodeString( &nameW
);
633 #define TEST_OVERLAPPED_READ_SIZE 4096
635 static void read_file_test(void)
637 DECLSPEC_ALIGN(TEST_OVERLAPPED_READ_SIZE
) static unsigned char aligned_buffer
[TEST_OVERLAPPED_READ_SIZE
];
638 const char text
[] = "foobar";
640 IO_STATUS_BLOCK iosb
;
644 LARGE_INTEGER offset
;
645 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
647 if (!(handle
= create_temp_file( FILE_FLAG_OVERLAPPED
))) return;
649 iosb
.Status
= 0xdeadbabe;
650 iosb
.Information
= 0xdeadbeef;
653 status
= pNtWriteFile( handle
, event
, apc
, &apc_count
, &iosb
, text
, strlen(text
), &offset
, NULL
);
654 ok( status
== STATUS_PENDING
|| broken(status
== STATUS_SUCCESS
) /* before Vista */,
655 "wrong status %lx.\n", status
);
656 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
657 ok( iosb
.Status
== STATUS_SUCCESS
, "wrong status %lx\n", iosb
.Status
);
658 ok( iosb
.Information
== strlen(text
), "wrong info %Iu\n", iosb
.Information
);
659 ok( is_signaled( event
), "event is not signaled\n" );
660 ok( !apc_count
, "apc was called\n" );
661 SleepEx( 1, TRUE
); /* alertable sleep */
662 ok( apc_count
== 1, "apc was not called\n" );
665 iosb
.Status
= 0xdeadbabe;
666 iosb
.Information
= 0xdeadbeef;
669 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, strlen(text
) + 10, &offset
, NULL
);
670 ok(status
== STATUS_PENDING
671 || broken(status
== STATUS_SUCCESS
) /* before Vista */,
672 "wrong status %lx.\n", status
);
673 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
674 ok( iosb
.Status
== STATUS_SUCCESS
, "wrong status %lx\n", iosb
.Status
);
675 ok( iosb
.Information
== strlen(text
), "wrong info %Iu\n", iosb
.Information
);
676 ok( is_signaled( event
), "event is not signaled\n" );
677 ok( !apc_count
, "apc was called\n" );
678 SleepEx( 1, TRUE
); /* alertable sleep */
679 ok( apc_count
== 1, "apc was not called\n" );
681 /* read beyond eof */
683 iosb
.Status
= 0xdeadbabe;
684 iosb
.Information
= 0xdeadbeef;
685 offset
.QuadPart
= strlen(text
) + 2;
686 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, &offset
, NULL
);
687 ok(status
== STATUS_PENDING
|| broken(status
== STATUS_END_OF_FILE
) /* before Vista */,
688 "expected STATUS_PENDING, got %#lx\n", status
);
689 if (status
== STATUS_PENDING
) /* vista */
691 WaitForSingleObject( event
, 1000 );
692 ok( iosb
.Status
== STATUS_END_OF_FILE
, "wrong status %lx\n", iosb
.Status
);
693 ok( iosb
.Information
== 0, "wrong info %Iu\n", iosb
.Information
);
694 ok( is_signaled( event
), "event is not signaled\n" );
695 ok( !apc_count
, "apc was called\n" );
696 SleepEx( 1, TRUE
); /* alertable sleep */
697 ok( apc_count
== 1, "apc was not called\n" );
699 CloseHandle( handle
);
701 /* now a non-overlapped file */
702 if (!(handle
= create_temp_file(0))) return;
704 iosb
.Status
= 0xdeadbabe;
705 iosb
.Information
= 0xdeadbeef;
707 status
= pNtWriteFile( handle
, event
, apc
, &apc_count
, &iosb
, text
, strlen(text
), &offset
, NULL
);
708 ok( status
== STATUS_END_OF_FILE
||
709 status
== STATUS_SUCCESS
||
710 status
== STATUS_PENDING
, /* vista */
711 "wrong status %lx\n", status
);
712 if (status
== STATUS_PENDING
) WaitForSingleObject( event
, 1000 );
713 ok( iosb
.Status
== STATUS_SUCCESS
, "wrong status %lx\n", iosb
.Status
);
714 ok( iosb
.Information
== strlen(text
), "wrong info %Iu\n", iosb
.Information
);
715 ok( is_signaled( event
), "event is not signaled\n" );
716 ok( !apc_count
, "apc was called\n" );
717 SleepEx( 1, TRUE
); /* alertable sleep */
718 ok( apc_count
== 1, "apc was not called\n" );
721 iosb
.Status
= 0xdeadbabe;
722 iosb
.Information
= 0xdeadbeef;
725 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, strlen(text
) + 10, &offset
, NULL
);
726 ok( status
== STATUS_SUCCESS
, "wrong status %lx\n", status
);
727 ok( iosb
.Status
== STATUS_SUCCESS
, "wrong status %lx\n", iosb
.Status
);
728 ok( iosb
.Information
== strlen(text
), "wrong info %Iu\n", iosb
.Information
);
729 ok( is_signaled( event
), "event is not signaled\n" );
730 ok( !apc_count
, "apc was called\n" );
731 SleepEx( 1, TRUE
); /* alertable sleep */
732 todo_wine
ok( !apc_count
, "apc was called\n" );
734 /* read beyond eof */
736 iosb
.Status
= 0xdeadbabe;
737 iosb
.Information
= 0xdeadbeef;
738 offset
.QuadPart
= strlen(text
) + 2;
740 status
= pNtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, &offset
, NULL
);
741 ok( status
== STATUS_END_OF_FILE
, "wrong status %lx\n", status
);
742 ok( iosb
.Status
== STATUS_END_OF_FILE
, "wrong status %lx\n", iosb
.Status
);
743 ok( iosb
.Information
== 0, "wrong info %Iu\n", iosb
.Information
);
744 ok( is_signaled( event
), "event is not signaled\n" );
745 ok( !apc_count
, "apc was called\n" );
746 SleepEx( 1, TRUE
); /* alertable sleep */
747 ok( !apc_count
, "apc was called\n" );
749 CloseHandle( handle
);
751 if (!(handle
= create_temp_file(FILE_FLAG_OVERLAPPED
| FILE_FLAG_NO_BUFFERING
)))
756 iosb
.Status
= 0xdeadbabe;
757 iosb
.Information
= 0xdeadbeef;
760 status
= pNtWriteFile(handle
, event
, apc
, &apc_count
, &iosb
,
761 aligned_buffer
, sizeof(aligned_buffer
), &offset
, NULL
);
762 ok(status
== STATUS_END_OF_FILE
|| status
== STATUS_PENDING
763 || broken(status
== STATUS_SUCCESS
) /* before Vista */,
764 "Wrong status %lx.\n", status
);
765 ok(iosb
.Status
== STATUS_SUCCESS
, "Wrong status %lx.\n", iosb
.Status
);
766 ok(iosb
.Information
== sizeof(aligned_buffer
), "Wrong info %Iu.\n", iosb
.Information
);
767 ok(is_signaled(event
), "event is not signaled.\n");
768 ok(!apc_count
, "apc was called.\n");
769 SleepEx(1, TRUE
); /* alertable sleep */
770 ok(apc_count
== 1, "apc was not called.\n");
774 iosb
.Status
= 0xdeadbabe;
775 iosb
.Information
= 0xdeadbeef;
778 status
= pNtReadFile(handle
, event
, apc
, &apc_count
, &iosb
,
779 aligned_buffer
, sizeof(aligned_buffer
), &offset
, NULL
);
780 ok(status
== STATUS_PENDING
, "Wrong status %lx.\n", status
);
781 WaitForSingleObject(event
, 1000);
782 ok(iosb
.Status
== STATUS_SUCCESS
, "Wrong status %lx.\n", iosb
.Status
);
783 ok(iosb
.Information
== sizeof(aligned_buffer
), "Wrong info %Iu.\n", iosb
.Information
);
784 ok(is_signaled(event
), "event is not signaled.\n");
785 ok(!apc_count
, "apc was called.\n");
786 SleepEx(1, TRUE
); /* alertable sleep */
787 ok(apc_count
== 1, "apc was not called.\n");
793 static void append_file_test(void)
795 static const char text
[6] = "foobar";
798 IO_STATUS_BLOCK iosb
;
799 LARGE_INTEGER offset
;
800 char path
[MAX_PATH
], buffer
[MAX_PATH
], buf
[16];
803 GetTempPathA( MAX_PATH
, path
);
804 GetTempFileNameA( path
, "foo", 0, buffer
);
806 handle
= CreateFileA(buffer
, FILE_WRITE_DATA
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
807 ok(handle
!= INVALID_HANDLE_VALUE
, "CreateFile error %ld\n", GetLastError());
810 iosb
.Information
= -1;
811 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
, 2, NULL
, NULL
);
812 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
813 ok(iosb
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iosb
.Status
);
814 ok(iosb
.Information
== 2, "expected 2, got %Iu\n", iosb
.Information
);
818 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
819 It matches the O_WRONLY|O_APPEND open() posix behavior */
820 handle
= CreateFileA(buffer
, FILE_APPEND_DATA
, 0, NULL
, OPEN_EXISTING
, 0, 0);
821 ok(handle
!= INVALID_HANDLE_VALUE
, "CreateFile error %ld\n", GetLastError());
824 iosb
.Information
= -1;
826 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
+ 2, 2, &offset
, NULL
);
827 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
828 ok(iosb
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iosb
.Status
);
829 ok(iosb
.Information
== 2, "expected 2, got %Iu\n", iosb
.Information
);
831 ret
= SetFilePointer(handle
, 0, NULL
, FILE_CURRENT
);
832 ok(ret
== 4, "expected 4, got %lu\n", ret
);
835 iosb
.Information
= -1;
837 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
+ 4, 2, &offset
, NULL
);
838 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
839 ok(iosb
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iosb
.Status
);
840 ok(iosb
.Information
== 2, "expected 2, got %Iu\n", iosb
.Information
);
842 ret
= SetFilePointer(handle
, 0, NULL
, FILE_CURRENT
);
843 ok(ret
== 6, "expected 6, got %lu\n", ret
);
847 handle
= CreateFileA(buffer
, FILE_READ_DATA
| FILE_WRITE_DATA
| FILE_APPEND_DATA
, 0, NULL
, OPEN_EXISTING
, 0, 0);
848 ok(handle
!= INVALID_HANDLE_VALUE
, "CreateFile error %ld\n", GetLastError());
850 memset(buf
, 0, sizeof(buf
));
852 iosb
.Information
= -1;
854 status
= pNtReadFile(handle
, 0, NULL
, NULL
, &iosb
, buf
, sizeof(buf
), &offset
, NULL
);
855 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#lx\n", status
);
856 ok(iosb
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iosb
.Status
);
857 ok(iosb
.Information
== 6, "expected 6, got %Iu\n", iosb
.Information
);
859 ok(memcmp(buf
, text
, 6) == 0, "wrong file contents: %s\n", buf
);
862 iosb
.Information
= -1;
864 status
= pNtWriteFile(handle
, NULL
, NULL
, NULL
, &iosb
, text
+ 3, 3, &offset
, NULL
);
865 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
866 ok(iosb
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iosb
.Status
);
867 ok(iosb
.Information
== 3, "expected 3, got %Iu\n", iosb
.Information
);
869 memset(buf
, 0, sizeof(buf
));
871 iosb
.Information
= -1;
873 status
= pNtReadFile(handle
, 0, NULL
, NULL
, &iosb
, buf
, sizeof(buf
), &offset
, NULL
);
874 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#lx\n", status
);
875 ok(iosb
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iosb
.Status
);
876 ok(iosb
.Information
== 6, "expected 6, got %Iu\n", iosb
.Information
);
878 ok(memcmp(buf
, "barbar", 6) == 0, "wrong file contents: %s\n", buf
);
884 static void nt_mailslot_test(void)
887 ACCESS_MASK DesiredAccess
;
888 OBJECT_ATTRIBUTES attr
;
892 ULONG MaxMessageSize
;
893 LARGE_INTEGER TimeOut
;
894 IO_STATUS_BLOCK IoStatusBlock
;
897 WCHAR buffer1
[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
898 'R',':','\\','F','R','E','D','\0' };
900 TimeOut
.QuadPart
= -1;
902 pRtlInitUnicodeString(&str
, buffer1
);
903 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
904 CreateOptions
= MailslotQuota
= MaxMessageSize
= 0;
905 DesiredAccess
= GENERIC_READ
;
908 * Check for NULL pointer handling
910 rc
= pNtCreateMailslotFile(NULL
, DesiredAccess
,
911 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
913 ok( rc
== STATUS_ACCESS_VIOLATION
||
914 rc
== STATUS_INVALID_PARAMETER
, /* win2k3 */
915 "rc = %lx not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc
);
918 * Test to see if the Timeout can be NULL
920 hslot
= (HANDLE
)0xdeadbeef;
921 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
922 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
924 ok( rc
== STATUS_SUCCESS
||
925 rc
== STATUS_INVALID_PARAMETER
, /* win2k3 */
926 "rc = %lx not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc
);
927 ok( hslot
!= 0, "Handle is invalid\n");
929 if ( rc
== STATUS_SUCCESS
) pNtClose(hslot
);
934 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
935 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
936 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
938 ok( rc
== STATUS_SUCCESS
, "Create MailslotFile failed rc = %lx\n", rc
);
939 ok( hslot
!= 0, "Handle is invalid\n");
941 rc
= pNtClose(hslot
);
942 ok( rc
== STATUS_SUCCESS
, "NtClose failed\n");
945 static void WINAPI
user_apc_proc(ULONG_PTR arg
)
947 unsigned int *apc_count
= (unsigned int *)arg
;
951 static void test_set_io_completion(void)
953 FILE_IO_COMPLETION_INFORMATION info
[2] = {{0}};
954 LARGE_INTEGER timeout
= {{0}};
955 unsigned int apc_count
;
956 IO_STATUS_BLOCK iosb
;
957 ULONG_PTR key
, value
;
963 if (sizeof(size
) > 4) size
|= (ULONGLONG
)0x12345678 << 32;
965 res
= pNtCreateIoCompletion( &h
, IO_COMPLETION_ALL_ACCESS
, NULL
, 0 );
966 ok( res
== STATUS_SUCCESS
, "NtCreateIoCompletion failed: %#lx\n", res
);
967 ok( h
&& h
!= INVALID_HANDLE_VALUE
, "got invalid handle %p\n", h
);
969 res
= pNtRemoveIoCompletion( h
, &key
, &value
, &iosb
, &timeout
);
970 ok( res
== STATUS_TIMEOUT
, "NtRemoveIoCompletion failed: %#lx\n", res
);
972 res
= pNtSetIoCompletion( h
, CKEY_FIRST
, CVALUE_FIRST
, STATUS_INVALID_DEVICE_REQUEST
, size
);
973 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %lx\n", res
);
975 count
= get_pending_msgs(h
);
976 ok( count
== 1, "Unexpected msg count: %ld\n", count
);
978 res
= pNtRemoveIoCompletion( h
, &key
, &value
, &iosb
, &timeout
);
979 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletion failed: %#lx\n", res
);
980 ok( key
== CKEY_FIRST
, "Invalid completion key: %#Ix\n", key
);
981 ok( iosb
.Information
== size
, "Invalid iosb.Information: %Iu\n", iosb
.Information
);
982 ok( iosb
.Status
== STATUS_INVALID_DEVICE_REQUEST
, "Invalid iosb.Status: %#lx\n", iosb
.Status
);
983 ok( value
== CVALUE_FIRST
, "Invalid completion value: %#Ix\n", value
);
985 count
= get_pending_msgs(h
);
986 ok( !count
, "Unexpected msg count: %ld\n", count
);
988 if (!pNtRemoveIoCompletionEx
)
990 skip("NtRemoveIoCompletionEx() not present\n");
996 res
= pNtRemoveIoCompletionEx( h
, info
, 2, &count
, &timeout
, FALSE
);
997 ok( res
== STATUS_TIMEOUT
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
998 ok( count
<= 1, "wrong count %lu\n", count
);
1000 res
= pNtSetIoCompletion( h
, 123, 456, 789, size
);
1001 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %#lx\n", res
);
1004 res
= pNtRemoveIoCompletionEx( h
, info
, 2, &count
, &timeout
, FALSE
);
1005 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
1006 ok( count
== 1, "wrong count %lu\n", count
);
1007 ok( info
[0].CompletionKey
== 123, "wrong key %#Ix\n", info
[0].CompletionKey
);
1008 ok( info
[0].CompletionValue
== 456, "wrong value %#Ix\n", info
[0].CompletionValue
);
1009 ok( info
[0].IoStatusBlock
.Information
== size
, "wrong information %#Ix\n",
1010 info
[0].IoStatusBlock
.Information
);
1011 ok( info
[0].IoStatusBlock
.Status
== 789, "wrong status %#lx\n", info
[0].IoStatusBlock
.Status
);
1013 res
= pNtSetIoCompletion( h
, 123, 456, 789, size
);
1014 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %#lx\n", res
);
1016 res
= pNtSetIoCompletion( h
, 12, 34, 56, size
);
1017 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %#lx\n", res
);
1020 res
= pNtRemoveIoCompletionEx( h
, info
, 2, &count
, &timeout
, FALSE
);
1021 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
1022 ok( count
== 2, "wrong count %lu\n", count
);
1023 ok( info
[0].CompletionKey
== 123, "wrong key %#Ix\n", info
[0].CompletionKey
);
1024 ok( info
[0].CompletionValue
== 456, "wrong value %#Ix\n", info
[0].CompletionValue
);
1025 ok( info
[0].IoStatusBlock
.Information
== size
, "wrong information %#Ix\n",
1026 info
[0].IoStatusBlock
.Information
);
1027 ok( info
[0].IoStatusBlock
.Status
== 789, "wrong status %#lx\n", info
[0].IoStatusBlock
.Status
);
1028 ok( info
[1].CompletionKey
== 12, "wrong key %#Ix\n", info
[1].CompletionKey
);
1029 ok( info
[1].CompletionValue
== 34, "wrong value %#Ix\n", info
[1].CompletionValue
);
1030 ok( info
[1].IoStatusBlock
.Information
== size
, "wrong information %#Ix\n",
1031 info
[1].IoStatusBlock
.Information
);
1032 ok( info
[1].IoStatusBlock
.Status
== 56, "wrong status %#lx\n", info
[1].IoStatusBlock
.Status
);
1034 res
= pNtSetIoCompletion( h
, 123, 456, 789, size
);
1035 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %#lx\n", res
);
1037 res
= pNtSetIoCompletion( h
, 12, 34, 56, size
);
1038 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %#lx\n", res
);
1041 res
= pNtRemoveIoCompletionEx( h
, info
, 1, &count
, NULL
, FALSE
);
1042 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
1043 ok( count
== 1, "wrong count %lu\n", count
);
1044 ok( info
[0].CompletionKey
== 123, "wrong key %#Ix\n", info
[0].CompletionKey
);
1045 ok( info
[0].CompletionValue
== 456, "wrong value %#Ix\n", info
[0].CompletionValue
);
1046 ok( info
[0].IoStatusBlock
.Information
== size
, "wrong information %#Ix\n",
1047 info
[0].IoStatusBlock
.Information
);
1048 ok( info
[0].IoStatusBlock
.Status
== 789, "wrong status %#lx\n", info
[0].IoStatusBlock
.Status
);
1051 res
= pNtRemoveIoCompletionEx( h
, info
, 1, &count
, NULL
, FALSE
);
1052 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
1053 ok( count
== 1, "wrong count %lu\n", count
);
1054 ok( info
[0].CompletionKey
== 12, "wrong key %#Ix\n", info
[0].CompletionKey
);
1055 ok( info
[0].CompletionValue
== 34, "wrong value %#Ix\n", info
[0].CompletionValue
);
1056 ok( info
[0].IoStatusBlock
.Information
== size
, "wrong information %#Ix\n",
1057 info
[0].IoStatusBlock
.Information
);
1058 ok( info
[0].IoStatusBlock
.Status
== 56, "wrong status %#lx\n", info
[0].IoStatusBlock
.Status
);
1061 QueueUserAPC( user_apc_proc
, GetCurrentThread(), (ULONG_PTR
)&apc_count
);
1064 res
= pNtRemoveIoCompletionEx( h
, info
, 2, &count
, &timeout
, FALSE
);
1065 ok( res
== STATUS_TIMEOUT
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
1066 ok( count
<= 1, "wrong count %lu\n", count
);
1067 ok( !apc_count
, "wrong apc count %d\n", apc_count
);
1069 res
= pNtRemoveIoCompletionEx( h
, info
, 2, &count
, &timeout
, TRUE
);
1070 ok( res
== STATUS_USER_APC
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
1071 ok( count
<= 1, "wrong count %lu\n", count
);
1072 ok( apc_count
== 1, "wrong apc count %u\n", apc_count
);
1075 QueueUserAPC( user_apc_proc
, GetCurrentThread(), (ULONG_PTR
)&apc_count
);
1077 res
= pNtSetIoCompletion( h
, 123, 456, 789, size
);
1078 ok( res
== STATUS_SUCCESS
, "NtSetIoCompletion failed: %#lx\n", res
);
1080 res
= pNtRemoveIoCompletionEx( h
, info
, 2, &count
, &timeout
, TRUE
);
1081 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletionEx failed: %#lx\n", res
);
1082 ok( count
== 1, "wrong count %lu\n", count
);
1083 ok( !apc_count
, "wrong apc count %u\n", apc_count
);
1090 static void test_file_io_completion(void)
1092 static const char pipe_name
[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1094 IO_STATUS_BLOCK iosb
;
1095 BYTE send_buf
[TEST_BUF_LEN
], recv_buf
[TEST_BUF_LEN
];
1096 FILE_COMPLETION_INFORMATION fci
;
1097 LARGE_INTEGER timeout
= {{0}};
1098 HANDLE server
, client
;
1099 ULONG_PTR key
, value
;
1107 res
= pNtCreateIoCompletion( &h
, IO_COMPLETION_ALL_ACCESS
, NULL
, 0 );
1108 ok( res
== STATUS_SUCCESS
, "NtCreateIoCompletion failed: %#lx\n", res
);
1109 ok( h
&& h
!= INVALID_HANDLE_VALUE
, "got invalid handle %p\n", h
);
1110 fci
.CompletionPort
= h
;
1111 fci
.CompletionKey
= CKEY_SECOND
;
1113 server
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
,
1114 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1115 4, 1024, 1024, 1000, NULL
);
1116 ok( server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %lu\n", GetLastError() );
1117 client
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
,
1118 FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1119 ok( client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError() );
1121 iosb
.Status
= 0xdeadbeef;
1122 res
= pNtSetInformationFile( server
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1123 ok( res
== STATUS_INVALID_PARAMETER
, "NtSetInformationFile failed: %#lx\n", res
);
1125 ok( iosb
.Status
== 0xdeadbeef, "wrong status %#lx\n", iosb
.Status
);
1126 CloseHandle( client
);
1127 CloseHandle( server
);
1129 server
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
,
1130 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1131 4, 1024, 1024, 1000, NULL
);
1132 ok( server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %lu\n", GetLastError() );
1133 client
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
,
1134 FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1135 ok( client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError() );
1137 iosb
.Status
= 0xdeadbeef;
1138 res
= pNtSetInformationFile( server
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1139 ok( res
== STATUS_SUCCESS
, "NtSetInformationFile failed: %#lx\n", res
);
1140 ok( iosb
.Status
== STATUS_SUCCESS
, "wrong status %#lx\n", iosb
.Status
);
1142 memset( send_buf
, 0, TEST_BUF_LEN
);
1143 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1144 count
= get_pending_msgs(h
);
1145 ok( !count
, "Unexpected msg count: %ld\n", count
);
1146 ReadFile( server
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1147 count
= get_pending_msgs(h
);
1148 ok( !count
, "Unexpected msg count: %ld\n", count
);
1149 WriteFile( client
, send_buf
, TEST_BUF_LEN
, &read
, NULL
);
1151 res
= pNtRemoveIoCompletion( h
, &key
, &value
, &iosb
, &timeout
);
1152 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletion failed: %#lx\n", res
);
1153 ok( key
== CKEY_SECOND
, "Invalid completion key: %#Ix\n", key
);
1154 ok( iosb
.Information
== 3, "Invalid iosb.Information: %Id\n", iosb
.Information
);
1155 ok( iosb
.Status
== STATUS_SUCCESS
, "Invalid iosb.Status: %#lx\n", iosb
.Status
);
1156 ok( value
== (ULONG_PTR
)&o
, "Invalid completion value: %#Ix\n", value
);
1157 ok( !memcmp( send_buf
, recv_buf
, TEST_BUF_LEN
),
1158 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1159 recv_buf
[0], recv_buf
[1], recv_buf
[2], send_buf
[0], send_buf
[1], send_buf
[2] );
1160 count
= get_pending_msgs(h
);
1161 ok( !count
, "Unexpected msg count: %ld\n", count
);
1163 memset( send_buf
, 0, TEST_BUF_LEN
);
1164 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1165 WriteFile( client
, send_buf
, 2, &read
, NULL
);
1166 count
= get_pending_msgs(h
);
1167 ok( !count
, "Unexpected msg count: %ld\n", count
);
1168 ReadFile( server
, recv_buf
, 2, &read
, &o
);
1169 count
= get_pending_msgs(h
);
1170 ok( count
== 1, "Unexpected msg count: %ld\n", count
);
1172 res
= pNtRemoveIoCompletion( h
, &key
, &value
, &iosb
, &timeout
);
1173 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletion failed: %#lx\n", res
);
1174 ok( key
== CKEY_SECOND
, "Invalid completion key: %#Ix\n", key
);
1175 ok( iosb
.Information
== 2, "Invalid iosb.Information: %Id\n", iosb
.Information
);
1176 ok( iosb
.Status
== STATUS_SUCCESS
, "Invalid iosb.Status: %#lx\n", iosb
.Status
);
1177 ok( value
== (ULONG_PTR
)&o
, "Invalid completion value: %#Ix\n", value
);
1178 ok( !memcmp( send_buf
, recv_buf
, 2 ),
1179 "Receive buffer (%02x %02x) did not match send buffer (%02x %02x)\n",
1180 recv_buf
[0], recv_buf
[1], send_buf
[0], send_buf
[1] );
1182 ReadFile( server
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1183 CloseHandle( server
);
1184 count
= get_pending_msgs(h
);
1185 ok( count
== 1, "Unexpected msg count: %ld\n", count
);
1187 res
= pNtRemoveIoCompletion( h
, &key
, &value
, &iosb
, &timeout
);
1188 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletion failed: %#lx\n", res
);
1189 ok( key
== CKEY_SECOND
, "Invalid completion key: %Ix\n", key
);
1190 ok( iosb
.Information
== 0, "Invalid iosb.Information: %Id\n", iosb
.Information
);
1191 ok( iosb
.Status
== STATUS_PIPE_BROKEN
, "Invalid iosb.Status: %lx\n", iosb
.Status
);
1192 ok( value
== (ULONG_PTR
)&o
, "Invalid completion value: %Ix\n", value
);
1194 CloseHandle( client
);
1196 /* test associating a completion port with a handle after an async is queued */
1197 server
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
,
1198 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1199 4, 1024, 1024, 1000, NULL
);
1200 ok( server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %lu\n", GetLastError() );
1201 client
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
,
1202 FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1203 ok( client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError() );
1205 memset( send_buf
, 0, TEST_BUF_LEN
);
1206 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1207 count
= get_pending_msgs(h
);
1208 ok( !count
, "Unexpected msg count: %ld\n", count
);
1209 ReadFile( server
, recv_buf
, TEST_BUF_LEN
, &read
, &o
);
1211 iosb
.Status
= 0xdeadbeef;
1212 res
= pNtSetInformationFile( server
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1213 ok( res
== STATUS_SUCCESS
, "NtSetInformationFile failed: %lx\n", res
);
1214 ok( iosb
.Status
== STATUS_SUCCESS
, "iosb.Status invalid: %lx\n", iosb
.Status
);
1215 count
= get_pending_msgs(h
);
1216 ok( !count
, "Unexpected msg count: %ld\n", count
);
1218 WriteFile( client
, send_buf
, TEST_BUF_LEN
, &read
, NULL
);
1220 res
= pNtRemoveIoCompletion( h
, &key
, &value
, &iosb
, &timeout
);
1221 ok( res
== STATUS_SUCCESS
, "NtRemoveIoCompletion failed: %#lx\n", res
);
1222 ok( key
== CKEY_SECOND
, "Invalid completion key: %#Ix\n", key
);
1223 ok( iosb
.Information
== 3, "Invalid iosb.Information: %Id\n", iosb
.Information
);
1224 ok( iosb
.Status
== STATUS_SUCCESS
, "Invalid iosb.Status: %#lx\n", iosb
.Status
);
1225 ok( value
== (ULONG_PTR
)&o
, "Invalid completion value: %#Ix\n", value
);
1226 ok( !memcmp( send_buf
, recv_buf
, TEST_BUF_LEN
),
1227 "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n",
1228 recv_buf
[0], recv_buf
[1], recv_buf
[2], send_buf
[0], send_buf
[1], send_buf
[2] );
1230 count
= get_pending_msgs(h
);
1231 ok( !count
, "Unexpected msg count: %ld\n", count
);
1233 /* using APCs on handle with associated completion port is not allowed */
1234 res
= pNtReadFile( server
, NULL
, apc
, &apc_count
, &iosb
, recv_buf
, sizeof(recv_buf
), NULL
, NULL
);
1235 ok(res
== STATUS_INVALID_PARAMETER
, "NtReadFile returned %lx\n", res
);
1237 CloseHandle( server
);
1238 CloseHandle( client
);
1240 /* test associating a completion port with a handle after an async using APC is queued */
1241 server
= CreateNamedPipeA( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
,
1242 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1243 4, 1024, 1024, 1000, NULL
);
1244 ok( server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %lu\n", GetLastError() );
1245 client
= CreateFileA( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
,
1246 FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
1247 ok( client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError() );
1250 memset( send_buf
, 0, TEST_BUF_LEN
);
1251 memset( recv_buf
, 0xde, TEST_BUF_LEN
);
1252 count
= get_pending_msgs(h
);
1253 ok( !count
, "Unexpected msg count: %ld\n", count
);
1255 res
= pNtReadFile( server
, NULL
, apc
, &apc_count
, &iosb
, recv_buf
, sizeof(recv_buf
), NULL
, NULL
);
1256 ok(res
== STATUS_PENDING
, "NtReadFile returned %lx\n", res
);
1258 iosb
.Status
= 0xdeadbeef;
1259 res
= pNtSetInformationFile( server
, &iosb
, &fci
, sizeof(fci
), FileCompletionInformation
);
1260 ok( res
== STATUS_SUCCESS
, "NtSetInformationFile failed: %lx\n", res
);
1261 ok( iosb
.Status
== STATUS_SUCCESS
, "iosb.Status invalid: %lx\n", iosb
.Status
);
1262 count
= get_pending_msgs(h
);
1263 ok( !count
, "Unexpected msg count: %ld\n", count
);
1265 WriteFile( client
, send_buf
, TEST_BUF_LEN
, &read
, NULL
);
1267 ok(!apc_count
, "apc_count = %u\n", apc_count
);
1268 count
= get_pending_msgs(h
);
1269 ok( !count
, "Unexpected msg count: %ld\n", count
);
1271 SleepEx(1, TRUE
); /* alertable sleep */
1272 ok(apc_count
== 1, "apc was not called\n");
1273 count
= get_pending_msgs(h
);
1274 ok( !count
, "Unexpected msg count: %ld\n", count
);
1276 /* using APCs on handle with associated completion port is not allowed */
1277 res
= pNtReadFile( server
, NULL
, apc
, &apc_count
, &iosb
, recv_buf
, sizeof(recv_buf
), NULL
, NULL
);
1278 ok(res
== STATUS_INVALID_PARAMETER
, "NtReadFile returned %lx\n", res
);
1280 CloseHandle( server
);
1281 CloseHandle( client
);
1285 static void test_file_full_size_information(void)
1288 FILE_FS_FULL_SIZE_INFORMATION ffsi
;
1289 FILE_FS_SIZE_INFORMATION fsi
;
1293 if(!(h
= create_temp_file(0))) return ;
1295 memset(&ffsi
,0,sizeof(ffsi
));
1296 memset(&fsi
,0,sizeof(fsi
));
1298 /* Assume No Quota Settings configured on Wine Testbot */
1299 res
= pNtQueryVolumeInformationFile(h
, &io
, &ffsi
, sizeof ffsi
, FileFsFullSizeInformation
);
1300 ok(res
== STATUS_SUCCESS
, "cannot get attributes, res %lx\n", res
);
1301 res
= pNtQueryVolumeInformationFile(h
, &io
, &fsi
, sizeof fsi
, FileFsSizeInformation
);
1302 ok(res
== STATUS_SUCCESS
, "cannot get attributes, res %lx\n", res
);
1304 /* Test for FileFsSizeInformation */
1305 ok(fsi
.TotalAllocationUnits
.QuadPart
> 0,
1306 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1307 wine_dbgstr_longlong(fsi
.TotalAllocationUnits
.QuadPart
));
1308 ok(fsi
.AvailableAllocationUnits
.QuadPart
> 0,
1309 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1310 wine_dbgstr_longlong(fsi
.AvailableAllocationUnits
.QuadPart
));
1312 /* Assume file system is NTFS */
1313 ok(fsi
.BytesPerSector
== 512, "[fsi] BytesPerSector expected 512, got %ld\n",fsi
.BytesPerSector
);
1314 ok(fsi
.SectorsPerAllocationUnit
== 8, "[fsi] SectorsPerAllocationUnit expected 8, got %ld\n",fsi
.SectorsPerAllocationUnit
);
1316 ok(ffsi
.TotalAllocationUnits
.QuadPart
> 0,
1317 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1318 wine_dbgstr_longlong(ffsi
.TotalAllocationUnits
.QuadPart
));
1319 ok(ffsi
.CallerAvailableAllocationUnits
.QuadPart
> 0,
1320 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1321 wine_dbgstr_longlong(ffsi
.CallerAvailableAllocationUnits
.QuadPart
));
1322 ok(ffsi
.ActualAvailableAllocationUnits
.QuadPart
> 0,
1323 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1324 wine_dbgstr_longlong(ffsi
.ActualAvailableAllocationUnits
.QuadPart
));
1325 ok(ffsi
.TotalAllocationUnits
.QuadPart
== fsi
.TotalAllocationUnits
.QuadPart
,
1326 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1327 wine_dbgstr_longlong(fsi
.TotalAllocationUnits
.QuadPart
),
1328 wine_dbgstr_longlong(ffsi
.TotalAllocationUnits
.QuadPart
));
1329 ok(ffsi
.CallerAvailableAllocationUnits
.QuadPart
== fsi
.AvailableAllocationUnits
.QuadPart
,
1330 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1331 wine_dbgstr_longlong(fsi
.AvailableAllocationUnits
.QuadPart
),
1332 wine_dbgstr_longlong(ffsi
.CallerAvailableAllocationUnits
.QuadPart
));
1334 /* Assume file system is NTFS */
1335 ok(ffsi
.BytesPerSector
== 512, "[ffsi] BytesPerSector expected 512, got %ld\n",ffsi
.BytesPerSector
);
1336 ok(ffsi
.SectorsPerAllocationUnit
== 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %ld\n",ffsi
.SectorsPerAllocationUnit
);
1341 static void test_file_basic_information(void)
1343 FILE_BASIC_INFORMATION fbi
, fbi2
;
1347 int attrib_mask
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_NORMAL
;
1349 if (!(h
= create_temp_file(0))) return;
1351 /* Check default first */
1352 memset(&fbi
, 0, sizeof(fbi
));
1353 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1354 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1355 ok ( (fbi
.FileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) == FILE_ATTRIBUTE_ARCHIVE
,
1356 "attribute %lx not expected\n", fbi
.FileAttributes
);
1358 memset(&fbi2
, 0, sizeof(fbi2
));
1359 fbi2
.LastWriteTime
.QuadPart
= -1;
1360 io
.Status
= 0xdeadbeef;
1361 res
= pNtSetInformationFile(h
, &io
, &fbi2
, sizeof fbi2
, FileBasicInformation
);
1362 ok ( res
== STATUS_SUCCESS
, "can't set -1 write time, NtSetInformationFile returned %x\n", res
);
1363 ok ( io
.Status
== STATUS_SUCCESS
, "can't set -1 write time, io.Status is %lx\n", io
.Status
);
1365 memset(&fbi2
, 0, sizeof(fbi2
));
1366 fbi2
.LastAccessTime
.QuadPart
= 0x200deadcafebeef;
1367 io
.Status
= 0xdeadbeef;
1368 res
= pNtSetInformationFile(h
, &io
, &fbi2
, sizeof(fbi2
), FileBasicInformation
);
1369 ok ( res
== STATUS_SUCCESS
, "can't set access time, NtSetInformationFile returned %x\n", res
);
1370 ok ( io
.Status
== STATUS_SUCCESS
, "can't set access time, io.Status is %lx\n", io
.Status
);
1371 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof(fbi
), FileBasicInformation
);
1372 ok ( res
== STATUS_SUCCESS
, "can't get access time, NtQueryInformationFile returned %x\n", res
);
1373 ok ( io
.Status
== STATUS_SUCCESS
, "can't get access time, io.Status is %lx\n", io
.Status
);
1374 ok ( fbi2
.LastAccessTime
.QuadPart
== fbi
.LastAccessTime
.QuadPart
,
1375 "access time mismatch, set: %s get: %s\n",
1376 wine_dbgstr_longlong(fbi2
.LastAccessTime
.QuadPart
),
1377 wine_dbgstr_longlong(fbi
.LastAccessTime
.QuadPart
) );
1379 memset(&fbi2
, 0, sizeof(fbi2
));
1380 res
= pNtQueryInformationFile(h
, &io
, &fbi2
, sizeof fbi2
, FileBasicInformation
);
1381 ok ( res
== STATUS_SUCCESS
, "can't get write time 1, res %x\n", res
);
1382 ok ( fbi2
.LastWriteTime
.QuadPart
== fbi
.LastWriteTime
.QuadPart
, "write time mismatch, %s != %s\n",
1383 wine_dbgstr_longlong(fbi2
.LastWriteTime
.QuadPart
),
1384 wine_dbgstr_longlong(fbi
.LastWriteTime
.QuadPart
) );
1386 memset(&fbi2
, 0, sizeof(fbi2
));
1387 io
.Status
= 0xdeadbeef;
1388 res
= pNtSetInformationFile(h
, &io
, &fbi2
, sizeof fbi2
, FileBasicInformation
);
1389 ok ( res
== STATUS_SUCCESS
, "can't set nothing, NtSetInformationFile returned %x\n", res
);
1390 ok ( io
.Status
== STATUS_SUCCESS
, "can't set nothing, io.Status is %lx\n", io
.Status
);
1392 memset(&fbi2
, 0, sizeof(fbi2
));
1393 res
= pNtQueryInformationFile(h
, &io
, &fbi2
, sizeof fbi2
, FileBasicInformation
);
1394 ok ( res
== STATUS_SUCCESS
, "can't get write time 2, res %x\n", res
);
1395 ok ( fbi2
.LastWriteTime
.QuadPart
== fbi
.LastWriteTime
.QuadPart
, "write time changed, %s != %s\n",
1396 wine_dbgstr_longlong(fbi2
.LastWriteTime
.QuadPart
),
1397 wine_dbgstr_longlong(fbi
.LastWriteTime
.QuadPart
) );
1400 /* Clear fbi to avoid setting times */
1401 memset(&fbi
, 0, sizeof(fbi
));
1402 fbi
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
1403 io
.Status
= 0xdeadbeef;
1404 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1405 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, NtSetInformationFile returned %x\n", res
);
1406 ok ( io
.Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status is %lx\n", io
.Status
);
1408 memset(&fbi
, 0, sizeof(fbi
));
1409 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1410 ok ( res
== STATUS_SUCCESS
, "can't get system attribute\n");
1411 ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_SYSTEM
, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fbi
.FileAttributes
);
1414 memset(&fbi
, 0, sizeof(fbi
));
1415 fbi
.FileAttributes
= FILE_ATTRIBUTE_HIDDEN
;
1416 io
.Status
= 0xdeadbeef;
1417 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1418 ok ( res
== STATUS_SUCCESS
, "can't set hidden attribute, NtSetInformationFile returned %x\n", res
);
1419 ok ( io
.Status
== STATUS_SUCCESS
, "can't set hidden attribute, io.Status is %lx\n", io
.Status
);
1421 memset(&fbi
, 0, sizeof(fbi
));
1422 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1423 ok ( res
== STATUS_SUCCESS
, "can't get hidden attribute\n");
1424 ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_HIDDEN
, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\n", fbi
.FileAttributes
);
1426 /* Check NORMAL last of all (to make sure we can clear attributes) */
1427 memset(&fbi
, 0, sizeof(fbi
));
1428 fbi
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
1429 io
.Status
= 0xdeadbeef;
1430 res
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1431 ok ( res
== STATUS_SUCCESS
, "can't set normal attribute, NtSetInformationFile returned %x\n", res
);
1432 ok ( io
.Status
== STATUS_SUCCESS
, "can't set normal attribute, io.Status is %lx\n", io
.Status
);
1434 memset(&fbi
, 0, sizeof(fbi
));
1435 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
1436 ok ( res
== STATUS_SUCCESS
, "can't get normal attribute\n");
1437 todo_wine
ok ( (fbi
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_NORMAL
, "attribute %lx not 0\n", fbi
.FileAttributes
);
1442 static void test_file_all_information(void)
1445 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1446 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1447 * don't leave enough room there.
1450 FILE_ALL_INFORMATION fai
;
1455 int attrib_mask
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_NORMAL
;
1457 if (!(h
= create_temp_file(0))) return;
1459 /* Check default first */
1460 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1461 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1462 ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) == FILE_ATTRIBUTE_ARCHIVE
,
1463 "attribute %lx not expected\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1466 /* Clear fbi to avoid setting times */
1467 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1468 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
1469 io
.Status
= 0xdeadbeef;
1470 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1471 ok ( res
== STATUS_INVALID_INFO_CLASS
|| broken(res
== STATUS_NOT_IMPLEMENTED
), "shouldn't be able to set FileAllInformation, res %x\n", res
);
1472 todo_wine
ok ( io
.Status
== 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %lx\n", io
.Status
);
1473 io
.Status
= 0xdeadbeef;
1474 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1475 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1476 ok ( io
.Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %lx\n", io
.Status
);
1478 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1479 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1480 ok ( res
== STATUS_SUCCESS
, "can't get attributes, res %x\n", res
);
1481 ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_SYSTEM
, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1484 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1485 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_HIDDEN
;
1486 io
.Status
= 0xdeadbeef;
1487 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1488 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1489 ok ( io
.Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %lx\n", io
.Status
);
1491 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1492 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1493 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1494 ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_HIDDEN
, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1496 /* Check NORMAL last of all (to make sure we can clear attributes) */
1497 memset(&fai_buf
.fai
.BasicInformation
, 0, sizeof(fai_buf
.fai
.BasicInformation
));
1498 fai_buf
.fai
.BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
1499 io
.Status
= 0xdeadbeef;
1500 res
= pNtSetInformationFile(h
, &io
, &fai_buf
.fai
.BasicInformation
, sizeof fai_buf
.fai
.BasicInformation
, FileBasicInformation
);
1501 ok ( res
== STATUS_SUCCESS
, "can't set system attribute, res: %x\n", res
);
1502 ok ( io
.Status
== STATUS_SUCCESS
, "can't set system attribute, io.Status: %lx\n", io
.Status
);
1504 memset(&fai_buf
.fai
, 0, sizeof(fai_buf
.fai
));
1505 res
= pNtQueryInformationFile(h
, &io
, &fai_buf
.fai
, sizeof fai_buf
, FileAllInformation
);
1506 ok ( res
== STATUS_SUCCESS
, "can't get attributes\n");
1507 todo_wine
ok ( (fai_buf
.fai
.BasicInformation
.FileAttributes
& attrib_mask
) == FILE_ATTRIBUTE_NORMAL
, "attribute %lx not FILE_ATTRIBUTE_NORMAL\n", fai_buf
.fai
.BasicInformation
.FileAttributes
);
1512 static void delete_object( WCHAR
*path
)
1514 BOOL ret
= SetFileAttributesW( path
, FILE_ATTRIBUTE_NORMAL
);
1515 ok( ret
|| GetLastError() == ERROR_FILE_NOT_FOUND
, "SetFileAttribute failed with %lu\n", GetLastError() );
1516 ret
= DeleteFileW( path
);
1517 ok( ret
|| GetLastError() == ERROR_FILE_NOT_FOUND
|| GetLastError() == ERROR_ACCESS_DENIED
,
1518 "DeleteFileW failed with %lu\n", GetLastError() );
1519 if (!ret
&& GetLastError() == ERROR_ACCESS_DENIED
)
1521 ret
= RemoveDirectoryW( path
);
1522 ok( ret
, "RemoveDirectoryW failed with %lu\n", GetLastError() );
1526 static void test_file_rename_information(FILE_INFORMATION_CLASS
class)
1528 static const WCHAR foo_txtW
[] = {'\\','f','o','o','.','t','x','t',0};
1529 static const WCHAR fooW
[] = {'f','o','o',0};
1530 WCHAR tmp_path
[MAX_PATH
], oldpath
[MAX_PATH
+ 16], newpath
[MAX_PATH
+ 16], *filename
, *p
;
1531 FILE_RENAME_INFORMATION
*fri
;
1532 FILE_NAME_INFORMATION
*fni
;
1533 BOOL success
, fileDeleted
;
1534 UNICODE_STRING name_str
;
1535 HANDLE handle
, handle2
;
1539 GetTempPathW( MAX_PATH
, tmp_path
);
1541 /* oldpath is a file, newpath doesn't exist */
1542 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1543 ok( res
!= 0, "failed to create temp file\n" );
1544 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1545 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1547 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1548 ok( res
!= 0, "failed to create temp file\n" );
1549 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1550 DeleteFileW( newpath
);
1551 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1553 fri
->RootDirectory
= NULL
;
1554 fri
->FileNameLength
= name_str
.Length
;
1555 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1556 pRtlFreeUnicodeString( &name_str
);
1558 io
.Status
= 0xdeadbeef;
1559 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1561 if (class == FileRenameInformationEx
&& (res
== STATUS_NOT_IMPLEMENTED
|| res
== STATUS_INVALID_INFO_CLASS
))
1563 win_skip( "FileRenameInformationEx not supported\n" );
1564 CloseHandle( handle
);
1565 HeapFree( GetProcessHeap(), 0, fri
);
1566 delete_object( oldpath
);
1570 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
1571 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
1572 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1573 ok( fileDeleted
, "file should not exist\n" );
1574 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1575 ok( !fileDeleted
, "file should exist\n" );
1577 fni
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
) );
1578 res
= pNtQueryInformationFile( handle
, &io
, fni
, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
), FileNameInformation
);
1579 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
1580 fni
->FileName
[ fni
->FileNameLength
/ sizeof(WCHAR
) ] = 0;
1581 ok( !lstrcmpiW(fni
->FileName
, newpath
+ 2), "FileName expected %s, got %s\n",
1582 wine_dbgstr_w(newpath
+ 2), wine_dbgstr_w(fni
->FileName
) );
1583 HeapFree( GetProcessHeap(), 0, fni
);
1585 CloseHandle( handle
);
1586 HeapFree( GetProcessHeap(), 0, fri
);
1587 delete_object( oldpath
);
1588 delete_object( newpath
);
1590 /* oldpath is a file, newpath is a file, Replace = FALSE */
1591 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1592 ok( res
!= 0, "failed to create temp file\n" );
1593 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1594 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1596 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1597 ok( res
!= 0, "failed to create temp file\n" );
1598 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1599 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1601 fri
->RootDirectory
= NULL
;
1602 fri
->FileNameLength
= name_str
.Length
;
1603 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1604 pRtlFreeUnicodeString( &name_str
);
1606 io
.Status
= 0xdeadbeef;
1607 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1608 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
1609 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
1610 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1611 ok( !fileDeleted
, "file should exist\n" );
1612 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1613 ok( !fileDeleted
, "file should exist\n" );
1615 CloseHandle( handle
);
1616 HeapFree( GetProcessHeap(), 0, fri
);
1617 delete_object( oldpath
);
1618 delete_object( newpath
);
1620 /* oldpath is a file, newpath is a file, Replace = TRUE */
1621 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1622 ok( res
!= 0, "failed to create temp file\n" );
1623 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1624 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1626 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1627 ok( res
!= 0, "failed to create temp file\n" );
1628 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1629 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1630 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
1631 fri
->RootDirectory
= NULL
;
1632 fri
->FileNameLength
= name_str
.Length
;
1633 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1634 pRtlFreeUnicodeString( &name_str
);
1636 io
.Status
= 0xdeadbeef;
1637 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1638 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
1639 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
1640 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1641 ok( fileDeleted
, "file should not exist\n" );
1642 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1643 ok( !fileDeleted
, "file should exist\n" );
1645 CloseHandle( handle
);
1646 HeapFree( GetProcessHeap(), 0, fri
);
1647 delete_object( oldpath
);
1648 delete_object( newpath
);
1650 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1651 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1652 ok( res
!= 0, "failed to create temp file\n" );
1653 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1654 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1656 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1657 ok( res
!= 0, "failed to create temp file\n" );
1658 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1659 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1661 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1662 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1664 fri
->RootDirectory
= NULL
;
1665 fri
->FileNameLength
= name_str
.Length
;
1666 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1667 pRtlFreeUnicodeString( &name_str
);
1669 io
.Status
= 0xdeadbeef;
1670 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1671 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
1672 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
1673 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1674 ok( !fileDeleted
, "file should exist\n" );
1675 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1676 ok( !fileDeleted
, "file should exist\n" );
1678 CloseHandle( handle
);
1679 CloseHandle( handle2
);
1680 HeapFree( GetProcessHeap(), 0, fri
);
1681 delete_object( oldpath
);
1682 delete_object( newpath
);
1684 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1685 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1686 ok( res
!= 0, "failed to create temp file\n" );
1687 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1688 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1690 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1691 ok( res
!= 0, "failed to create temp file\n" );
1692 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1693 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1695 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1696 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1697 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
1698 fri
->RootDirectory
= NULL
;
1699 fri
->FileNameLength
= name_str
.Length
;
1700 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1701 pRtlFreeUnicodeString( &name_str
);
1703 io
.Status
= 0xdeadbeef;
1704 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1705 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
1706 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
1707 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1708 ok( !fileDeleted
, "file should exist\n" );
1709 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1710 ok( !fileDeleted
, "file should exist\n" );
1712 CloseHandle( handle
);
1713 CloseHandle( handle2
);
1714 HeapFree( GetProcessHeap(), 0, fri
);
1715 delete_object( oldpath
);
1716 delete_object( newpath
);
1718 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1719 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1720 ok( res
!= 0, "failed to create temp file\n" );
1721 DeleteFileW( oldpath
);
1722 success
= CreateDirectoryW( oldpath
, NULL
);
1723 ok( success
!= 0, "failed to create temp directory\n" );
1724 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1725 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1727 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1728 ok( res
!= 0, "failed to create temp file\n" );
1729 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1730 DeleteFileW( newpath
);
1731 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1733 fri
->RootDirectory
= NULL
;
1734 fri
->FileNameLength
= name_str
.Length
;
1735 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1736 pRtlFreeUnicodeString( &name_str
);
1738 io
.Status
= 0xdeadbeef;
1739 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1740 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
1741 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
1742 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1743 ok( fileDeleted
, "file should not exist\n" );
1744 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1745 ok( !fileDeleted
, "file should exist\n" );
1747 fni
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
) );
1748 res
= pNtQueryInformationFile( handle
, &io
, fni
, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
), FileNameInformation
);
1749 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
1750 fni
->FileName
[ fni
->FileNameLength
/ sizeof(WCHAR
) ] = 0;
1751 ok( !lstrcmpiW(fni
->FileName
, newpath
+ 2), "FileName expected %s, got %s\n",
1752 wine_dbgstr_w(newpath
+ 2), wine_dbgstr_w(fni
->FileName
) );
1753 HeapFree( GetProcessHeap(), 0, fni
);
1755 CloseHandle( handle
);
1756 HeapFree( GetProcessHeap(), 0, fri
);
1757 delete_object( oldpath
);
1758 delete_object( newpath
);
1760 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1761 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1762 ok( res
!= 0, "failed to create temp file\n" );
1763 DeleteFileW( oldpath
);
1764 success
= CreateDirectoryW( oldpath
, NULL
);
1765 ok( success
!= 0, "failed to create temp directory\n" );
1766 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1767 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1769 lstrcpyW( newpath
, oldpath
);
1770 lstrcatW( newpath
, foo_txtW
);
1771 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0 );
1772 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1774 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1775 ok( res
!= 0, "failed to create temp file\n" );
1776 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1777 DeleteFileW( newpath
);
1778 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1780 fri
->RootDirectory
= NULL
;
1781 fri
->FileNameLength
= name_str
.Length
;
1782 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1783 pRtlFreeUnicodeString( &name_str
);
1785 io
.Status
= 0xdeadbeef;
1786 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1787 todo_wine
ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_ACCESS_DENIED
, "io.Status got %lx\n", io
.Status
);
1788 todo_wine
ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
1789 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1790 todo_wine
ok( !fileDeleted
, "file should exist\n" );
1791 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1792 todo_wine
ok( fileDeleted
, "file should not exist\n" );
1794 CloseHandle( handle
);
1795 CloseHandle( handle2
);
1796 HeapFree( GetProcessHeap(), 0, fri
);
1797 delete_object( oldpath
);
1798 if (res
== STATUS_SUCCESS
) /* remove when Wine is fixed */
1800 lstrcpyW( oldpath
, newpath
);
1801 lstrcatW( oldpath
, foo_txtW
);
1802 delete_object( oldpath
);
1804 delete_object( newpath
);
1806 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1807 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1808 ok( res
!= 0, "failed to create temp file\n" );
1809 DeleteFileW( oldpath
);
1810 success
= CreateDirectoryW( oldpath
, NULL
);
1811 ok( success
!= 0, "failed to create temp directory\n" );
1812 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1813 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1815 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1816 ok( res
!= 0, "failed to create temp file\n" );
1817 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1818 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1820 fri
->RootDirectory
= NULL
;
1821 fri
->FileNameLength
= name_str
.Length
;
1822 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1823 pRtlFreeUnicodeString( &name_str
);
1825 io
.Status
= 0xdeadbeef;
1826 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1827 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_OBJECT_NAME_COLLISION
, "io.Status got %lx\n", io
.Status
);
1828 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
1829 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1830 ok( !fileDeleted
, "file should exist\n" );
1831 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1832 ok( !fileDeleted
, "file should exist\n" );
1834 CloseHandle( handle
);
1835 HeapFree( GetProcessHeap(), 0, fri
);
1836 delete_object( oldpath
);
1837 delete_object( newpath
);
1839 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1840 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1841 ok( res
!= 0, "failed to create temp file\n" );
1842 DeleteFileW( oldpath
);
1843 success
= CreateDirectoryW( oldpath
, NULL
);
1844 ok( success
!= 0, "failed to create temp directory\n" );
1845 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1846 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1848 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1849 ok( res
!= 0, "failed to create temp file\n" );
1850 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1851 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1853 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1854 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1856 fri
->RootDirectory
= NULL
;
1857 fri
->FileNameLength
= name_str
.Length
;
1858 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1859 pRtlFreeUnicodeString( &name_str
);
1861 io
.Status
= 0xdeadbeef;
1862 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1863 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_OBJECT_NAME_COLLISION
, "io.Status got %lx\n", io
.Status
);
1864 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
1865 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1866 ok( !fileDeleted
, "file should exist\n" );
1867 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1868 ok( !fileDeleted
, "file should exist\n" );
1870 CloseHandle( handle
);
1871 CloseHandle( handle2
);
1872 HeapFree( GetProcessHeap(), 0, fri
);
1873 delete_object( oldpath
);
1874 delete_object( newpath
);
1876 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1877 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1878 ok( res
!= 0, "failed to create temp file\n" );
1879 DeleteFileW( oldpath
);
1880 success
= CreateDirectoryW( oldpath
, NULL
);
1881 ok( success
!= 0, "failed to create temp directory\n" );
1882 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1883 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1885 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1886 ok( res
!= 0, "failed to create temp file\n" );
1887 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1888 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1889 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
1890 fri
->RootDirectory
= NULL
;
1891 fri
->FileNameLength
= name_str
.Length
;
1892 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1893 pRtlFreeUnicodeString( &name_str
);
1895 io
.Status
= 0xdeadbeef;
1896 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1897 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
1898 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
1899 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1900 ok( fileDeleted
, "file should not exist\n" );
1901 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1902 ok( !fileDeleted
, "file should exist\n" );
1904 CloseHandle( handle
);
1905 HeapFree( GetProcessHeap(), 0, fri
);
1906 delete_object( oldpath
);
1907 delete_object( newpath
);
1909 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1910 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1911 ok( res
!= 0, "failed to create temp file\n" );
1912 DeleteFileW( oldpath
);
1913 success
= CreateDirectoryW( oldpath
, NULL
);
1914 ok( success
!= 0, "failed to create temp directory\n" );
1915 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1916 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1918 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1919 ok( res
!= 0, "failed to create temp file\n" );
1920 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1921 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1923 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1924 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1925 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
1926 fri
->RootDirectory
= NULL
;
1927 fri
->FileNameLength
= name_str
.Length
;
1928 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1929 pRtlFreeUnicodeString( &name_str
);
1931 io
.Status
= 0xdeadbeef;
1932 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1933 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_ACCESS_DENIED
, "io.Status got %lx\n", io
.Status
);
1934 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
1935 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1936 ok( !fileDeleted
, "file should exist\n" );
1937 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1938 ok( !fileDeleted
, "file should exist\n" );
1940 CloseHandle( handle
);
1941 CloseHandle( handle2
);
1942 HeapFree( GetProcessHeap(), 0, fri
);
1943 delete_object( oldpath
);
1944 delete_object( newpath
);
1946 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1947 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1948 ok( res
!= 0, "failed to create temp file\n" );
1949 DeleteFileW( oldpath
);
1950 success
= CreateDirectoryW( oldpath
, NULL
);
1951 ok( success
!= 0, "failed to create temp directory\n" );
1952 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1953 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1955 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1956 ok( res
!= 0, "failed to create temp file\n" );
1957 DeleteFileW( newpath
);
1958 success
= CreateDirectoryW( newpath
, NULL
);
1959 ok( success
!= 0, "failed to create temp directory\n" );
1960 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1961 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1963 fri
->RootDirectory
= NULL
;
1964 fri
->FileNameLength
= name_str
.Length
;
1965 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
1966 pRtlFreeUnicodeString( &name_str
);
1968 io
.Status
= 0xdeadbeef;
1969 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
1970 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_OBJECT_NAME_COLLISION
, "io.Status got %lx\n", io
.Status
);
1971 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
1972 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1973 ok( !fileDeleted
, "file should exist\n" );
1974 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
1975 ok( !fileDeleted
, "file should exist\n" );
1977 CloseHandle( handle
);
1978 HeapFree( GetProcessHeap(), 0, fri
);
1979 delete_object( oldpath
);
1980 delete_object( newpath
);
1982 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1983 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
1984 ok( res
!= 0, "failed to create temp file\n" );
1985 DeleteFileW( oldpath
);
1986 success
= CreateDirectoryW( oldpath
, NULL
);
1987 ok( success
!= 0, "failed to create temp directory\n" );
1988 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
1989 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
1991 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
1992 ok( res
!= 0, "failed to create temp file\n" );
1993 DeleteFileW( newpath
);
1994 success
= CreateDirectoryW( newpath
, NULL
);
1995 ok( success
!= 0, "failed to create temp directory\n" );
1996 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
1997 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
1998 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
1999 fri
->RootDirectory
= NULL
;
2000 fri
->FileNameLength
= name_str
.Length
;
2001 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
2002 pRtlFreeUnicodeString( &name_str
);
2004 io
.Status
= 0xdeadbeef;
2005 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
2006 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_ACCESS_DENIED
, "io.Status got %lx\n", io
.Status
);
2007 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
2008 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2009 ok( !fileDeleted
, "file should exist\n" );
2010 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2011 ok( !fileDeleted
, "file should exist\n" );
2013 CloseHandle( handle
);
2014 HeapFree( GetProcessHeap(), 0, fri
);
2015 delete_object( oldpath
);
2016 delete_object( newpath
);
2018 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
2019 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2020 ok( res
!= 0, "failed to create temp file\n" );
2021 DeleteFileW( oldpath
);
2022 success
= CreateDirectoryW( oldpath
, NULL
);
2023 ok( success
!= 0, "failed to create temp directory\n" );
2024 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2025 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2027 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2028 ok( res
!= 0, "failed to create temp file\n" );
2029 DeleteFileW( newpath
);
2030 success
= CreateDirectoryW( newpath
, NULL
);
2031 ok( success
!= 0, "failed to create temp directory\n" );
2032 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2033 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2035 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2036 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
2037 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
2038 fri
->RootDirectory
= NULL
;
2039 fri
->FileNameLength
= name_str
.Length
;
2040 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
2041 pRtlFreeUnicodeString( &name_str
);
2043 io
.Status
= 0xdeadbeef;
2044 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
2045 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_ACCESS_DENIED
, "io.Status got %lx\n", io
.Status
);
2046 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
2047 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2048 ok( !fileDeleted
, "file should exist\n" );
2049 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2050 ok( !fileDeleted
, "file should exist\n" );
2052 CloseHandle( handle
);
2053 CloseHandle( handle2
);
2054 HeapFree( GetProcessHeap(), 0, fri
);
2055 delete_object( oldpath
);
2056 delete_object( newpath
);
2058 /* oldpath is a file, newpath is a directory, Replace = FALSE */
2059 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2060 ok( res
!= 0, "failed to create temp file\n" );
2061 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2062 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2064 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2065 ok( res
!= 0, "failed to create temp file\n" );
2066 DeleteFileW( newpath
);
2067 success
= CreateDirectoryW( newpath
, NULL
);
2068 ok( success
!= 0, "failed to create temp directory\n" );
2069 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2070 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
2072 fri
->RootDirectory
= NULL
;
2073 fri
->FileNameLength
= name_str
.Length
;
2074 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
2075 pRtlFreeUnicodeString( &name_str
);
2077 io
.Status
= 0xdeadbeef;
2078 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
2079 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2080 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
2081 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2082 ok( !fileDeleted
, "file should exist\n" );
2083 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2084 ok( !fileDeleted
, "file should exist\n" );
2086 CloseHandle( handle
);
2087 HeapFree( GetProcessHeap(), 0, fri
);
2088 delete_object( oldpath
);
2089 delete_object( newpath
);
2091 /* oldpath is a file, newpath is a directory, Replace = TRUE */
2092 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2093 ok( res
!= 0, "failed to create temp file\n" );
2094 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2095 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2097 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2098 ok( res
!= 0, "failed to create temp file\n" );
2099 DeleteFileW( newpath
);
2100 success
= CreateDirectoryW( newpath
, NULL
);
2101 ok( success
!= 0, "failed to create temp directory\n" );
2102 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2103 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
2104 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
2105 fri
->RootDirectory
= NULL
;
2106 fri
->FileNameLength
= name_str
.Length
;
2107 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
2108 pRtlFreeUnicodeString( &name_str
);
2110 io
.Status
= 0xdeadbeef;
2111 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
2112 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2113 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
2114 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2115 ok( !fileDeleted
, "file should exist\n" );
2116 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2117 ok( !fileDeleted
, "file should exist\n" );
2119 CloseHandle( handle
);
2120 HeapFree( GetProcessHeap(), 0, fri
);
2121 delete_object( oldpath
);
2122 delete_object( newpath
);
2124 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
2125 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2126 ok( res
!= 0, "failed to create temp file\n" );
2127 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2128 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2130 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2131 ok( res
!= 0, "failed to create temp file\n" );
2132 DeleteFileW( newpath
);
2133 for (filename
= newpath
, p
= newpath
; *p
; p
++)
2134 if (*p
== '\\') filename
= p
+ 1;
2135 handle2
= CreateFileW( tmp_path
, 0, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2136 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2138 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + lstrlenW(filename
) * sizeof(WCHAR
) );
2140 fri
->RootDirectory
= handle2
;
2141 fri
->FileNameLength
= lstrlenW(filename
) * sizeof(WCHAR
);
2142 memcpy( fri
->FileName
, filename
, fri
->FileNameLength
);
2144 io
.Status
= 0xdeadbeef;
2145 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
2146 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
2147 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2148 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2149 ok( fileDeleted
, "file should not exist\n" );
2150 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2151 ok( !fileDeleted
, "file should exist\n" );
2153 fni
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
) );
2154 res
= pNtQueryInformationFile( handle
, &io
, fni
, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
), FileNameInformation
);
2155 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2156 fni
->FileName
[ fni
->FileNameLength
/ sizeof(WCHAR
) ] = 0;
2157 ok( !lstrcmpiW(fni
->FileName
, newpath
+ 2), "FileName expected %s, got %s\n",
2158 wine_dbgstr_w(newpath
+ 2), wine_dbgstr_w(fni
->FileName
) );
2159 HeapFree( GetProcessHeap(), 0, fni
);
2161 CloseHandle( handle
);
2162 CloseHandle( handle2
);
2163 HeapFree( GetProcessHeap(), 0, fri
);
2164 delete_object( oldpath
);
2165 delete_object( newpath
);
2167 /* oldpath == newpath */
2168 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2169 ok( res
!= 0, "failed to create temp file\n" );
2170 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2171 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2173 pRtlDosPathNameToNtPathName_U( oldpath
, &name_str
, NULL
, NULL
);
2174 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
2176 fri
->RootDirectory
= NULL
;
2177 fri
->FileNameLength
= name_str
.Length
;
2178 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
2179 pRtlFreeUnicodeString( &name_str
);
2181 io
.Status
= 0xdeadbeef;
2182 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, class );
2183 ok( io
.Status
== STATUS_SUCCESS
, "got io status %#lx\n", io
.Status
);
2184 ok( res
== STATUS_SUCCESS
, "got status %lx\n", res
);
2185 ok( GetFileAttributesW( oldpath
) != INVALID_FILE_ATTRIBUTES
, "file should exist\n" );
2187 CloseHandle( handle
);
2188 HeapFree( GetProcessHeap(), 0, fri
);
2189 delete_object( oldpath
);
2192 static void test_file_rename_information_ex(void)
2194 static const WCHAR fooW
[] = {'f','o','o',0};
2195 WCHAR tmp_path
[MAX_PATH
], oldpath
[MAX_PATH
+ 16], newpath
[MAX_PATH
+ 16];
2196 FILE_RENAME_INFORMATION
*fri
;
2198 UNICODE_STRING name_str
;
2199 HANDLE handle
, handle2
;
2203 GetTempPathW( MAX_PATH
, tmp_path
);
2205 /* oldpath is a file, newpath is a read-only file, with FILE_RENAME_REPLACE_IF_EXISTS */
2206 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2207 ok( res
!= 0, "failed to create temp file\n" );
2208 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2209 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2211 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2212 ok( res
!= 0, "failed to create temp file\n" );
2213 DeleteFileW( newpath
);
2214 handle2
= CreateFileW( newpath
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0 );
2215 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2216 CloseHandle( handle2
);
2217 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2218 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
2219 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
;
2220 fri
->RootDirectory
= NULL
;
2221 fri
->FileNameLength
= name_str
.Length
;
2222 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
2223 pRtlFreeUnicodeString( &name_str
);
2225 io
.Status
= 0xdeadbeef;
2226 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, FileRenameInformationEx
);
2228 if (res
== STATUS_NOT_IMPLEMENTED
|| res
== STATUS_INVALID_INFO_CLASS
)
2230 win_skip( "FileRenameInformationEx not supported\n" );
2231 CloseHandle( handle
);
2232 HeapFree( GetProcessHeap(), 0, fri
);
2233 delete_object( oldpath
);
2237 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2238 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
2239 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2240 ok( !fileDeleted
, "file should exist\n" );
2241 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2242 ok( !fileDeleted
, "file should exist\n" );
2244 CloseHandle( handle
);
2245 HeapFree( GetProcessHeap(), 0, fri
);
2246 delete_object( oldpath
);
2247 delete_object( newpath
);
2249 /* oldpath is a file, newpath is a read-only file, with FILE_RENAME_REPLACE_IF_EXISTS and FILE_RENAME_IGNORE_READONLY_ATTRIBUTE */
2250 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2251 ok( res
!= 0, "failed to create temp file\n" );
2252 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2253 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2255 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2256 ok( res
!= 0, "failed to create temp file\n" );
2257 DeleteFileW( newpath
);
2258 handle2
= CreateFileW( newpath
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0 );
2259 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2260 CloseHandle( handle2
);
2261 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2262 fri
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
2263 fri
->Flags
= FILE_RENAME_REPLACE_IF_EXISTS
| FILE_RENAME_IGNORE_READONLY_ATTRIBUTE
;
2264 fri
->RootDirectory
= NULL
;
2265 fri
->FileNameLength
= name_str
.Length
;
2266 memcpy( fri
->FileName
, name_str
.Buffer
, name_str
.Length
);
2267 pRtlFreeUnicodeString( &name_str
);
2269 io
.Status
= 0xdeadbeef;
2270 res
= pNtSetInformationFile( handle
, &io
, fri
, sizeof(FILE_RENAME_INFORMATION
) + fri
->FileNameLength
, FileRenameInformationEx
);
2271 ok( io
.Status
== STATUS_SUCCESS
|| io
.Status
== 0xdeadbeef,
2272 "io.Status expected STATUS_SUCCESS or 0xdeadbeef, got %lx\n", io
.Status
);
2273 ok( res
== STATUS_SUCCESS
|| res
== STATUS_NOT_SUPPORTED
,
2274 "res expected STATUS_SUCCESS or STATUS_NOT_SUPPORTED, got %lx\n", res
);
2276 if (res
== STATUS_SUCCESS
)
2278 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2279 ok( fileDeleted
, "file should not exist\n" );
2280 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2281 ok( !fileDeleted
, "file should exist\n" );
2284 CloseHandle( handle
);
2285 HeapFree( GetProcessHeap(), 0, fri
);
2286 delete_object( oldpath
);
2287 delete_object( newpath
);
2290 static void test_file_link_information(FILE_INFORMATION_CLASS
class)
2292 static const WCHAR foo_txtW
[] = {'\\','f','o','o','.','t','x','t',0};
2293 static const WCHAR fooW
[] = {'f','o','o',0};
2294 WCHAR tmp_path
[MAX_PATH
], oldpath
[MAX_PATH
+ 16], newpath
[MAX_PATH
+ 16], *filename
, *p
;
2295 FILE_LINK_INFORMATION
*fli
;
2296 FILE_NAME_INFORMATION
*fni
;
2297 WIN32_FIND_DATAW find_data
;
2298 BOOL success
, fileDeleted
;
2299 UNICODE_STRING name_str
;
2300 HANDLE handle
, handle2
;
2304 GetTempPathW( MAX_PATH
, tmp_path
);
2306 /* oldpath is a file, newpath doesn't exist */
2307 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2308 ok( res
!= 0, "failed to create temp file\n" );
2309 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2310 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2312 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2313 ok( res
!= 0, "failed to create temp file\n" );
2314 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2315 DeleteFileW( newpath
);
2316 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2318 fli
->RootDirectory
= NULL
;
2319 fli
->FileNameLength
= name_str
.Length
;
2320 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2321 pRtlFreeUnicodeString( &name_str
);
2323 io
.Status
= 0xdeadbeef;
2324 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2326 if (class == FileLinkInformationEx
&& (res
== STATUS_NOT_IMPLEMENTED
|| res
== STATUS_INVALID_INFO_CLASS
))
2328 win_skip( "FileLinkInformationEx not supported\n" );
2329 CloseHandle( handle
);
2330 HeapFree( GetProcessHeap(), 0, fli
);
2331 delete_object( oldpath
);
2335 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
2336 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2337 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2338 ok( !fileDeleted
, "file should exist\n" );
2339 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2340 ok( !fileDeleted
, "file should exist\n" );
2342 fni
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
) );
2343 res
= pNtQueryInformationFile( handle
, &io
, fni
, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
), FileNameInformation
);
2344 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2345 fni
->FileName
[ fni
->FileNameLength
/ sizeof(WCHAR
) ] = 0;
2346 ok( !lstrcmpiW(fni
->FileName
, oldpath
+ 2), "FileName expected %s, got %s\n",
2347 wine_dbgstr_w(oldpath
+ 2), wine_dbgstr_w(fni
->FileName
) );
2348 HeapFree( GetProcessHeap(), 0, fni
);
2350 CloseHandle( handle
);
2351 HeapFree( GetProcessHeap(), 0, fli
);
2352 delete_object( oldpath
);
2353 delete_object( newpath
);
2355 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2356 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2357 ok( res
!= 0, "failed to create temp file\n" );
2358 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2359 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2361 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2362 ok( res
!= 0, "failed to create temp file\n" );
2363 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2364 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2366 fli
->RootDirectory
= NULL
;
2367 fli
->FileNameLength
= name_str
.Length
;
2368 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2369 pRtlFreeUnicodeString( &name_str
);
2371 io
.Status
= 0xdeadbeef;
2372 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2373 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2374 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
2375 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2376 ok( !fileDeleted
, "file should exist\n" );
2377 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2378 ok( !fileDeleted
, "file should exist\n" );
2380 CloseHandle( handle
);
2381 HeapFree( GetProcessHeap(), 0, fli
);
2382 delete_object( oldpath
);
2383 delete_object( newpath
);
2385 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2386 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2387 ok( res
!= 0, "failed to create temp file\n" );
2388 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2389 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2391 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2392 ok( res
!= 0, "failed to create temp file\n" );
2393 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2394 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2395 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2396 fli
->RootDirectory
= NULL
;
2397 fli
->FileNameLength
= name_str
.Length
;
2398 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2399 pRtlFreeUnicodeString( &name_str
);
2401 io
.Status
= 0xdeadbeef;
2402 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2403 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
2404 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2405 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2406 ok( !fileDeleted
, "file should exist\n" );
2407 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2408 ok( !fileDeleted
, "file should exist\n" );
2410 CloseHandle( handle
);
2411 HeapFree( GetProcessHeap(), 0, fli
);
2412 delete_object( oldpath
);
2413 delete_object( newpath
);
2415 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, different casing on link */
2416 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2417 ok( res
!= 0, "failed to create temp file\n" );
2418 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2419 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2421 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2422 ok( res
!= 0, "failed to create temp file\n" );
2423 wcsrchr( newpath
, '\\' )[1] = 'F';
2424 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2425 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2426 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2427 fli
->RootDirectory
= NULL
;
2428 fli
->FileNameLength
= name_str
.Length
;
2429 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2430 pRtlFreeUnicodeString( &name_str
);
2432 io
.Status
= 0xdeadbeef;
2433 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2434 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
2435 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2436 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2437 ok( !fileDeleted
, "file should exist\n" );
2438 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2439 ok( !fileDeleted
, "file should exist\n" );
2441 CloseHandle( handle
);
2442 handle
= FindFirstFileW( newpath
, &find_data
);
2443 ok(handle
!= INVALID_HANDLE_VALUE
, "FindFirstFileW: failed, error %ld\n", GetLastError());
2444 if (handle
!= INVALID_HANDLE_VALUE
)
2446 todo_wine
ok(!lstrcmpW(wcsrchr(newpath
, '\\') + 1, find_data
.cFileName
),
2447 "Link did not change casing on existing target file: got %s\n", wine_dbgstr_w(find_data
.cFileName
));
2450 FindClose( handle
);
2451 HeapFree( GetProcessHeap(), 0, fli
);
2452 delete_object( oldpath
);
2453 delete_object( newpath
);
2455 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2456 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2457 ok( res
!= 0, "failed to create temp file\n" );
2458 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2459 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2461 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2462 ok( res
!= 0, "failed to create temp file\n" );
2463 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2464 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2466 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2467 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2469 fli
->RootDirectory
= NULL
;
2470 fli
->FileNameLength
= name_str
.Length
;
2471 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2472 pRtlFreeUnicodeString( &name_str
);
2474 io
.Status
= 0xdeadbeef;
2475 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2476 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2477 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
2478 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2479 ok( !fileDeleted
, "file should exist\n" );
2480 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2481 ok( !fileDeleted
, "file should exist\n" );
2483 CloseHandle( handle
);
2484 CloseHandle( handle2
);
2485 HeapFree( GetProcessHeap(), 0, fli
);
2486 delete_object( oldpath
);
2487 delete_object( newpath
);
2489 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2490 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2491 ok( res
!= 0, "failed to create temp file\n" );
2492 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2493 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2495 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2496 ok( res
!= 0, "failed to create temp file\n" );
2497 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2498 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2500 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2501 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2502 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2503 fli
->RootDirectory
= NULL
;
2504 fli
->FileNameLength
= name_str
.Length
;
2505 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2506 pRtlFreeUnicodeString( &name_str
);
2508 io
.Status
= 0xdeadbeef;
2509 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2510 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2511 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
2512 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2513 ok( !fileDeleted
, "file should exist\n" );
2514 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2515 ok( !fileDeleted
, "file should exist\n" );
2517 CloseHandle( handle
);
2518 CloseHandle( handle2
);
2519 HeapFree( GetProcessHeap(), 0, fli
);
2520 delete_object( oldpath
);
2521 delete_object( newpath
);
2523 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2524 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2525 ok( res
!= 0, "failed to create temp file\n" );
2526 DeleteFileW( oldpath
);
2527 success
= CreateDirectoryW( oldpath
, NULL
);
2528 ok( success
!= 0, "failed to create temp directory\n" );
2529 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2530 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2532 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2533 ok( res
!= 0, "failed to create temp file\n" );
2534 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2535 DeleteFileW( newpath
);
2536 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2538 fli
->RootDirectory
= NULL
;
2539 fli
->FileNameLength
= name_str
.Length
;
2540 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2541 pRtlFreeUnicodeString( &name_str
);
2543 io
.Status
= 0xdeadbeef;
2544 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2545 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2546 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2547 ok( res
== STATUS_FILE_IS_A_DIRECTORY
, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2548 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2549 ok( !fileDeleted
, "file should exist\n" );
2550 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2551 ok( fileDeleted
, "file should not exist\n" );
2553 fni
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
) );
2554 res
= pNtQueryInformationFile( handle
, &io
, fni
, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
), FileNameInformation
);
2555 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2556 fni
->FileName
[ fni
->FileNameLength
/ sizeof(WCHAR
) ] = 0;
2557 ok( !lstrcmpiW(fni
->FileName
, oldpath
+ 2), "FileName expected %s, got %s\n",
2558 wine_dbgstr_w(oldpath
+ 2), wine_dbgstr_w(fni
->FileName
) );
2559 HeapFree( GetProcessHeap(), 0, fni
);
2561 CloseHandle( handle
);
2562 HeapFree( GetProcessHeap(), 0, fli
);
2563 delete_object( oldpath
);
2564 delete_object( newpath
);
2566 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2567 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2568 ok( res
!= 0, "failed to create temp file\n" );
2569 DeleteFileW( oldpath
);
2570 success
= CreateDirectoryW( oldpath
, NULL
);
2571 ok( success
!= 0, "failed to create temp directory\n" );
2572 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2573 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2575 lstrcpyW( newpath
, oldpath
);
2576 lstrcatW( newpath
, foo_txtW
);
2577 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0 );
2578 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2580 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2581 ok( res
!= 0, "failed to create temp file\n" );
2582 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2583 DeleteFileW( newpath
);
2584 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2586 fli
->RootDirectory
= NULL
;
2587 fli
->FileNameLength
= name_str
.Length
;
2588 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2589 pRtlFreeUnicodeString( &name_str
);
2591 io
.Status
= 0xdeadbeef;
2592 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2593 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2594 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2595 ok( res
== STATUS_FILE_IS_A_DIRECTORY
, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2596 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2597 ok( !fileDeleted
, "file should exist\n" );
2598 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2599 ok( fileDeleted
, "file should not exist\n" );
2601 CloseHandle( handle
);
2602 CloseHandle( handle2
);
2603 HeapFree( GetProcessHeap(), 0, fli
);
2604 delete_object( oldpath
);
2605 delete_object( newpath
);
2607 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2608 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2609 ok( res
!= 0, "failed to create temp file\n" );
2610 DeleteFileW( oldpath
);
2611 success
= CreateDirectoryW( oldpath
, NULL
);
2612 ok( success
!= 0, "failed to create temp directory\n" );
2613 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2614 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2616 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2617 ok( res
!= 0, "failed to create temp file\n" );
2618 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2619 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2621 fli
->RootDirectory
= NULL
;
2622 fli
->FileNameLength
= name_str
.Length
;
2623 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2624 pRtlFreeUnicodeString( &name_str
);
2626 io
.Status
= 0xdeadbeef;
2627 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2628 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2629 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2630 ok( res
== STATUS_OBJECT_NAME_COLLISION
|| res
== STATUS_FILE_IS_A_DIRECTORY
/* > Win XP */,
2631 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2632 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2633 ok( !fileDeleted
, "file should exist\n" );
2634 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2635 ok( !fileDeleted
, "file should exist\n" );
2637 CloseHandle( handle
);
2638 HeapFree( GetProcessHeap(), 0, fli
);
2639 delete_object( oldpath
);
2640 delete_object( newpath
);
2642 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2643 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2644 ok( res
!= 0, "failed to create temp file\n" );
2645 DeleteFileW( oldpath
);
2646 success
= CreateDirectoryW( oldpath
, NULL
);
2647 ok( success
!= 0, "failed to create temp directory\n" );
2648 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2649 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2651 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2652 ok( res
!= 0, "failed to create temp file\n" );
2653 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2654 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2656 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2657 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2659 fli
->RootDirectory
= NULL
;
2660 fli
->FileNameLength
= name_str
.Length
;
2661 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2662 pRtlFreeUnicodeString( &name_str
);
2664 io
.Status
= 0xdeadbeef;
2665 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2666 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2667 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2668 ok( res
== STATUS_OBJECT_NAME_COLLISION
|| res
== STATUS_FILE_IS_A_DIRECTORY
/* > Win XP */,
2669 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2670 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2671 ok( !fileDeleted
, "file should exist\n" );
2672 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2673 ok( !fileDeleted
, "file should exist\n" );
2675 CloseHandle( handle
);
2676 CloseHandle( handle2
);
2677 HeapFree( GetProcessHeap(), 0, fli
);
2678 delete_object( oldpath
);
2679 delete_object( newpath
);
2681 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2682 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2683 ok( res
!= 0, "failed to create temp file\n" );
2684 DeleteFileW( oldpath
);
2685 success
= CreateDirectoryW( oldpath
, NULL
);
2686 ok( success
!= 0, "failed to create temp directory\n" );
2687 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2688 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2690 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2691 ok( res
!= 0, "failed to create temp file\n" );
2692 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2693 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2694 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2695 fli
->RootDirectory
= NULL
;
2696 fli
->FileNameLength
= name_str
.Length
;
2697 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2698 pRtlFreeUnicodeString( &name_str
);
2700 io
.Status
= 0xdeadbeef;
2701 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2702 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2703 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2704 ok( res
== STATUS_FILE_IS_A_DIRECTORY
, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2705 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2706 ok( !fileDeleted
, "file should exist\n" );
2707 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2708 ok( !fileDeleted
, "file should exist\n" );
2710 CloseHandle( handle
);
2711 HeapFree( GetProcessHeap(), 0, fli
);
2712 delete_object( oldpath
);
2713 delete_object( newpath
);
2715 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2716 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2717 ok( res
!= 0, "failed to create temp file\n" );
2718 DeleteFileW( oldpath
);
2719 success
= CreateDirectoryW( oldpath
, NULL
);
2720 ok( success
!= 0, "failed to create temp directory\n" );
2721 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2722 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2724 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2725 ok( res
!= 0, "failed to create temp file\n" );
2726 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2727 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2729 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2730 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2731 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2732 fli
->RootDirectory
= NULL
;
2733 fli
->FileNameLength
= name_str
.Length
;
2734 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2735 pRtlFreeUnicodeString( &name_str
);
2737 io
.Status
= 0xdeadbeef;
2738 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2739 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2740 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2741 ok( res
== STATUS_FILE_IS_A_DIRECTORY
, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2742 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2743 ok( !fileDeleted
, "file should exist\n" );
2744 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2745 ok( !fileDeleted
, "file should exist\n" );
2747 CloseHandle( handle
);
2748 CloseHandle( handle2
);
2749 HeapFree( GetProcessHeap(), 0, fli
);
2750 delete_object( oldpath
);
2751 delete_object( newpath
);
2753 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2754 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2755 ok( res
!= 0, "failed to create temp file\n" );
2756 DeleteFileW( oldpath
);
2757 success
= CreateDirectoryW( oldpath
, NULL
);
2758 ok( success
!= 0, "failed to create temp directory\n" );
2759 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2760 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2762 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2763 ok( res
!= 0, "failed to create temp file\n" );
2764 DeleteFileW( newpath
);
2765 success
= CreateDirectoryW( newpath
, NULL
);
2766 ok( success
!= 0, "failed to create temp directory\n" );
2767 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2768 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2770 fli
->RootDirectory
= NULL
;
2771 fli
->FileNameLength
= name_str
.Length
;
2772 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2773 pRtlFreeUnicodeString( &name_str
);
2775 io
.Status
= 0xdeadbeef;
2776 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2777 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2778 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2779 ok( res
== STATUS_OBJECT_NAME_COLLISION
|| res
== STATUS_FILE_IS_A_DIRECTORY
/* > Win XP */,
2780 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2781 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2782 ok( !fileDeleted
, "file should exist\n" );
2783 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2784 ok( !fileDeleted
, "file should exist\n" );
2786 CloseHandle( handle
);
2787 HeapFree( GetProcessHeap(), 0, fli
);
2788 delete_object( oldpath
);
2789 delete_object( newpath
);
2791 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2792 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2793 ok( res
!= 0, "failed to create temp file\n" );
2794 DeleteFileW( oldpath
);
2795 success
= CreateDirectoryW( oldpath
, NULL
);
2796 ok( success
!= 0, "failed to create temp directory\n" );
2797 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2798 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2800 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2801 ok( res
!= 0, "failed to create temp file\n" );
2802 DeleteFileW( newpath
);
2803 success
= CreateDirectoryW( newpath
, NULL
);
2804 ok( success
!= 0, "failed to create temp directory\n" );
2805 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2806 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2807 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2808 fli
->RootDirectory
= NULL
;
2809 fli
->FileNameLength
= name_str
.Length
;
2810 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2811 pRtlFreeUnicodeString( &name_str
);
2813 io
.Status
= 0xdeadbeef;
2814 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2815 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2816 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2817 ok( res
== STATUS_FILE_IS_A_DIRECTORY
, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2818 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2819 ok( !fileDeleted
, "file should exist\n" );
2820 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2821 ok( !fileDeleted
, "file should exist\n" );
2823 CloseHandle( handle
);
2824 HeapFree( GetProcessHeap(), 0, fli
);
2825 delete_object( oldpath
);
2826 delete_object( newpath
);
2828 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2829 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2830 ok( res
!= 0, "failed to create temp file\n" );
2831 DeleteFileW( oldpath
);
2832 success
= CreateDirectoryW( oldpath
, NULL
);
2833 ok( success
!= 0, "failed to create temp directory\n" );
2834 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2835 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2837 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2838 ok( res
!= 0, "failed to create temp file\n" );
2839 DeleteFileW( newpath
);
2840 success
= CreateDirectoryW( newpath
, NULL
);
2841 ok( success
!= 0, "failed to create temp directory\n" );
2842 handle2
= CreateFileW( newpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2843 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2845 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2846 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2847 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2848 fli
->RootDirectory
= NULL
;
2849 fli
->FileNameLength
= name_str
.Length
;
2850 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2851 pRtlFreeUnicodeString( &name_str
);
2853 io
.Status
= 0xdeadbeef;
2854 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2855 ok( io
.Status
== 0xdeadbeef || io
.Status
== STATUS_FILE_IS_A_DIRECTORY
,
2856 "io.Status expected 0xdeadbeef or STATUS_FILE_IS_A_DIRECTORY, got %lx\n", io
.Status
);
2857 ok( res
== STATUS_FILE_IS_A_DIRECTORY
, "res expected STATUS_FILE_IS_A_DIRECTORY, got %lx\n", res
);
2858 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2859 ok( !fileDeleted
, "file should exist\n" );
2860 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2861 ok( !fileDeleted
, "file should exist\n" );
2863 CloseHandle( handle
);
2864 CloseHandle( handle2
);
2865 HeapFree( GetProcessHeap(), 0, fli
);
2866 delete_object( oldpath
);
2867 delete_object( newpath
);
2869 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2870 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2871 ok( res
!= 0, "failed to create temp file\n" );
2872 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2873 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2875 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2876 ok( res
!= 0, "failed to create temp file\n" );
2877 DeleteFileW( newpath
);
2878 success
= CreateDirectoryW( newpath
, NULL
);
2879 ok( success
!= 0, "failed to create temp directory\n" );
2880 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2881 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2883 fli
->RootDirectory
= NULL
;
2884 fli
->FileNameLength
= name_str
.Length
;
2885 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2886 pRtlFreeUnicodeString( &name_str
);
2888 io
.Status
= 0xdeadbeef;
2889 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2890 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2891 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "res expected STATUS_OBJECT_NAME_COLLISION, got %lx\n", res
);
2892 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2893 ok( !fileDeleted
, "file should exist\n" );
2894 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2895 ok( !fileDeleted
, "file should exist\n" );
2897 CloseHandle( handle
);
2898 HeapFree( GetProcessHeap(), 0, fli
);
2899 delete_object( oldpath
);
2900 delete_object( newpath
);
2902 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2903 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2904 ok( res
!= 0, "failed to create temp file\n" );
2905 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2906 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2908 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2909 ok( res
!= 0, "failed to create temp file\n" );
2910 DeleteFileW( newpath
);
2911 success
= CreateDirectoryW( newpath
, NULL
);
2912 ok( success
!= 0, "failed to create temp directory\n" );
2913 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
2914 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
2915 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2916 fli
->RootDirectory
= NULL
;
2917 fli
->FileNameLength
= name_str
.Length
;
2918 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2919 pRtlFreeUnicodeString( &name_str
);
2921 io
.Status
= 0xdeadbeef;
2922 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2923 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
2924 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
2925 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2926 ok( !fileDeleted
, "file should exist\n" );
2927 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2928 ok( !fileDeleted
, "file should exist\n" );
2930 CloseHandle( handle
);
2931 HeapFree( GetProcessHeap(), 0, fli
);
2932 delete_object( oldpath
);
2933 delete_object( newpath
);
2935 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2936 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2937 ok( res
!= 0, "failed to create temp file\n" );
2938 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2939 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2941 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
2942 ok( res
!= 0, "failed to create temp file\n" );
2943 DeleteFileW( newpath
);
2944 for (filename
= newpath
, p
= newpath
; *p
; p
++)
2945 if (*p
== '\\') filename
= p
+ 1;
2946 handle2
= CreateFileW( tmp_path
, 0, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
2947 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2949 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + lstrlenW(filename
) * sizeof(WCHAR
) );
2951 fli
->RootDirectory
= handle2
;
2952 fli
->FileNameLength
= lstrlenW(filename
) * sizeof(WCHAR
);
2953 memcpy( fli
->FileName
, filename
, fli
->FileNameLength
);
2955 io
.Status
= 0xdeadbeef;
2956 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2957 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
2958 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2959 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2960 ok( !fileDeleted
, "file should exist\n" );
2961 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
2962 ok( !fileDeleted
, "file should exist\n" );
2964 fni
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
) );
2965 res
= pNtQueryInformationFile( handle
, &io
, fni
, sizeof(FILE_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
), FileNameInformation
);
2966 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
2967 fni
->FileName
[ fni
->FileNameLength
/ sizeof(WCHAR
) ] = 0;
2968 ok( !lstrcmpiW(fni
->FileName
, oldpath
+ 2), "FileName expected %s, got %s\n",
2969 wine_dbgstr_w(oldpath
+ 2), wine_dbgstr_w(fni
->FileName
) );
2970 HeapFree( GetProcessHeap(), 0, fni
);
2972 CloseHandle( handle
);
2973 CloseHandle( handle2
);
2974 HeapFree( GetProcessHeap(), 0, fli
);
2975 delete_object( oldpath
);
2976 delete_object( newpath
);
2978 /* oldpath == newpath */
2979 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
2980 ok( res
!= 0, "failed to create temp file\n" );
2981 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
2982 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
2984 pRtlDosPathNameToNtPathName_U( oldpath
, &name_str
, NULL
, NULL
);
2985 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
2987 fli
->RootDirectory
= NULL
;
2988 fli
->FileNameLength
= name_str
.Length
;
2989 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
2990 pRtlFreeUnicodeString( &name_str
);
2992 io
.Status
= 0xdeadbeef;
2993 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
2994 todo_wine
ok( io
.Status
== 0xdeadbeef, "got io status %#lx\n", io
.Status
);
2995 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "got status %lx\n", res
);
2997 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
2998 io
.Status
= 0xdeadbeef;
2999 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
3000 ok( io
.Status
== STATUS_SUCCESS
, "got io status %#lx\n", io
.Status
);
3001 ok( res
== STATUS_SUCCESS
, "got status %lx\n", res
);
3002 ok( GetFileAttributesW( oldpath
) != INVALID_FILE_ATTRIBUTES
, "file should exist\n" );
3004 CloseHandle( handle
);
3005 HeapFree( GetProcessHeap(), 0, fli
);
3006 delete_object( oldpath
);
3008 /* oldpath == newpath, different casing on link */
3009 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
3010 ok( res
!= 0, "failed to create temp file\n" );
3011 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3012 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
3014 wcsrchr( oldpath
, '\\' )[1] = 'F';
3015 pRtlDosPathNameToNtPathName_U( oldpath
, &name_str
, NULL
, NULL
);
3016 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION
) + name_str
.Length
);
3018 fli
->RootDirectory
= NULL
;
3019 fli
->FileNameLength
= name_str
.Length
;
3020 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
3021 pRtlFreeUnicodeString( &name_str
);
3023 io
.Status
= 0xdeadbeef;
3024 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
3025 todo_wine
ok( io
.Status
== 0xdeadbeef, "got io status %#lx\n", io
.Status
);
3026 ok( res
== STATUS_OBJECT_NAME_COLLISION
, "got status %lx\n", res
);
3028 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
3029 io
.Status
= 0xdeadbeef;
3030 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, class );
3031 ok( io
.Status
== STATUS_SUCCESS
, "got io status %#lx\n", io
.Status
);
3032 ok( res
== STATUS_SUCCESS
, "got status %lx\n", res
);
3033 ok( GetFileAttributesW( oldpath
) != INVALID_FILE_ATTRIBUTES
, "file should exist\n" );
3035 CloseHandle( handle
);
3036 handle
= FindFirstFileW( oldpath
, &find_data
);
3037 ok(handle
!= INVALID_HANDLE_VALUE
, "FindFirstFileW: failed, error %ld\n", GetLastError());
3038 if (handle
!= INVALID_HANDLE_VALUE
)
3040 todo_wine
ok(!lstrcmpW(wcsrchr(oldpath
, '\\') + 1, find_data
.cFileName
),
3041 "Link did not change casing on same file: got %s\n", wine_dbgstr_w(find_data
.cFileName
));
3044 FindClose( handle
);
3045 HeapFree( GetProcessHeap(), 0, fli
);
3046 delete_object( oldpath
);
3049 static void test_file_link_information_ex(void)
3051 static const WCHAR fooW
[] = {'f','o','o',0};
3052 WCHAR tmp_path
[MAX_PATH
], oldpath
[MAX_PATH
+ 16], newpath
[MAX_PATH
+ 16];
3053 FILE_LINK_INFORMATION
*fli
;
3055 UNICODE_STRING name_str
;
3056 HANDLE handle
, handle2
;
3060 GetTempPathW( MAX_PATH
, tmp_path
);
3062 /* oldpath is a file, newpath is a read-only file, with FILE_LINK_REPLACE_IF_EXISTS */
3063 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
3064 ok( res
!= 0, "failed to create temp file\n" );
3065 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3066 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
3068 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
3069 ok( res
!= 0, "failed to create temp file\n" );
3070 DeleteFileW( newpath
);
3071 handle2
= CreateFileW( newpath
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0 );
3072 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
3073 CloseHandle( handle2
);
3074 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
3075 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
3076 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
;
3077 fli
->RootDirectory
= NULL
;
3078 fli
->FileNameLength
= name_str
.Length
;
3079 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
3080 pRtlFreeUnicodeString( &name_str
);
3082 io
.Status
= 0xdeadbeef;
3083 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, FileLinkInformationEx
);
3085 if (res
== STATUS_NOT_IMPLEMENTED
|| res
== STATUS_INVALID_INFO_CLASS
)
3087 win_skip( "FileLinkInformationEx not supported\n" );
3088 CloseHandle( handle
);
3089 HeapFree( GetProcessHeap(), 0, fli
);
3090 delete_object( oldpath
);
3094 todo_wine
ok( io
.Status
== 0xdeadbeef, "io.Status expected 0xdeadbeef, got %lx\n", io
.Status
);
3095 ok( res
== STATUS_ACCESS_DENIED
, "res expected STATUS_ACCESS_DENIED, got %lx\n", res
);
3096 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3097 ok( !fileDeleted
, "file should exist\n" );
3098 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3099 ok( !fileDeleted
, "file should exist\n" );
3101 CloseHandle( handle
);
3102 HeapFree( GetProcessHeap(), 0, fli
);
3103 delete_object( oldpath
);
3104 delete_object( newpath
);
3106 /* oldpath is a file, newpath is a read-only file, with FILE_LINK_REPLACE_IF_EXISTS and FILE_LINK_IGNORE_READONLY_ATTRIBUTE */
3107 res
= GetTempFileNameW( tmp_path
, fooW
, 0, oldpath
);
3108 ok( res
!= 0, "failed to create temp file\n" );
3109 handle
= CreateFileW( oldpath
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3110 ok( handle
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
3112 res
= GetTempFileNameW( tmp_path
, fooW
, 0, newpath
);
3113 ok( res
!= 0, "failed to create temp file\n" );
3114 DeleteFileW( newpath
);
3115 handle2
= CreateFileW( newpath
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0 );
3116 ok( handle2
!= INVALID_HANDLE_VALUE
, "CreateFileW failed\n" );
3117 CloseHandle( handle2
);
3118 pRtlDosPathNameToNtPathName_U( newpath
, &name_str
, NULL
, NULL
);
3119 fli
= HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION
) + name_str
.Length
);
3120 fli
->Flags
= FILE_LINK_REPLACE_IF_EXISTS
| FILE_LINK_IGNORE_READONLY_ATTRIBUTE
;
3121 fli
->RootDirectory
= NULL
;
3122 fli
->FileNameLength
= name_str
.Length
;
3123 memcpy( fli
->FileName
, name_str
.Buffer
, name_str
.Length
);
3124 pRtlFreeUnicodeString( &name_str
);
3126 io
.Status
= 0xdeadbeef;
3127 res
= pNtSetInformationFile( handle
, &io
, fli
, sizeof(FILE_LINK_INFORMATION
) + fli
->FileNameLength
, FileLinkInformationEx
);
3128 ok( io
.Status
== STATUS_SUCCESS
, "io.Status expected STATUS_SUCCESS, got %lx\n", io
.Status
);
3129 ok( res
== STATUS_SUCCESS
, "res expected STATUS_SUCCESS, got %lx\n", res
);
3130 fileDeleted
= GetFileAttributesW( oldpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3131 ok( !fileDeleted
, "file should exist\n" );
3132 fileDeleted
= GetFileAttributesW( newpath
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3133 ok( !fileDeleted
, "file should exist\n" );
3135 CloseHandle( handle
);
3136 HeapFree( GetProcessHeap(), 0, fli
);
3137 delete_object( oldpath
);
3138 delete_object( newpath
);
3141 static void test_file_both_information(void)
3144 FILE_BOTH_DIR_INFORMATION fbi
;
3148 if (!(h
= create_temp_file(0))) return;
3150 memset(&fbi
, 0, sizeof(fbi
));
3151 res
= pNtQueryInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBothDirectoryInformation
);
3152 ok ( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_NOT_IMPLEMENTED
, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res
);
3157 static NTSTATUS
nt_get_file_attrs(const char *name
, DWORD
*attrs
)
3159 WCHAR nameW
[MAX_PATH
];
3160 FILE_BASIC_INFORMATION info
;
3161 UNICODE_STRING nt_name
;
3162 OBJECT_ATTRIBUTES attr
;
3165 MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, MAX_PATH
);
3167 *attrs
= INVALID_FILE_ATTRIBUTES
;
3169 if (!pRtlDosPathNameToNtPathName_U( nameW
, &nt_name
, NULL
, NULL
))
3170 return STATUS_UNSUCCESSFUL
;
3172 attr
.Length
= sizeof(attr
);
3173 attr
.RootDirectory
= 0;
3174 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3175 attr
.ObjectName
= &nt_name
;
3176 attr
.SecurityDescriptor
= NULL
;
3177 attr
.SecurityQualityOfService
= NULL
;
3179 status
= pNtQueryAttributesFile( &attr
, &info
);
3180 pRtlFreeUnicodeString( &nt_name
);
3182 if (status
== STATUS_SUCCESS
)
3183 *attrs
= info
.FileAttributes
;
3188 static void test_file_disposition_information(void)
3190 char tmp_path
[MAX_PATH
], buffer
[MAX_PATH
+ 16];
3192 HANDLE handle
, handle2
, handle3
, mapping
;
3195 FILE_DISPOSITION_INFORMATION fdi
;
3196 FILE_DISPOSITION_INFORMATION_EX fdie
;
3197 FILE_STANDARD_INFORMATION fsi
;
3202 GetTempPathA( MAX_PATH
, tmp_path
);
3204 /* tests for info struct size */
3205 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3206 handle
= CreateFileA( buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3207 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3208 res
= pNtSetInformationFile( handle
, &io
, &fdi
, 0, FileDispositionInformation
);
3210 ok( res
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %lx\n", res
);
3212 res
= pNtSetInformationFile( handle
, &io
, &fdi2
, sizeof(fdi2
), FileDispositionInformation
);
3213 ok( res
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %lx\n", res
);
3214 CloseHandle( handle
);
3215 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3216 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3217 DeleteFileA( buffer
);
3219 /* cannot set disposition on file not opened with delete access */
3220 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3221 handle
= CreateFileA(buffer
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3222 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3223 res
= pNtQueryInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3224 ok( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_NOT_IMPLEMENTED
, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %lx)\n", res
);
3225 fdi
.DoDeleteFile
= TRUE
;
3226 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3227 ok( res
== STATUS_ACCESS_DENIED
, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %lx)\n", res
);
3228 CloseHandle( handle
);
3229 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3230 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3231 DeleteFileA( buffer
);
3233 /* can set disposition on file opened with proper access */
3234 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3235 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3236 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3237 fdi
.DoDeleteFile
= TRUE
;
3238 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3239 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3240 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3241 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3243 ok(fsi
.DeletePending
, "Handle should be marked for deletion\n");
3244 CloseHandle( handle
);
3245 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3246 ok( fileDeleted
, "File should have been deleted\n" );
3248 /* file exists until all handles to it get closed */
3249 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3250 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, 0, 0);
3251 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3252 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3253 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to open temp file\n" );
3254 fdi
.DoDeleteFile
= TRUE
;
3255 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3256 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3257 res
= nt_get_file_attrs( buffer
, &fdi2
);
3259 ok( res
== STATUS_DELETE_PENDING
, "got %#lx\n", res
);
3260 /* can't open the deleted file */
3261 handle3
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3263 ok( handle3
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3264 if (handle3
!= INVALID_HANDLE_VALUE
)
3265 CloseHandle( handle3
);
3267 ok(GetLastError() == ERROR_ACCESS_DENIED
, "got %lu\n", GetLastError());
3268 /* can't open the deleted file (wrong sharing mode) */
3269 handle3
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3270 ok( handle3
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3272 ok(GetLastError() == ERROR_ACCESS_DENIED
, "got %lu\n", GetLastError());
3273 CloseHandle( handle
);
3274 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3275 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3276 CloseHandle( handle2
);
3277 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3278 ok( fileDeleted
, "File should have been deleted\n" );
3280 /* file exists until all handles to it get closed */
3281 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3282 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0);
3283 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3284 /* can open the marked for delete file (proper sharing mode) */
3285 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3286 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to open temp file\n" );
3287 res
= nt_get_file_attrs( buffer
, &fdi2
);
3288 ok( res
== STATUS_SUCCESS
, "got %#lx\n", res
);
3289 /* can't open the marked for delete file (wrong sharing mode) */
3290 handle3
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3291 ok( handle3
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3292 ok(GetLastError() == ERROR_SHARING_VIOLATION
, "got %lu\n", GetLastError());
3293 CloseHandle( handle
);
3294 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3295 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3296 CloseHandle( handle2
);
3297 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3298 ok( fileDeleted
, "File should have been deleted\n" );
3300 /* file is deleted after handle with FILE_DISPOSITION_POSIX_SEMANTICS is closed */
3301 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3302 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3303 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, 0, 0);
3304 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3305 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3306 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to open temp file\n" );
3307 fdie
.Flags
= FILE_DISPOSITION_DELETE
| FILE_DISPOSITION_POSIX_SEMANTICS
;
3308 res
= pNtSetInformationFile( handle
, &io
, &fdie
, sizeof fdie
, FileDispositionInformationEx
);
3309 ok( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_SUCCESS
,
3310 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res
);
3311 CloseHandle( handle
);
3312 if ( res
== STATUS_SUCCESS
)
3314 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3315 ok( fileDeleted
, "File should have been deleted\n" );
3317 CloseHandle( handle2
);
3319 /* file is deleted after handle with FILE_DISPOSITION_POSIX_SEMANTICS is closed */
3320 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3321 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3322 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, 0, 0);
3323 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3324 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3325 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to open temp file\n" );
3326 fdie
.Flags
= FILE_DISPOSITION_DELETE
| FILE_DISPOSITION_POSIX_SEMANTICS
;
3327 res
= pNtSetInformationFile( handle
, &io
, &fdie
, sizeof fdie
, FileDispositionInformationEx
);
3328 ok( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_SUCCESS
,
3329 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res
);
3330 CloseHandle( handle2
);
3331 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3332 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3333 CloseHandle( handle
);
3334 if ( res
== STATUS_SUCCESS
)
3336 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3337 ok( fileDeleted
, "File should have been deleted\n" );
3340 /* cannot set disposition on readonly file */
3341 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3342 DeleteFileA( buffer
);
3343 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0);
3344 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3345 fdi
.DoDeleteFile
= TRUE
;
3346 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3347 ok( res
== STATUS_CANNOT_DELETE
, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %lx)\n", res
);
3348 CloseHandle( handle
);
3349 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3350 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3351 SetFileAttributesA( buffer
, FILE_ATTRIBUTE_NORMAL
);
3352 DeleteFileA( buffer
);
3354 /* cannot set disposition on readonly file */
3355 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3356 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0);
3357 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3358 fdi
.DoDeleteFile
= TRUE
;
3359 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3361 ok( res
== STATUS_CANNOT_DELETE
, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %lx)\n", res
);
3362 CloseHandle( handle
);
3363 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3365 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3366 SetFileAttributesA( buffer
, FILE_ATTRIBUTE_NORMAL
);
3367 DeleteFileA( buffer
);
3369 /* set disposition on readonly file ignoring readonly attribute */
3370 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3371 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3372 DeleteFileA( buffer
);
3373 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_READONLY
, 0);
3374 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3375 fdie
.Flags
= FILE_DISPOSITION_DELETE
| FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE
;
3376 res
= pNtSetInformationFile( handle
, &io
, &fdie
, sizeof fdie
, FileDispositionInformationEx
);
3377 ok( res
== STATUS_SUCCESS
3378 || broken(res
== STATUS_INVALID_INFO_CLASS
) /* win10 1507 & 32-bit 1607 */
3379 || broken(res
== STATUS_NOT_SUPPORTED
), /* win10 1709 & 64-bit 1607 */
3380 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res
);
3381 CloseHandle( handle
);
3382 if ( res
== STATUS_SUCCESS
)
3384 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3385 ok( fileDeleted
, "File should have been deleted\n" );
3387 SetFileAttributesA( buffer
, FILE_ATTRIBUTE_NORMAL
);
3388 DeleteFileA( buffer
);
3390 /* can set disposition on file and then reset it */
3391 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3392 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3393 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3394 fdi
.DoDeleteFile
= TRUE
;
3395 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3396 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3397 fdi
.DoDeleteFile
= FALSE
;
3398 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3399 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3400 CloseHandle( handle
);
3401 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3402 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3403 DeleteFileA( buffer
);
3405 /* can't reset disposition if delete-on-close flag is specified */
3406 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3407 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0);
3408 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3409 fdi
.DoDeleteFile
= FALSE
;
3410 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3411 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3412 CloseHandle( handle
);
3413 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3414 ok( fileDeleted
, "File should have been deleted\n" );
3416 /* can't reset disposition on duplicated handle if delete-on-close flag is specified */
3417 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3418 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0);
3419 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3420 ok( DuplicateHandle( GetCurrentProcess(), handle
, GetCurrentProcess(), &handle2
, 0, FALSE
, DUPLICATE_SAME_ACCESS
), "DuplicateHandle failed\n" );
3421 CloseHandle( handle
);
3422 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3423 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3424 fdi
.DoDeleteFile
= FALSE
;
3425 res
= pNtSetInformationFile( handle2
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3426 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3427 CloseHandle( handle2
);
3428 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3429 ok( fileDeleted
, "File should have been deleted\n" );
3431 /* can reset delete-on-close flag through FileDispositionInformationEx */
3432 /* FileDispositionInformationEx is only supported on Windows 10 build 1809 and later */
3433 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3434 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0);
3435 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3436 fdie
.Flags
= FILE_DISPOSITION_ON_CLOSE
;
3437 res
= pNtSetInformationFile( handle
, &io
, &fdie
, sizeof fdie
, FileDispositionInformationEx
);
3438 ok( res
== STATUS_INVALID_INFO_CLASS
|| res
== STATUS_SUCCESS
,
3439 "unexpected FileDispositionInformationEx result (expected STATUS_SUCCESS or SSTATUS_INVALID_INFO_CLASS, got %lx)\n", res
);
3440 CloseHandle( handle
);
3441 if ( res
== STATUS_SUCCESS
)
3443 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3444 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3445 DeleteFileA( buffer
);
3448 /* DeleteFile fails for wrong sharing mode */
3449 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3450 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3451 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3452 fileDeleted
= DeleteFileA( buffer
);
3453 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3454 ok(GetLastError() == ERROR_SHARING_VIOLATION
, "got %lu\n", GetLastError());
3455 CloseHandle( handle
);
3456 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3457 ok( !fileDeleted
, "File shouldn't have been deleted\n" );
3458 DeleteFileA( buffer
);
3460 /* DeleteFile succeeds for proper sharing mode */
3461 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3462 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, 0, 0);
3463 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3464 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3465 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3466 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3467 fileDeleted
= DeleteFileA( buffer
);
3468 ok( fileDeleted
, "File should have been deleted\n" );
3469 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3470 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3472 ok(fsi
.DeletePending
, "Handle should be marked for deletion\n");
3473 res
= nt_get_file_attrs( buffer
, &fdi2
);
3475 ok( res
== STATUS_OBJECT_NAME_NOT_FOUND
|| broken(res
== STATUS_DELETE_PENDING
), "got %#lx\n", res
);
3476 /* can't open the deleted file */
3477 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3479 ok( handle2
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3481 ok( GetLastError() == ERROR_FILE_NOT_FOUND
|| broken(GetLastError() == ERROR_ACCESS_DENIED
), "got %lu\n", GetLastError());
3482 if (handle2
!= INVALID_HANDLE_VALUE
)
3483 CloseHandle( handle2
);
3484 CloseHandle( handle
);
3485 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3486 ok( fileDeleted
, "File should have been deleted\n" );
3488 /* can set disposition on a directory opened with proper access */
3489 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3490 DeleteFileA( buffer
);
3491 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
3492 handle
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3493 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3494 fdi
.DoDeleteFile
= TRUE
;
3495 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3496 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3497 CloseHandle( handle
);
3498 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3499 ok( fileDeleted
, "Directory should have been deleted\n" );
3501 /* RemoveDirectory fails for wrong sharing mode */
3502 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3503 DeleteFileA( buffer
);
3504 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
3505 handle
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3506 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3507 fileDeleted
= RemoveDirectoryA( buffer
);
3508 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
3509 ok(GetLastError() == ERROR_SHARING_VIOLATION
, "got %lu\n", GetLastError());
3510 CloseHandle( handle
);
3511 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3512 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
3513 RemoveDirectoryA( buffer
);
3515 /* RemoveDirectory succeeds for proper sharing mode */
3516 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3517 DeleteFileA( buffer
);
3518 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
3519 handle
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3520 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3521 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3522 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3523 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3524 fileDeleted
= RemoveDirectoryA( buffer
);
3525 ok( fileDeleted
, "Directory should have been deleted\n" );
3526 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3527 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3529 ok(fsi
.DeletePending
, "Handle should be marked for deletion\n");
3530 res
= nt_get_file_attrs( buffer
, &fdi2
);
3532 ok( res
== STATUS_OBJECT_NAME_NOT_FOUND
|| broken(res
== STATUS_DELETE_PENDING
), "got %#lx\n", res
);
3533 /* can't open the deleted directory */
3534 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3536 ok( handle2
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3538 ok(GetLastError() == ERROR_FILE_NOT_FOUND
|| broken(GetLastError() == ERROR_ACCESS_DENIED
), "got %lu\n", GetLastError());
3539 if (handle2
!= INVALID_HANDLE_VALUE
) CloseHandle( handle2
);
3540 CloseHandle( handle
);
3541 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3542 ok( fileDeleted
, "Directory should have been deleted\n" );
3544 /* directory exists until all handles to it get closed */
3545 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3546 DeleteFileA( buffer
);
3547 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
3548 handle
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3549 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3550 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3551 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3552 fdi
.DoDeleteFile
= TRUE
;
3553 res
= pNtSetInformationFile( handle2
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3554 ok( res
== STATUS_SUCCESS
, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res
);
3555 res
= nt_get_file_attrs( buffer
, &fdi2
);
3557 ok( res
== STATUS_DELETE_PENDING
, "got %#lx\n", res
);
3558 /* can't open the deleted directory */
3559 handle3
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3561 ok( handle3
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3562 if (handle3
!= INVALID_HANDLE_VALUE
)
3563 CloseHandle( handle3
);
3565 ok(GetLastError() == ERROR_ACCESS_DENIED
, "got %lu\n", GetLastError());
3566 /* can't open the deleted directory (wrong sharing mode) */
3567 handle3
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3568 ok( handle3
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3570 ok(GetLastError() == ERROR_ACCESS_DENIED
, "got %lu\n", GetLastError());
3571 CloseHandle( handle2
);
3572 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3573 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
3574 CloseHandle( handle
);
3575 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3576 ok( fileDeleted
, "Directory should have been deleted\n" );
3578 /* directory exists until all handles to it get closed */
3579 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3580 DeleteFileA( buffer
);
3581 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
3582 handle
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_DELETE_ON_CLOSE
, 0);
3583 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3584 /* can open the marked for delete directory (proper sharing mode) */
3585 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3586 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3587 /* can't open the marked for delete file (wrong sharing mode) */
3588 handle3
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3589 ok( handle3
== INVALID_HANDLE_VALUE
, "CreateFile should fail\n" );
3590 ok(GetLastError() == ERROR_SHARING_VIOLATION
, "got %lu\n", GetLastError());
3591 CloseHandle( handle
);
3592 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3593 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
3594 CloseHandle( handle2
);
3595 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3596 ok( fileDeleted
, "Directory should have been deleted\n" );
3598 /* can open a non-empty directory with FILE_FLAG_DELETE_ON_CLOSE */
3599 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3600 DeleteFileA( buffer
);
3601 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
3602 dirpos
= lstrlenA( buffer
);
3603 lstrcpyA( buffer
+ dirpos
, "\\tst" );
3604 handle2
= CreateFileA(buffer
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3605 CloseHandle( handle2
);
3606 buffer
[dirpos
] = '\0';
3607 handle
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_DELETE_ON_CLOSE
, 0);
3608 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3609 SetLastError(0xdeadbeef);
3610 CloseHandle( handle
);
3611 ok(GetLastError() == 0xdeadbeef, "got %lu\n", GetLastError());
3612 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3613 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
3614 buffer
[dirpos
] = '\\';
3615 fileDeleted
= DeleteFileA( buffer
);
3616 ok( fileDeleted
, "File should have been deleted\n" );
3617 buffer
[dirpos
] = '\0';
3618 fileDeleted
= RemoveDirectoryA( buffer
);
3619 ok( fileDeleted
, "Directory should have been deleted\n" );
3621 /* cannot set disposition on a non-empty directory */
3622 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3623 DeleteFileA( buffer
);
3624 ok( CreateDirectoryA( buffer
, NULL
), "CreateDirectory failed\n" );
3625 handle
= CreateFileA(buffer
, DELETE
, 0, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
3626 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to open a directory\n" );
3627 dirpos
= lstrlenA( buffer
);
3628 lstrcpyA( buffer
+ dirpos
, "\\tst" );
3629 handle2
= CreateFileA(buffer
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
3630 CloseHandle( handle2
);
3631 fdi
.DoDeleteFile
= TRUE
;
3632 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof fdi
, FileDispositionInformation
);
3633 ok( res
== STATUS_DIRECTORY_NOT_EMPTY
, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %lx)\n", res
);
3634 fileDeleted
= DeleteFileA( buffer
);
3635 ok( fileDeleted
, "File should have been deleted\n" );
3636 buffer
[dirpos
] = '\0';
3637 CloseHandle( handle
);
3638 fileDeleted
= GetFileAttributesA( buffer
) == INVALID_FILE_ATTRIBUTES
&& GetLastError() == ERROR_FILE_NOT_FOUND
;
3639 ok( !fileDeleted
, "Directory shouldn't have been deleted\n" );
3640 fileDeleted
= RemoveDirectoryA( buffer
);
3641 ok( fileDeleted
, "Directory should have been deleted\n" );
3643 /* a file with an open mapping handle cannot be deleted */
3645 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3646 handle
= CreateFileA( buffer
, GENERIC_READ
| GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3647 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create file, error %lu\n", GetLastError() );
3648 WriteFile(handle
, "data", 4, &size
, NULL
);
3649 mapping
= CreateFileMappingA( handle
, NULL
, PAGE_READONLY
, 0, 4, NULL
);
3650 ok( !!mapping
, "failed to create mapping, error %lu\n", GetLastError() );
3652 fdi
.DoDeleteFile
= FALSE
;
3653 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3654 ok( !res
, "got %#lx\n", res
);
3656 fdi
.DoDeleteFile
= TRUE
;
3657 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3658 ok( res
== STATUS_CANNOT_DELETE
, "got %#lx\n", res
);
3659 res
= GetFileAttributesA( buffer
);
3660 ok( res
!= INVALID_FILE_ATTRIBUTES
, "expected file to exist\n" );
3662 CloseHandle( mapping
);
3663 CloseHandle( handle
);
3664 res
= DeleteFileA( buffer
);
3665 ok( res
, "got error %lu\n", GetLastError() );
3667 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3668 handle
= CreateFileA( buffer
, GENERIC_READ
| GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3669 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create file, error %lu\n", GetLastError() );
3670 WriteFile(handle
, "data", 4, &size
, NULL
);
3671 mapping
= CreateFileMappingA( handle
, NULL
, PAGE_READONLY
, 0, 4, NULL
);
3672 ok( !!mapping
, "failed to create mapping, error %lu\n", GetLastError() );
3673 CloseHandle( mapping
);
3675 fdi
.DoDeleteFile
= TRUE
;
3676 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3677 ok( !res
, "got %#lx\n", res
);
3679 CloseHandle( handle
);
3680 res
= DeleteFileA( buffer
);
3681 ok( !res
, "expected failure\n" );
3682 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "got error %lu\n", GetLastError() );
3684 /* a file with an open view cannot be deleted */
3686 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3687 handle
= CreateFileA( buffer
, GENERIC_READ
| GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3688 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create file, error %lu\n", GetLastError() );
3689 WriteFile(handle
, "data", 4, &size
, NULL
);
3690 mapping
= CreateFileMappingA( handle
, NULL
, PAGE_READONLY
, 0, 4, NULL
);
3691 ok( !!mapping
, "failed to create mapping, error %lu\n", GetLastError() );
3692 view
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4 );
3693 ok( !!view
, "failed to map view, error %lu\n", GetLastError() );
3694 CloseHandle( mapping
);
3696 fdi
.DoDeleteFile
= FALSE
;
3697 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3698 ok( !res
, "got %#lx\n", res
);
3700 fdi
.DoDeleteFile
= TRUE
;
3701 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3702 ok( res
== STATUS_CANNOT_DELETE
, "got %#lx\n", res
);
3703 res
= GetFileAttributesA( buffer
);
3704 ok( res
!= INVALID_FILE_ATTRIBUTES
, "expected file to exist\n" );
3706 UnmapViewOfFile( view
);
3707 CloseHandle( handle
);
3708 res
= DeleteFileA( buffer
);
3709 ok( res
, "got error %lu\n", GetLastError() );
3711 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3712 handle
= CreateFileA( buffer
, GENERIC_READ
| GENERIC_WRITE
| DELETE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
3713 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create file, error %lu\n", GetLastError() );
3714 WriteFile(handle
, "data", 4, &size
, NULL
);
3715 mapping
= CreateFileMappingA( handle
, NULL
, PAGE_READONLY
, 0, 4, NULL
);
3716 ok( !!mapping
, "failed to create mapping, error %lu\n", GetLastError() );
3717 view
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 4 );
3718 ok( !!view
, "failed to map view, error %lu\n", GetLastError() );
3719 CloseHandle( mapping
);
3720 UnmapViewOfFile( view
);
3722 fdi
.DoDeleteFile
= TRUE
;
3723 res
= pNtSetInformationFile( handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3724 ok( !res
, "got %#lx\n", res
);
3726 CloseHandle( handle
);
3727 res
= DeleteFileA( buffer
);
3728 ok( !res
, "expected failure\n" );
3729 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "got error %lu\n", GetLastError() );
3731 /* pending delete flag is shared across handles */
3732 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3733 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, 0, 0);
3734 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3735 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3736 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3737 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3738 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3739 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3740 res
= NtQueryInformationFile(handle2
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3741 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3742 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3743 fdi
.DoDeleteFile
= TRUE
;
3744 res
= NtSetInformationFile(handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3745 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3746 res
= NtQueryInformationFile(handle2
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3747 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3749 ok(fsi
.DeletePending
, "Handle should be marked for deletion\n");
3750 fdi
.DoDeleteFile
= FALSE
;
3751 res
= NtSetInformationFile(handle2
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3752 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3753 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3754 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3755 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3756 CloseHandle(handle
);
3757 CloseHandle(handle2
);
3758 res
= GetFileAttributesA( buffer
);
3760 ok( res
!= INVALID_FILE_ATTRIBUTES
, "expected file to exist\n" );
3762 /* pending delete flag is shared across handles (even after closing) */
3763 GetTempFileNameA( tmp_path
, "dis", 0, buffer
);
3764 handle
= CreateFileA(buffer
, GENERIC_WRITE
| DELETE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, 0, 0);
3765 ok( handle
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3766 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3767 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3768 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3769 handle2
= CreateFileA(buffer
, DELETE
, FILE_SHARE_DELETE
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0);
3770 ok( handle2
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
3771 res
= NtQueryInformationFile(handle2
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3772 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3773 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3774 fdi
.DoDeleteFile
= TRUE
;
3775 res
= NtSetInformationFile(handle
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3776 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3777 res
= NtQueryInformationFile(handle2
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3778 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3780 ok(fsi
.DeletePending
, "Handle should be marked for deletion\n");
3781 fdi
.DoDeleteFile
= FALSE
;
3782 res
= NtSetInformationFile(handle2
, &io
, &fdi
, sizeof(fdi
), FileDispositionInformation
);
3783 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3784 CloseHandle(handle2
);
3785 res
= NtQueryInformationFile(handle
, &io
, &fsi
, sizeof(fsi
), FileStandardInformation
);
3786 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile failed %lx\n", res
);
3787 ok(!fsi
.DeletePending
, "Handle shouldn't be marked for deletion\n");
3788 CloseHandle(handle
);
3789 res
= GetFileAttributesA( buffer
);
3791 ok( res
!= INVALID_FILE_ATTRIBUTES
, "expected file to exist\n" );
3794 static void test_file_name_information(void)
3796 WCHAR
*file_name
, *volume_prefix
, *expected
;
3797 FILE_NAME_INFORMATION
*info
;
3798 ULONG old_redir
= 1, tmp
;
3799 UINT file_name_size
;
3806 /* GetVolumePathName is not present before w2k */
3807 if (!pGetVolumePathNameW
) {
3808 win_skip("GetVolumePathNameW not found\n");
3812 file_name_size
= GetSystemDirectoryW( NULL
, 0 );
3813 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
3814 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
3815 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
3817 len
= GetSystemDirectoryW( file_name
, file_name_size
);
3818 ok(len
== file_name_size
- 1,
3819 "GetSystemDirectoryW returned %u, expected %u.\n",
3820 len
, file_name_size
- 1);
3822 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
3823 ok(len
, "GetVolumePathNameW failed.\n");
3825 len
= lstrlenW( volume_prefix
);
3826 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
3827 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
3828 expected
[file_name_size
- len
- 1] = '\0';
3830 /* A bit more than we actually need, but it keeps the calculation simple. */
3831 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
3832 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
3834 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( TRUE
, &old_redir
);
3835 h
= CreateFileW( file_name
, GENERIC_READ
,
3836 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
3837 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
3838 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( old_redir
, &tmp
);
3839 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
3841 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
) - 1, FileNameInformation
);
3842 ok(hr
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile returned %#lx.\n", hr
);
3844 memset( info
, 0xcc, info_size
);
3845 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
), FileNameInformation
);
3846 ok(hr
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3847 hr
, STATUS_BUFFER_OVERFLOW
);
3848 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "io.Status is %#lx, expected %#lx.\n",
3849 io
.Status
, STATUS_BUFFER_OVERFLOW
);
3850 ok(info
->FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
), "info->FileNameLength is %lu\n", info
->FileNameLength
);
3851 ok(info
->FileName
[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info
->FileName
[2]);
3852 ok(CharLowerW((LPWSTR
)(UINT_PTR
)info
->FileName
[1]) == CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]),
3853 "info->FileName[1] is %p, expected %p.\n",
3854 CharLowerW((LPWSTR
)(UINT_PTR
)info
->FileName
[1]), CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]));
3855 ok(io
.Information
== sizeof(*info
), "io.Information is %Iu\n", io
.Information
);
3857 memset( info
, 0xcc, info_size
);
3858 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileNameInformation
);
3859 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr
, STATUS_SUCCESS
);
3860 ok(io
.Status
== STATUS_SUCCESS
, "io.Status is %#lx, expected %#lx.\n", io
.Status
, STATUS_SUCCESS
);
3861 ok(info
->FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
), "info->FileNameLength is %lu\n", info
->FileNameLength
);
3862 ok(info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
3863 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)]);
3864 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = '\0';
3865 ok(!lstrcmpiW( info
->FileName
, expected
), "info->FileName is %s, expected %s.\n",
3866 wine_dbgstr_w( info
->FileName
), wine_dbgstr_w( expected
));
3867 ok(io
.Information
== FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + info
->FileNameLength
,
3868 "io.Information is %Iu, expected %lu.\n",
3869 io
.Information
, FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + info
->FileNameLength
);
3872 HeapFree( GetProcessHeap(), 0, info
);
3873 HeapFree( GetProcessHeap(), 0, expected
);
3874 HeapFree( GetProcessHeap(), 0, volume_prefix
);
3876 if (old_redir
|| !pGetSystemWow64DirectoryW
|| !(file_name_size
= pGetSystemWow64DirectoryW( NULL
, 0 )))
3878 skip("Not running on WoW64, skipping test.\n");
3879 HeapFree( GetProcessHeap(), 0, file_name
);
3883 h
= CreateFileW( file_name
, GENERIC_READ
,
3884 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
3885 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
3886 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
3887 HeapFree( GetProcessHeap(), 0, file_name
);
3889 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
3890 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
3891 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*expected
) );
3893 len
= pGetSystemWow64DirectoryW( file_name
, file_name_size
);
3894 ok(len
== file_name_size
- 1,
3895 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3896 len
, file_name_size
- 1);
3898 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
3899 ok(len
, "GetVolumePathNameW failed.\n");
3901 len
= lstrlenW( volume_prefix
);
3902 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
3903 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
3904 expected
[file_name_size
- len
- 1] = '\0';
3906 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
3907 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
3909 memset( info
, 0xcc, info_size
);
3910 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileNameInformation
);
3911 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr
, STATUS_SUCCESS
);
3912 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = '\0';
3913 ok(!lstrcmpiW( info
->FileName
, expected
), "info->FileName is %s, expected %s.\n",
3914 wine_dbgstr_w( info
->FileName
), wine_dbgstr_w( expected
));
3917 HeapFree( GetProcessHeap(), 0, info
);
3918 HeapFree( GetProcessHeap(), 0, expected
);
3919 HeapFree( GetProcessHeap(), 0, volume_prefix
);
3920 HeapFree( GetProcessHeap(), 0, file_name
);
3923 static void test_file_all_name_information(void)
3925 WCHAR
*file_name
, *volume_prefix
, *expected
;
3926 FILE_ALL_INFORMATION
*info
;
3927 ULONG old_redir
= 1, tmp
;
3928 UINT file_name_size
;
3935 /* GetVolumePathName is not present before w2k */
3936 if (!pGetVolumePathNameW
) {
3937 win_skip("GetVolumePathNameW not found\n");
3941 file_name_size
= GetSystemDirectoryW( NULL
, 0 );
3942 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
3943 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
3944 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
3946 len
= GetSystemDirectoryW( file_name
, file_name_size
);
3947 ok(len
== file_name_size
- 1,
3948 "GetSystemDirectoryW returned %u, expected %u.\n",
3949 len
, file_name_size
- 1);
3951 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
3952 ok(len
, "GetVolumePathNameW failed.\n");
3954 len
= lstrlenW( volume_prefix
);
3955 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
3956 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
3957 expected
[file_name_size
- len
- 1] = '\0';
3959 /* A bit more than we actually need, but it keeps the calculation simple. */
3960 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
3961 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
3963 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( TRUE
, &old_redir
);
3964 h
= CreateFileW( file_name
, GENERIC_READ
,
3965 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
3966 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
3967 if (pRtlWow64EnableFsRedirectionEx
) pRtlWow64EnableFsRedirectionEx( old_redir
, &tmp
);
3968 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
3970 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
) - 1, FileAllInformation
);
3971 ok(hr
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3972 hr
, STATUS_INFO_LENGTH_MISMATCH
);
3974 memset( info
, 0xcc, info_size
);
3975 hr
= pNtQueryInformationFile( h
, &io
, info
, sizeof(*info
), FileAllInformation
);
3976 ok(hr
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile returned %#lx, expected %#lx.\n",
3977 hr
, STATUS_BUFFER_OVERFLOW
);
3978 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "io.Status is %#lx, expected %#lx.\n",
3979 io
.Status
, STATUS_BUFFER_OVERFLOW
);
3980 ok(info
->NameInformation
.FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
),
3981 "info->NameInformation.FileNameLength is %lu\n", info
->NameInformation
.FileNameLength
);
3982 ok(info
->NameInformation
.FileName
[2] == 0xcccc,
3983 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info
->NameInformation
.FileName
[2]);
3984 ok(CharLowerW((LPWSTR
)(UINT_PTR
)info
->NameInformation
.FileName
[1]) == CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]),
3985 "info->NameInformation.FileName[1] is %p, expected %p.\n",
3986 CharLowerW((LPWSTR
)(UINT_PTR
)info
->NameInformation
.FileName
[1]), CharLowerW((LPWSTR
)(UINT_PTR
)expected
[1]));
3987 ok(io
.Information
== sizeof(*info
), "io.Information is %Iu\n", io
.Information
);
3989 memset( info
, 0xcc, info_size
);
3990 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileAllInformation
);
3991 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr
, STATUS_SUCCESS
);
3992 ok(io
.Status
== STATUS_SUCCESS
, "io.Status is %#lx, expected %#lx.\n", io
.Status
, STATUS_SUCCESS
);
3993 ok(info
->NameInformation
.FileNameLength
== lstrlenW( expected
) * sizeof(WCHAR
),
3994 "info->NameInformation.FileNameLength is %lu\n", info
->NameInformation
.FileNameLength
);
3995 ok(info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] == 0xcccc,
3996 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3997 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)]);
3998 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] = '\0';
3999 ok(!lstrcmpiW( info
->NameInformation
.FileName
, expected
),
4000 "info->NameInformation.FileName is %s, expected %s.\n",
4001 wine_dbgstr_w( info
->NameInformation
.FileName
), wine_dbgstr_w( expected
));
4002 ok(io
.Information
== FIELD_OFFSET(FILE_ALL_INFORMATION
, NameInformation
.FileName
)
4003 + info
->NameInformation
.FileNameLength
,
4004 "io.Information is %Iu\n", io
.Information
);
4007 HeapFree( GetProcessHeap(), 0, info
);
4008 HeapFree( GetProcessHeap(), 0, expected
);
4009 HeapFree( GetProcessHeap(), 0, volume_prefix
);
4011 if (old_redir
|| !pGetSystemWow64DirectoryW
|| !(file_name_size
= pGetSystemWow64DirectoryW( NULL
, 0 )))
4013 skip("Not running on WoW64, skipping test.\n");
4014 HeapFree( GetProcessHeap(), 0, file_name
);
4018 h
= CreateFileW( file_name
, GENERIC_READ
,
4019 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
4020 NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 );
4021 ok(h
!= INVALID_HANDLE_VALUE
, "Failed to open file.\n");
4022 HeapFree( GetProcessHeap(), 0, file_name
);
4024 file_name
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*file_name
) );
4025 volume_prefix
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*volume_prefix
) );
4026 expected
= HeapAlloc( GetProcessHeap(), 0, file_name_size
* sizeof(*expected
) );
4028 len
= pGetSystemWow64DirectoryW( file_name
, file_name_size
);
4029 ok(len
== file_name_size
- 1,
4030 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
4031 len
, file_name_size
- 1);
4033 len
= pGetVolumePathNameW( file_name
, volume_prefix
, file_name_size
);
4034 ok(len
, "GetVolumePathNameW failed.\n");
4036 len
= lstrlenW( volume_prefix
);
4037 if (len
&& volume_prefix
[len
- 1] == '\\') --len
;
4038 memcpy( expected
, file_name
+ len
, (file_name_size
- len
- 1) * sizeof(WCHAR
) );
4039 expected
[file_name_size
- len
- 1] = '\0';
4041 info_size
= sizeof(*info
) + (file_name_size
* sizeof(WCHAR
));
4042 info
= HeapAlloc( GetProcessHeap(), 0, info_size
);
4044 memset( info
, 0xcc, info_size
);
4045 hr
= pNtQueryInformationFile( h
, &io
, info
, info_size
, FileAllInformation
);
4046 ok(hr
== STATUS_SUCCESS
, "NtQueryInformationFile returned %#lx, expected %#lx.\n", hr
, STATUS_SUCCESS
);
4047 info
->NameInformation
.FileName
[info
->NameInformation
.FileNameLength
/ sizeof(WCHAR
)] = '\0';
4048 ok(!lstrcmpiW( info
->NameInformation
.FileName
, expected
), "info->NameInformation.FileName is %s, expected %s.\n",
4049 wine_dbgstr_w( info
->NameInformation
.FileName
), wine_dbgstr_w( expected
));
4052 HeapFree( GetProcessHeap(), 0, info
);
4053 HeapFree( GetProcessHeap(), 0, expected
);
4054 HeapFree( GetProcessHeap(), 0, volume_prefix
);
4055 HeapFree( GetProcessHeap(), 0, file_name
);
4058 #define test_completion_flags(a,b) _test_completion_flags(__LINE__,a,b)
4059 static void _test_completion_flags(unsigned line
, HANDLE handle
, DWORD expected_flags
)
4061 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
4065 info
.Flags
= 0xdeadbeef;
4066 status
= pNtQueryInformationFile(handle
, &io
, &info
, sizeof(info
),
4067 FileIoCompletionNotificationInformation
);
4068 ok_(__FILE__
,line
)(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4069 ok_(__FILE__
,line
)(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
4070 ok_(__FILE__
,line
)(io
.Information
== sizeof(info
), "Information = %Iu\n", io
.Information
);
4071 /* FILE_SKIP_SET_USER_EVENT_ON_FAST_IO is not supported on win2k3 */
4072 ok_(__FILE__
,line
)((info
.Flags
& ~FILE_SKIP_SET_USER_EVENT_ON_FAST_IO
) == expected_flags
,
4073 "got %08lx\n", info
.Flags
);
4076 static void test_file_completion_information(void)
4078 DECLSPEC_ALIGN(TEST_OVERLAPPED_READ_SIZE
) static unsigned char aligned_buf
[TEST_OVERLAPPED_READ_SIZE
];
4079 static const char buf
[] = "testdata";
4080 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
4081 OVERLAPPED ov
, *pov
;
4090 if (!(h
= create_temp_file(0))) return;
4092 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
) - 1, FileIoCompletionNotificationInformation
);
4093 ok(status
== STATUS_INFO_LENGTH_MISMATCH
|| broken(status
== STATUS_INVALID_INFO_CLASS
/* XP */),
4094 "expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status
);
4095 if (status
!= STATUS_INFO_LENGTH_MISMATCH
)
4097 win_skip("FileIoCompletionNotificationInformation class not supported\n");
4102 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
4103 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4104 ok(status
== STATUS_INVALID_PARAMETER
, "expected STATUS_INVALID_PARAMETER, got %08lx\n", status
);
4107 if (!(h
= create_temp_file(FILE_FLAG_OVERLAPPED
))) return;
4109 info
.Flags
= FILE_SKIP_SET_EVENT_ON_HANDLE
;
4110 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4111 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4112 test_completion_flags(h
, FILE_SKIP_SET_EVENT_ON_HANDLE
);
4114 info
.Flags
= FILE_SKIP_SET_USER_EVENT_ON_FAST_IO
;
4115 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4116 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4117 test_completion_flags(h
, FILE_SKIP_SET_EVENT_ON_HANDLE
);
4120 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4121 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4122 test_completion_flags(h
, FILE_SKIP_SET_EVENT_ON_HANDLE
);
4124 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
4125 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4126 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4127 test_completion_flags(h
, FILE_SKIP_SET_EVENT_ON_HANDLE
| FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
);
4129 info
.Flags
= 0xdeadbeef;
4130 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4131 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4132 test_completion_flags(h
, FILE_SKIP_SET_EVENT_ON_HANDLE
| FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
);
4135 if (!(h
= create_temp_file(FILE_FLAG_OVERLAPPED
))) return;
4136 test_completion_flags(h
, 0);
4138 memset(&ov
, 0, sizeof(ov
));
4139 ov
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
4140 port
= CreateIoCompletionPort(h
, NULL
, 0xdeadbeef, 0);
4141 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %lu\n", GetLastError());
4143 for (i
= 0; i
< 10; i
++)
4145 SetLastError(0xdeadbeef);
4146 ret
= WriteFile(h
, buf
, sizeof(buf
), &num_bytes
, &ov
);
4147 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* Before Vista */,
4148 "Unexpected result %#x, GetLastError() %lu.\n", ret
, GetLastError());
4149 if (ret
|| GetLastError() != ERROR_IO_PENDING
) break;
4150 ret
= GetOverlappedResult(h
, &ov
, &num_bytes
, TRUE
);
4151 ok(ret
, "GetOverlappedResult failed, error %lu\n", GetLastError());
4152 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
4153 ok(ret
, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
4158 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %lu\n", num_bytes
);
4162 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
4163 ok(ret
, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
4164 ok(key
== 0xdeadbeef, "expected 0xdeadbeef, got %Ix\n", key
);
4165 ok(pov
== &ov
, "expected %p, got %p\n", &ov
, pov
);
4168 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
4169 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4170 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4171 test_completion_flags(h
, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
);
4173 for (i
= 0; i
< 10; i
++)
4175 SetLastError(0xdeadbeef);
4176 ret
= WriteFile(h
, buf
, sizeof(buf
), &num_bytes
, &ov
);
4177 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* Before Vista */,
4178 "Unexpected result %#x, GetLastError() %lu.\n", ret
, GetLastError());
4179 if (ret
|| GetLastError() != ERROR_IO_PENDING
) break;
4180 ret
= GetOverlappedResult(h
, &ov
, &num_bytes
, TRUE
);
4181 ok(ret
, "GetOverlappedResult failed, error %lu\n", GetLastError());
4186 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %lu\n", num_bytes
);
4188 pov
= (void *)0xdeadbeef;
4189 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 500);
4190 ok(!ret
, "GetQueuedCompletionStatus succeeded\n");
4191 ok(pov
== NULL
, "expected NULL, got %p\n", pov
);
4195 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4196 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4197 test_completion_flags(h
, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
);
4199 for (i
= 0; i
< 10; i
++)
4201 SetLastError(0xdeadbeef);
4202 ret
= WriteFile(h
, buf
, sizeof(buf
), &num_bytes
, &ov
);
4203 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* Before Vista */,
4204 "Unexpected result %#x, GetLastError() %lu.\n", ret
, GetLastError());
4205 if (ret
|| GetLastError() != ERROR_IO_PENDING
) break;
4206 ret
= GetOverlappedResult(h
, &ov
, &num_bytes
, TRUE
);
4207 ok(ret
, "GetOverlappedResult failed, error %lu\n", GetLastError());
4208 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
4209 ok(ret
, "GetQueuedCompletionStatus failed, error %lu\n", GetLastError());
4214 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %lu\n", num_bytes
);
4216 pov
= (void *)0xdeadbeef;
4217 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
4218 ok(!ret
, "GetQueuedCompletionStatus succeeded\n");
4219 ok(pov
== NULL
, "expected NULL, got %p\n", pov
);
4225 if (!(h
= create_temp_file(FILE_FLAG_OVERLAPPED
| FILE_FLAG_NO_BUFFERING
)))
4228 port
= CreateIoCompletionPort(h
, NULL
, 0xdeadbeef, 0);
4229 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %lu.\n", GetLastError());
4231 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
4232 status
= pNtSetInformationFile(h
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
4233 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %#lx.\n", status
);
4234 test_completion_flags(h
, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
);
4236 ret
= WriteFile(h
, aligned_buf
, sizeof(aligned_buf
), &num_bytes
, &ov
);
4237 if (!ret
&& GetLastError() == ERROR_IO_PENDING
)
4239 ret
= GetOverlappedResult(h
, &ov
, &num_bytes
, TRUE
);
4240 ok(ret
, "GetOverlappedResult failed, error %lu.\n", GetLastError());
4241 ok(num_bytes
== sizeof(aligned_buf
), "expected sizeof(aligned_buf), got %lu.\n", num_bytes
);
4242 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
4243 ok(ret
, "GetQueuedCompletionStatus failed, error %lu.\n", GetLastError());
4245 ok(num_bytes
== sizeof(aligned_buf
), "expected sizeof(buf), got %lu.\n", num_bytes
);
4247 SetLastError(0xdeadbeef);
4248 ret
= ReadFile(h
, aligned_buf
, sizeof(aligned_buf
), &num_bytes
, &ov
);
4249 ok(!ret
&& GetLastError() == ERROR_IO_PENDING
, "Unexpected result, ret %#x, error %lu.\n",
4250 ret
, GetLastError());
4251 ret
= GetOverlappedResult(h
, &ov
, &num_bytes
, TRUE
);
4252 ok(ret
, "GetOverlappedResult failed, error %lu.\n", GetLastError());
4253 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
4254 ok(ret
, "GetQueuedCompletionStatus failed, error %lu.\n", GetLastError());
4256 CloseHandle(ov
.hEvent
);
4261 static void test_file_id_information(void)
4263 BY_HANDLE_FILE_INFORMATION info
;
4264 FILE_ID_INFORMATION fid
;
4271 if (!(h
= create_temp_file(0))) return;
4273 memset( &fid
, 0x11, sizeof(fid
) );
4274 status
= pNtQueryInformationFile( h
, &io
, &fid
, sizeof(fid
), FileIdInformation
);
4275 if (status
== STATUS_NOT_IMPLEMENTED
|| status
== STATUS_INVALID_INFO_CLASS
)
4277 win_skip( "FileIdInformation not supported\n" );
4282 memset( &info
, 0x22, sizeof(info
) );
4283 ret
= GetFileInformationByHandle( h
, &info
);
4284 ok( ret
, "GetFileInformationByHandle failed\n" );
4286 dwords
= (DWORD
*)&fid
.VolumeSerialNumber
;
4287 ok( dwords
[0] == info
.dwVolumeSerialNumber
, "expected %08lx, got %08lx\n",
4288 info
.dwVolumeSerialNumber
, dwords
[0] );
4289 ok( dwords
[1] != 0x11111111, "expected != 0x11111111\n" );
4291 dwords
= (DWORD
*)&fid
.FileId
;
4292 ok( dwords
[0] == info
.nFileIndexLow
, "expected %08lx, got %08lx\n", info
.nFileIndexLow
, dwords
[0] );
4293 ok( dwords
[1] == info
.nFileIndexHigh
, "expected %08lx, got %08lx\n", info
.nFileIndexHigh
, dwords
[1] );
4294 ok( dwords
[2] == 0, "expected 0, got %08lx\n", dwords
[2] );
4295 ok( dwords
[3] == 0, "expected 0, got %08lx\n", dwords
[3] );
4300 static void test_file_access_information(void)
4302 FILE_ACCESS_INFORMATION info
;
4307 if (!(h
= create_temp_file(0))) return;
4309 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
) - 1, FileAccessInformation
);
4310 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status
);
4312 status
= pNtQueryInformationFile( (HANDLE
)0xdeadbeef, &io
, &info
, sizeof(info
), FileAccessInformation
);
4313 ok( status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08lx\n", status
);
4315 memset(&info
, 0x11, sizeof(info
));
4316 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileAccessInformation
);
4317 ok( status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
4318 ok( info
.AccessFlags
== 0x13019f, "got %08lx\n", info
.AccessFlags
);
4323 static void test_file_attribute_tag_information(void)
4325 FILE_ATTRIBUTE_TAG_INFORMATION info
;
4326 FILE_BASIC_INFORMATION fbi
= {};
4331 if (!(h
= create_temp_file(0))) return;
4333 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
) - 1, FileAttributeTagInformation
);
4334 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "got %#lx\n", status
);
4336 status
= pNtQueryInformationFile( (HANDLE
)0xdeadbeef, &io
, &info
, sizeof(info
), FileAttributeTagInformation
);
4337 ok( status
== STATUS_INVALID_HANDLE
, "got %#lx\n", status
);
4339 memset(&info
, 0x11, sizeof(info
));
4340 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileAttributeTagInformation
);
4341 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4342 info
.FileAttributes
&= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
;
4343 ok( info
.FileAttributes
== FILE_ATTRIBUTE_ARCHIVE
, "got attributes %#lx\n", info
.FileAttributes
);
4344 ok( !info
.ReparseTag
, "got reparse tag %#lx\n", info
.ReparseTag
);
4346 fbi
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
4347 status
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof(fbi
), FileBasicInformation
);
4348 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4350 memset(&info
, 0x11, sizeof(info
));
4351 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileAttributeTagInformation
);
4352 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4353 todo_wine
ok( info
.FileAttributes
== FILE_ATTRIBUTE_SYSTEM
, "got attributes %#lx\n", info
.FileAttributes
);
4354 ok( !info
.ReparseTag
, "got reparse tag %#lx\n", info
.ReparseTag
);
4356 fbi
.FileAttributes
= FILE_ATTRIBUTE_HIDDEN
;
4357 status
= pNtSetInformationFile(h
, &io
, &fbi
, sizeof fbi
, FileBasicInformation
);
4358 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4360 memset(&info
, 0x11, sizeof(info
));
4361 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileAttributeTagInformation
);
4362 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4363 todo_wine
ok( info
.FileAttributes
== FILE_ATTRIBUTE_HIDDEN
, "got attributes %#lx\n", info
.FileAttributes
);
4364 ok( !info
.ReparseTag
, "got reparse tag %#lx\n", info
.ReparseTag
);
4369 static void test_file_stat_information(void)
4371 BY_HANDLE_FILE_INFORMATION info
;
4372 FILE_STAT_INFORMATION fsd
;
4378 if (!(h
= create_temp_file(0))) return;
4380 memset( &fsd
, 0x11, sizeof(fsd
) );
4381 status
= pNtQueryInformationFile( h
, &io
, &fsd
, sizeof(fsd
), FileStatInformation
);
4382 if (status
== STATUS_NOT_IMPLEMENTED
|| status
== STATUS_INVALID_INFO_CLASS
)
4384 win_skip( "FileStatInformation not supported\n" );
4388 ok( status
== STATUS_SUCCESS
, "query FileStatInformation returned %#lx\n", status
);
4390 memset( &info
, 0x22, sizeof(info
) );
4391 ret
= GetFileInformationByHandle( h
, &info
);
4392 ok( ret
, "GetFileInformationByHandle failed\n" );
4394 ok( fsd
.FileId
.u
.LowPart
== info
.nFileIndexLow
, "expected %08lx, got %08lx\n", info
.nFileIndexLow
, fsd
.FileId
.u
.LowPart
);
4395 ok( fsd
.FileId
.u
.HighPart
== info
.nFileIndexHigh
, "expected %08lx, got %08lx\n", info
.nFileIndexHigh
, fsd
.FileId
.u
.HighPart
);
4396 ok( fsd
.CreationTime
.u
.LowPart
== info
.ftCreationTime
.dwLowDateTime
, "expected %08lx, got %08lx\n",
4397 info
.ftCreationTime
.dwLowDateTime
, fsd
.CreationTime
.u
.LowPart
);
4398 ok( fsd
.CreationTime
.u
.HighPart
== info
.ftCreationTime
.dwHighDateTime
, "expected %08lx, got %08lx\n",
4399 info
.ftCreationTime
.dwHighDateTime
, fsd
.CreationTime
.u
.HighPart
);
4400 ok( fsd
.LastAccessTime
.u
.LowPart
== info
.ftLastAccessTime
.dwLowDateTime
, "expected %08lx, got %08lx\n",
4401 info
.ftLastAccessTime
.dwLowDateTime
, fsd
.LastAccessTime
.u
.LowPart
);
4402 ok( fsd
.LastAccessTime
.u
.HighPart
== info
.ftLastAccessTime
.dwHighDateTime
, "expected %08lx, got %08lx\n",
4403 info
.ftLastAccessTime
.dwHighDateTime
, fsd
.LastAccessTime
.u
.HighPart
);
4404 ok( fsd
.LastWriteTime
.u
.LowPart
== info
.ftLastWriteTime
.dwLowDateTime
, "expected %08lx, got %08lx\n",
4405 info
.ftLastWriteTime
.dwLowDateTime
, fsd
.LastWriteTime
.u
.LowPart
);
4406 ok( fsd
.LastWriteTime
.u
.HighPart
== info
.ftLastWriteTime
.dwHighDateTime
, "expected %08lx, got %08lx\n",
4407 info
.ftLastWriteTime
.dwHighDateTime
, fsd
.LastWriteTime
.u
.HighPart
);
4408 /* TODO: ChangeTime */
4409 /* TODO: AllocationSize */
4410 ok( fsd
.EndOfFile
.u
.LowPart
== info
.nFileSizeLow
, "expected %08lx, got %08lx\n", info
.nFileSizeLow
, fsd
.EndOfFile
.u
.LowPart
);
4411 ok( fsd
.EndOfFile
.u
.HighPart
== info
.nFileSizeHigh
, "expected %08lx, got %08lx\n", info
.nFileSizeHigh
, fsd
.EndOfFile
.u
.HighPart
);
4412 ok( fsd
.FileAttributes
== info
.dwFileAttributes
, "expected %08lx, got %08lx\n", info
.dwFileAttributes
, fsd
.FileAttributes
);
4413 ok( !fsd
.ReparseTag
, "got reparse tag %#lx\n", fsd
.ReparseTag
);
4414 ok( fsd
.NumberOfLinks
== info
.nNumberOfLinks
, "expected %08lx, got %08lx\n", info
.nNumberOfLinks
, fsd
.NumberOfLinks
);
4415 ok( fsd
.EffectiveAccess
== FILE_ALL_ACCESS
, "got %08lx\n", fsd
.EffectiveAccess
);
4420 static void rename_file( HANDLE h
, const WCHAR
*filename
)
4422 FILE_RENAME_INFORMATION
*fri
;
4423 UNICODE_STRING ntpath
;
4429 ret
= pRtlDosPathNameToNtPathName_U( filename
, &ntpath
, NULL
, NULL
);
4430 ok( ret
, "RtlDosPathNameToNtPathName_U failed\n" );
4432 size
= offsetof( FILE_RENAME_INFORMATION
, FileName
) + ntpath
.Length
;
4433 fri
= HeapAlloc( GetProcessHeap(), 0, size
);
4434 ok( fri
!= NULL
, "HeapAlloc failed\n" );
4435 fri
->ReplaceIfExists
= TRUE
;
4436 fri
->RootDirectory
= NULL
;
4437 fri
->FileNameLength
= ntpath
.Length
;
4438 memcpy( fri
->FileName
, ntpath
.Buffer
, ntpath
.Length
);
4439 pRtlFreeUnicodeString( &ntpath
);
4441 status
= pNtSetInformationFile( h
, &io
, fri
, size
, FileRenameInformation
);
4442 HeapFree( GetProcessHeap(), 0, fri
);
4443 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4446 static void test_dotfile_file_attributes(void)
4448 char temppath
[MAX_PATH
], filename
[MAX_PATH
];
4449 WCHAR temppathW
[MAX_PATH
], filenameW
[MAX_PATH
];
4450 FILE_BASIC_INFORMATION info
= {};
4456 GetTempPathA( MAX_PATH
, temppath
);
4457 GetTempFileNameA( temppath
, ".foo", 0, filename
);
4458 h
= CreateFileA( filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0 );
4459 ok( h
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
4461 status
= nt_get_file_attrs(filename
, &attrs
);
4462 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4463 ok( !(attrs
& FILE_ATTRIBUTE_HIDDEN
), "got attributes %#lx\n", attrs
);
4465 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileBasicInformation
);
4466 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4467 ok( !(info
.FileAttributes
& FILE_ATTRIBUTE_HIDDEN
), "got attributes %#lx\n", info
.FileAttributes
);
4469 info
.FileAttributes
= FILE_ATTRIBUTE_SYSTEM
;
4470 status
= pNtSetInformationFile( h
, &io
, &info
, sizeof(info
), FileBasicInformation
);
4471 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4473 status
= nt_get_file_attrs(filename
, &attrs
);
4474 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4475 ok( attrs
& FILE_ATTRIBUTE_SYSTEM
, "got attributes %#lx\n", attrs
);
4476 ok( !(attrs
& FILE_ATTRIBUTE_HIDDEN
), "got attributes %#lx\n", attrs
);
4478 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileBasicInformation
);
4479 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4480 ok( info
.FileAttributes
& FILE_ATTRIBUTE_SYSTEM
, "got attributes %#lx\n", info
.FileAttributes
);
4481 ok( !(info
.FileAttributes
& FILE_ATTRIBUTE_HIDDEN
), "got attributes %#lx\n", info
.FileAttributes
);
4485 GetTempPathW( MAX_PATH
, temppathW
);
4486 GetTempFileNameW( temppathW
, L
"foo", 0, filenameW
);
4487 h
= CreateFileW( filenameW
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_FLAG_DELETE_ON_CLOSE
, 0 );
4488 ok( h
!= INVALID_HANDLE_VALUE
, "failed to create temp file\n" );
4490 GetTempFileNameW( temppathW
, L
".foo", 0, filenameW
);
4491 winetest_push_context("foo -> .foo");
4492 rename_file( h
, filenameW
);
4493 winetest_pop_context();
4495 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileBasicInformation
);
4496 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4497 ok( !(info
.FileAttributes
& FILE_ATTRIBUTE_HIDDEN
), "got attributes %#lx\n", info
.FileAttributes
);
4499 GetTempFileNameW( temppathW
, L
"foo", 0, filenameW
);
4500 winetest_push_context(".foo -> foo");
4501 rename_file( h
, filenameW
);
4502 winetest_pop_context();
4504 status
= pNtQueryInformationFile( h
, &io
, &info
, sizeof(info
), FileBasicInformation
);
4505 ok( status
== STATUS_SUCCESS
, "got %#lx\n", status
);
4506 ok( !(info
.FileAttributes
& FILE_ATTRIBUTE_HIDDEN
), "got attributes %#lx\n", info
.FileAttributes
);
4511 static void test_file_mode(void)
4513 UNICODE_STRING file_name
, pipe_dev_name
, mountmgr_dev_name
, mailslot_dev_name
;
4514 WCHAR tmp_path
[MAX_PATH
], dos_file_name
[MAX_PATH
];
4515 FILE_MODE_INFORMATION mode
;
4516 OBJECT_ATTRIBUTES attr
;
4524 UNICODE_STRING
*file_name
;
4527 } option_tests
[] = {
4528 { &file_name
, 0, 0 },
4529 { &file_name
, FILE_NON_DIRECTORY_FILE
, 0 },
4530 { &file_name
, FILE_NON_DIRECTORY_FILE
| FILE_SEQUENTIAL_ONLY
, FILE_SEQUENTIAL_ONLY
},
4531 { &file_name
, FILE_WRITE_THROUGH
, FILE_WRITE_THROUGH
},
4532 { &file_name
, FILE_SYNCHRONOUS_IO_ALERT
, FILE_SYNCHRONOUS_IO_ALERT
},
4533 { &file_name
, FILE_NO_INTERMEDIATE_BUFFERING
, FILE_NO_INTERMEDIATE_BUFFERING
},
4534 { &file_name
, FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
, FILE_SYNCHRONOUS_IO_NONALERT
},
4535 { &file_name
, FILE_DELETE_ON_CLOSE
, 0 },
4536 { &file_name
, FILE_RANDOM_ACCESS
| FILE_NO_COMPRESSION
, 0 },
4537 { &pipe_dev_name
, 0, 0 },
4538 { &pipe_dev_name
, FILE_SYNCHRONOUS_IO_ALERT
, FILE_SYNCHRONOUS_IO_ALERT
},
4539 { &mailslot_dev_name
, 0, 0 },
4540 { &mailslot_dev_name
, FILE_SYNCHRONOUS_IO_ALERT
, FILE_SYNCHRONOUS_IO_ALERT
},
4541 { &mountmgr_dev_name
, 0, 0 },
4542 { &mountmgr_dev_name
, FILE_SYNCHRONOUS_IO_ALERT
, FILE_SYNCHRONOUS_IO_ALERT
}
4545 static WCHAR pipe_devW
[] = {'\\','?','?','\\','P','I','P','E','\\'};
4546 static WCHAR mailslot_devW
[] = {'\\','?','?','\\','M','A','I','L','S','L','O','T','\\'};
4547 static WCHAR mountmgr_devW
[] =
4548 {'\\','?','?','\\','M','o','u','n','t','P','o','i','n','t','M','a','n','a','g','e','r'};
4550 GetTempPathW(MAX_PATH
, tmp_path
);
4551 res
= GetTempFileNameW(tmp_path
, fooW
, 0, dos_file_name
);
4552 ok(res
, "GetTempFileNameW failed: %lu\n", GetLastError());
4553 pRtlDosPathNameToNtPathName_U( dos_file_name
, &file_name
, NULL
, NULL
);
4555 pipe_dev_name
.Buffer
= pipe_devW
;
4556 pipe_dev_name
.Length
= sizeof(pipe_devW
);
4557 pipe_dev_name
.MaximumLength
= sizeof(pipe_devW
);
4559 mailslot_dev_name
.Buffer
= mailslot_devW
;
4560 mailslot_dev_name
.Length
= sizeof(mailslot_devW
);
4561 mailslot_dev_name
.MaximumLength
= sizeof(mailslot_devW
);
4563 mountmgr_dev_name
.Buffer
= mountmgr_devW
;
4564 mountmgr_dev_name
.Length
= sizeof(mountmgr_devW
);
4565 mountmgr_dev_name
.MaximumLength
= sizeof(mountmgr_devW
);
4567 attr
.Length
= sizeof(attr
);
4568 attr
.RootDirectory
= 0;
4569 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
4570 attr
.SecurityDescriptor
= NULL
;
4571 attr
.SecurityQualityOfService
= NULL
;
4573 for (i
= 0; i
< ARRAY_SIZE(option_tests
); i
++)
4575 attr
.ObjectName
= option_tests
[i
].file_name
;
4576 access
= SYNCHRONIZE
;
4578 if (option_tests
[i
].file_name
== &file_name
)
4580 file
= CreateFileW(dos_file_name
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
4581 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError());
4583 access
|= GENERIC_WRITE
| DELETE
;
4586 status
= pNtOpenFile(&file
, access
, &attr
, &io
, 0, option_tests
[i
].options
);
4587 ok(status
== STATUS_SUCCESS
, "[%u] NtOpenFile failed: %lx\n", i
, status
);
4589 memset(&mode
, 0xcc, sizeof(mode
));
4590 status
= pNtQueryInformationFile(file
, &io
, &mode
, sizeof(mode
), FileModeInformation
);
4591 ok(status
== STATUS_SUCCESS
, "[%u] can't get FileModeInformation: %lx\n", i
, status
);
4592 ok(mode
.Mode
== option_tests
[i
].mode
, "[%u] Mode = %lx, expected %lx\n",
4593 i
, mode
.Mode
, option_tests
[i
].mode
);
4596 if (option_tests
[i
].file_name
== &file_name
)
4597 DeleteFileW(dos_file_name
);
4600 pRtlFreeUnicodeString(&file_name
);
4603 static void test_query_volume_information_file(void)
4607 WCHAR path
[MAX_PATH
];
4608 OBJECT_ATTRIBUTES attr
;
4610 UNICODE_STRING nameW
;
4611 FILE_FS_VOLUME_INFORMATION
*ffvi
;
4612 BYTE buf
[sizeof(FILE_FS_VOLUME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
4614 GetWindowsDirectoryW( path
, MAX_PATH
);
4615 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
4616 attr
.Length
= sizeof(attr
);
4617 attr
.RootDirectory
= 0;
4618 attr
.ObjectName
= &nameW
;
4619 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
4620 attr
.SecurityDescriptor
= NULL
;
4621 attr
.SecurityQualityOfService
= NULL
;
4623 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
4624 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
4625 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
4626 pRtlFreeUnicodeString( &nameW
);
4628 ZeroMemory( buf
, sizeof(buf
) );
4629 io
.Status
= 0xdadadada;
4630 io
.Information
= 0xcacacaca;
4632 status
= pNtQueryVolumeInformationFile( dir
, &io
, buf
, sizeof(buf
), FileFsVolumeInformation
);
4634 ffvi
= (FILE_FS_VOLUME_INFORMATION
*)buf
;
4636 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %ld\n", status
);
4637 ok(io
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %ld\n", io
.Status
);
4639 ok(io
.Information
== (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + ffvi
->VolumeLabelLength
),
4640 "expected %ld, got %Iu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + ffvi
->VolumeLabelLength
),
4643 todo_wine
ok(ffvi
->VolumeCreationTime
.QuadPart
!= 0, "Missing VolumeCreationTime\n");
4644 ok(ffvi
->VolumeSerialNumber
!= 0, "Missing VolumeSerialNumber\n");
4645 ok(ffvi
->SupportsObjects
== 1,"expected 1, got %d\n", ffvi
->SupportsObjects
);
4646 ok(ffvi
->VolumeLabelLength
== lstrlenW(ffvi
->VolumeLabel
) * sizeof(WCHAR
), "got %ld\n", ffvi
->VolumeLabelLength
);
4648 trace("VolumeSerialNumber: %lx VolumeLabelName: %s\n", ffvi
->VolumeSerialNumber
, wine_dbgstr_w(ffvi
->VolumeLabel
));
4653 static void test_query_attribute_information_file(void)
4657 WCHAR path
[MAX_PATH
];
4658 OBJECT_ATTRIBUTES attr
;
4660 UNICODE_STRING nameW
;
4661 FILE_FS_ATTRIBUTE_INFORMATION
*ffai
;
4662 BYTE buf
[sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
4664 GetWindowsDirectoryW( path
, MAX_PATH
);
4665 pRtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
);
4666 attr
.Length
= sizeof(attr
);
4667 attr
.RootDirectory
= 0;
4668 attr
.ObjectName
= &nameW
;
4669 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
4670 attr
.SecurityDescriptor
= NULL
;
4671 attr
.SecurityQualityOfService
= NULL
;
4673 status
= pNtOpenFile( &dir
, SYNCHRONIZE
|FILE_LIST_DIRECTORY
, &attr
, &io
,
4674 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
4675 ok( !status
, "open %s failed %lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
4676 pRtlFreeUnicodeString( &nameW
);
4678 ZeroMemory( buf
, sizeof(buf
) );
4679 io
.Status
= 0xdadadada;
4680 io
.Information
= 0xcacacaca;
4682 status
= pNtQueryVolumeInformationFile( dir
, &io
, buf
, sizeof(buf
), FileFsAttributeInformation
);
4684 ffai
= (FILE_FS_ATTRIBUTE_INFORMATION
*)buf
;
4686 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %ld\n", status
);
4687 ok(io
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %ld\n", io
.Status
);
4688 ok(ffai
->FileSystemAttributes
!= 0, "Missing FileSystemAttributes\n");
4689 ok(ffai
->MaximumComponentNameLength
!= 0, "Missing MaximumComponentNameLength\n");
4690 ok(ffai
->FileSystemNameLength
!= 0, "Missing FileSystemNameLength\n");
4692 trace("FileSystemAttributes: %lx MaximumComponentNameLength: %lx FileSystemName: %s\n",
4693 ffai
->FileSystemAttributes
, ffai
->MaximumComponentNameLength
,
4694 wine_dbgstr_wn(ffai
->FileSystemName
, ffai
->FileSystemNameLength
/ sizeof(WCHAR
)));
4699 static void test_NtCreateFile(void)
4701 static const struct test_data
4703 DWORD disposition
, attrib_in
, status
, result
, attrib_out
, needs_cleanup
;
4706 /* 0*/{ FILE_CREATE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
4707 /* 1*/{ FILE_CREATE
, 0, STATUS_OBJECT_NAME_COLLISION
, 0, 0, TRUE
},
4708 /* 2*/{ FILE_CREATE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
4709 /* 3*/{ FILE_OPEN
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
},
4710 /* 4*/{ FILE_OPEN
, FILE_ATTRIBUTE_READONLY
, STATUS_OBJECT_NAME_NOT_FOUND
, 0, 0, FALSE
},
4711 /* 5*/{ FILE_OPEN_IF
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
4712 /* 6*/{ FILE_OPEN_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
},
4713 /* 7*/{ FILE_OPEN_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
4714 /* 8*/{ FILE_OPEN_IF
, 0, 0, FILE_OPENED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
4715 /* 9*/{ FILE_OVERWRITE
, 0, STATUS_ACCESS_DENIED
, 0, 0, TRUE
},
4716 /*10*/{ FILE_OVERWRITE
, 0, STATUS_OBJECT_NAME_NOT_FOUND
, 0, 0, FALSE
},
4717 /*11*/{ FILE_CREATE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
4718 /*12*/{ FILE_OVERWRITE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OVERWRITTEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
4719 /*13*/{ FILE_OVERWRITE_IF
, 0, STATUS_ACCESS_DENIED
, 0, 0, TRUE
},
4720 /*14*/{ FILE_OVERWRITE_IF
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
4721 /*15*/{ FILE_OVERWRITE_IF
, FILE_ATTRIBUTE_READONLY
, 0, FILE_OVERWRITTEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, FALSE
},
4722 /*16*/{ FILE_SUPERSEDE
, 0, 0, FILE_SUPERSEDED
, FILE_ATTRIBUTE_ARCHIVE
, FALSE
},
4723 /*17*/{ FILE_SUPERSEDE
, FILE_ATTRIBUTE_READONLY
, 0, FILE_SUPERSEDED
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
, TRUE
},
4724 /*18*/{ FILE_SUPERSEDE
, 0, 0, FILE_CREATED
, FILE_ATTRIBUTE_ARCHIVE
, TRUE
}
4726 static const WCHAR fooW
[] = {'f','o','o',0};
4729 WCHAR path
[MAX_PATH
];
4730 OBJECT_ATTRIBUTES attr
;
4732 UNICODE_STRING nameW
;
4735 GetTempPathW(MAX_PATH
, path
);
4736 GetTempFileNameW(path
, fooW
, 0, path
);
4738 pRtlDosPathNameToNtPathName_U(path
, &nameW
, NULL
, NULL
);
4740 attr
.Length
= sizeof(attr
);
4741 attr
.RootDirectory
= NULL
;
4742 attr
.ObjectName
= &nameW
;
4743 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
4744 attr
.SecurityDescriptor
= NULL
;
4745 attr
.SecurityQualityOfService
= NULL
;
4747 for (i
= 0; i
< ARRAY_SIZE(td
); i
++)
4749 status
= pNtCreateFile(&handle
, GENERIC_READ
, &attr
, &io
, NULL
,
4750 td
[i
].attrib_in
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4751 td
[i
].disposition
, 0, NULL
, 0);
4753 ok(status
== td
[i
].status
, "%ld: expected %#lx got %#lx\n", i
, td
[i
].status
, status
);
4757 ok(io
.Information
== td
[i
].result
,"%ld: expected %#lx got %#Ix\n", i
, td
[i
].result
, io
.Information
);
4759 ret
= GetFileAttributesW(path
);
4760 ret
&= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
;
4761 /* FIXME: leave only 'else' case below once Wine is fixed */
4762 if (ret
!= td
[i
].attrib_out
)
4765 ok(ret
== td
[i
].attrib_out
, "%ld: expected %#lx got %#lx\n", i
, td
[i
].attrib_out
, ret
);
4766 SetFileAttributesW(path
, td
[i
].attrib_out
);
4769 ok(ret
== td
[i
].attrib_out
, "%ld: expected %#lx got %#lx\n", i
, td
[i
].attrib_out
, ret
);
4771 CloseHandle(handle
);
4774 if (td
[i
].needs_cleanup
)
4776 SetFileAttributesW(path
, FILE_ATTRIBUTE_ARCHIVE
);
4781 pRtlFreeUnicodeString( &nameW
);
4782 SetFileAttributesW(path
, FILE_ATTRIBUTE_ARCHIVE
);
4783 DeleteFileW( path
);
4785 wcscat( path
, L
"\\" );
4786 pRtlDosPathNameToNtPathName_U(path
, &nameW
, NULL
, NULL
);
4788 status
= pNtCreateFile( &handle
, GENERIC_READ
, &attr
, &io
, NULL
,
4789 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_CREATE
, 0, NULL
, 0);
4790 ok( status
== STATUS_OBJECT_NAME_INVALID
, "failed %s %lx\n", debugstr_w(nameW
.Buffer
), status
);
4791 status
= pNtCreateFile( &handle
, GENERIC_READ
, &attr
, &io
, NULL
,
4792 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_CREATE
,
4793 FILE_DIRECTORY_FILE
, NULL
, 0);
4794 ok( !status
, "failed %s %lx\n", debugstr_w(nameW
.Buffer
), status
);
4795 RemoveDirectoryW( path
);
4798 static void test_read_write(void)
4800 static const char contents
[14] = "1234567890abcd";
4802 HANDLE hfile
, event
;
4804 IO_STATUS_BLOCK iob
;
4805 DWORD ret
, bytes
, status
, off
;
4806 LARGE_INTEGER offset
;
4809 event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
4812 iob
.Information
= -1;
4813 offset
.QuadPart
= 0;
4814 status
= pNtReadFile(INVALID_HANDLE_VALUE
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
4815 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
|| status
== STATUS_INVALID_HANDLE
, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status
);
4816 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4817 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4820 iob
.Information
= -1;
4821 offset
.QuadPart
= 0;
4822 status
= pNtReadFile(INVALID_HANDLE_VALUE
, 0, NULL
, NULL
, &iob
, NULL
, sizeof(buf
), &offset
, NULL
);
4823 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
|| status
== STATUS_INVALID_HANDLE
, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status
);
4824 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4825 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4828 iob
.Information
= -1;
4829 offset
.QuadPart
= 0;
4830 status
= pNtWriteFile(INVALID_HANDLE_VALUE
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
4831 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
|| status
== STATUS_INVALID_HANDLE
, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status
);
4832 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4833 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4836 iob
.Information
= -1;
4837 offset
.QuadPart
= 0;
4838 status
= pNtWriteFile(INVALID_HANDLE_VALUE
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
4839 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
|| status
== STATUS_INVALID_HANDLE
, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status
);
4840 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4841 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4843 hfile
= create_temp_file(0);
4847 iob
.Information
= -1;
4848 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, NULL
, sizeof(contents
), NULL
, NULL
);
4849 ok(status
== STATUS_INVALID_USER_BUFFER
, "expected STATUS_INVALID_USER_BUFFER, got %#lx\n", status
);
4850 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4851 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4854 iob
.Information
= -1;
4856 status
= pNtWriteFile(hfile
, event
, NULL
, NULL
, &iob
, NULL
, sizeof(contents
), NULL
, NULL
);
4857 ok(status
== STATUS_INVALID_USER_BUFFER
, "expected STATUS_INVALID_USER_BUFFER, got %#lx\n", status
);
4858 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4859 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4860 ok(!is_signaled(event
), "event is not signaled\n");
4863 iob
.Information
= -1;
4864 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, NULL
, sizeof(contents
), NULL
, NULL
);
4865 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status
);
4866 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4867 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4870 iob
.Information
= -1;
4872 status
= pNtReadFile(hfile
, event
, NULL
, NULL
, &iob
, NULL
, sizeof(contents
), NULL
, NULL
);
4873 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status
);
4874 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4875 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4876 ok(is_signaled(event
), "event is not signaled\n");
4879 iob
.Information
= -1;
4881 status
= pNtReadFile(hfile
, event
, NULL
, NULL
, &iob
, (void*)0xdeadbeef, sizeof(contents
), NULL
, NULL
);
4882 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#lx\n", status
);
4883 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4884 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
4885 ok(is_signaled(event
), "event is not signaled\n");
4888 iob
.Information
= -1;
4889 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, 7, NULL
, NULL
);
4890 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
4891 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
4892 ok(iob
.Information
== 7, "expected 7, got %Iu\n", iob
.Information
);
4894 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
4897 iob
.Information
= -1;
4898 offset
.QuadPart
= (LONGLONG
)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4899 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
+ 7, sizeof(contents
) - 7, &offset
, NULL
);
4900 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
4901 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
4902 ok(iob
.Information
== sizeof(contents
) - 7, "expected sizeof(contents)-7, got %Iu\n", iob
.Information
);
4904 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
4905 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
4908 SetLastError(0xdeadbeef);
4909 ret
= ReadFile(INVALID_HANDLE_VALUE
, buf
, 0, &bytes
, NULL
);
4910 ok(!ret
, "ReadFile should fail\n");
4911 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
4912 ok(bytes
== 0, "bytes %lu\n", bytes
);
4915 SetLastError(0xdeadbeef);
4916 ret
= ReadFile(hfile
, buf
, 0, &bytes
, NULL
);
4917 ok(ret
, "ReadFile error %ld\n", GetLastError());
4918 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4919 ok(bytes
== 0, "bytes %lu\n", bytes
);
4922 SetLastError(0xdeadbeef);
4923 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
4924 ok(ret
, "ReadFile error %ld\n", GetLastError());
4925 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
4926 ok(bytes
== 0, "bytes %lu\n", bytes
);
4928 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
4931 SetLastError(0xdeadbeef);
4932 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
4933 ok(ret
, "ReadFile error %ld\n", GetLastError());
4934 ok(bytes
== sizeof(contents
), "bytes %lu\n", bytes
);
4935 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
4937 for (i
= -20; i
< -1; i
++)
4939 if (i
== -2) continue;
4942 iob
.Information
= -1;
4943 offset
.QuadPart
= (LONGLONG
)i
;
4944 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), &offset
, NULL
);
4945 ok(status
== STATUS_INVALID_PARAMETER
, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i
, status
);
4946 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
4947 ok(iob
.Information
== -1, "expected -1, got %Id\n", iob
.Information
);
4950 SetFilePointer(hfile
, sizeof(contents
) - 4, NULL
, FILE_BEGIN
);
4953 iob
.Information
= -1;
4954 offset
.QuadPart
= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */;
4955 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, "DCBA", 4, &offset
, NULL
);
4956 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
4957 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
4958 ok(iob
.Information
== 4, "expected 4, got %Iu\n", iob
.Information
);
4960 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
4961 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
4964 iob
.Information
= -1;
4965 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), NULL
, NULL
);
4966 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", status
);
4967 ok(iob
.Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", iob
.Status
);
4968 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
4970 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
4973 SetLastError(0xdeadbeef);
4974 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
4975 ok(ret
, "ReadFile error %ld\n", GetLastError());
4976 ok(bytes
== sizeof(contents
), "bytes %lu\n", bytes
);
4977 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
4978 ok(!memcmp(buf
+ sizeof(contents
) - 4, "DCBA", 4), "file contents mismatch\n");
4980 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
4981 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
4983 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
4986 SetLastError(0xdeadbeef);
4987 ret
= WriteFile(hfile
, contents
, sizeof(contents
), &bytes
, NULL
);
4988 ok(ret
, "WriteFile error %ld\n", GetLastError());
4989 ok(bytes
== sizeof(contents
), "bytes %lu\n", bytes
);
4991 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
4992 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
4994 /* test reading beyond EOF */
4996 SetLastError(0xdeadbeef);
4997 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
4998 ok(ret
, "ReadFile error %ld\n", GetLastError());
4999 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5000 ok(bytes
== 0, "bytes %lu\n", bytes
);
5003 SetLastError(0xdeadbeef);
5004 ret
= ReadFile(hfile
, buf
, 0, &bytes
, NULL
);
5005 ok(ret
, "ReadFile error %ld\n", GetLastError());
5006 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5007 ok(bytes
== 0, "bytes %lu\n", bytes
);
5010 SetLastError(0xdeadbeef);
5011 ret
= ReadFile(hfile
, NULL
, 0, &bytes
, NULL
);
5012 ok(ret
, "ReadFile error %ld\n", GetLastError());
5013 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5014 ok(bytes
== 0, "bytes %lu\n", bytes
);
5016 ovl
.Offset
= sizeof(contents
);
5019 ovl
.InternalHigh
= -1;
5022 SetLastError(0xdeadbeef);
5023 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
5024 ok(!ret
, "ReadFile should fail\n");
5025 ok(GetLastError() == ERROR_HANDLE_EOF
, "expected ERROR_HANDLE_EOF, got %ld\n", GetLastError());
5026 ok(bytes
== 0, "bytes %lu\n", bytes
);
5027 ok((NTSTATUS
)ovl
.Internal
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#Ix\n", ovl
.Internal
);
5028 ok(ovl
.InternalHigh
== 0, "expected 0, got %Iu\n", ovl
.InternalHigh
);
5030 ovl
.Offset
= sizeof(contents
);
5033 ovl
.InternalHigh
= -1;
5036 SetLastError(0xdeadbeef);
5037 ret
= ReadFile(hfile
, buf
, 0, &bytes
, &ovl
);
5038 ok(ret
, "ReadFile error %ld\n", GetLastError());
5039 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
5040 ok(bytes
== 0, "bytes %lu\n", bytes
);
5041 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5042 ok(ovl
.InternalHigh
== 0, "expected 0, got %Iu\n", ovl
.InternalHigh
);
5045 iob
.Information
= -1;
5046 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), NULL
, NULL
);
5047 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", status
);
5048 ok(iob
.Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", iob
.Status
);
5049 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5052 iob
.Information
= -1;
5053 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, NULL
, NULL
);
5054 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#lx\n", status
);
5055 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5056 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5059 iob
.Information
= -1;
5060 offset
.QuadPart
= sizeof(contents
);
5061 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5062 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", status
);
5063 ok(iob
.Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", iob
.Status
);
5064 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5067 iob
.Information
= -1;
5068 offset
.QuadPart
= sizeof(contents
);
5069 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, &offset
, NULL
);
5070 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#lx\n", status
);
5071 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5072 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5075 iob
.Information
= -1;
5076 offset
.QuadPart
= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */;
5077 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5078 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", status
);
5079 ok(iob
.Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", iob
.Status
);
5080 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5083 iob
.Information
= -1;
5084 offset
.QuadPart
= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */;
5085 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, &offset
, NULL
);
5086 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#lx\n", status
);
5087 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5088 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5090 for (i
= -20; i
< 0; i
++)
5092 if (i
== -2) continue;
5095 iob
.Information
= -1;
5096 offset
.QuadPart
= (LONGLONG
)i
;
5097 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5098 ok(status
== STATUS_INVALID_PARAMETER
, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i
, status
);
5099 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
5100 ok(iob
.Information
== -1, "expected -1, got %Id\n", iob
.Information
);
5103 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
5106 SetLastError(0xdeadbeef);
5107 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
5108 ok(ret
, "ReadFile error %ld\n", GetLastError());
5109 ok(bytes
== sizeof(contents
), "bytes %lu\n", bytes
);
5110 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
5112 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5113 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
5116 iob
.Information
= -1;
5117 offset
.QuadPart
= 0;
5118 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5119 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#lx\n", status
);
5120 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5121 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", iob
.Information
);
5122 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
5124 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5125 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
5128 iob
.Information
= -1;
5129 offset
.QuadPart
= sizeof(contents
) - 4;
5130 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, "DCBA", 4, &offset
, NULL
);
5131 ok(status
== STATUS_SUCCESS
, "NtWriteFile error %#lx\n", status
);
5132 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5133 ok(iob
.Information
== 4, "expected 4, got %Iu\n", iob
.Information
);
5135 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5136 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
5139 iob
.Information
= -1;
5140 offset
.QuadPart
= 0;
5141 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5142 ok(status
== STATUS_SUCCESS
, "NtReadFile error %#lx\n", status
);
5143 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5144 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", iob
.Information
);
5145 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
5146 ok(!memcmp(buf
+ sizeof(contents
) - 4, "DCBA", 4), "file contents mismatch\n");
5148 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5149 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
5151 ovl
.Offset
= sizeof(contents
) - 4;
5155 SetLastError(0xdeadbeef);
5156 ret
= WriteFile(hfile
, "ABCD", 4, &bytes
, &ovl
);
5157 ok(ret
, "WriteFile error %ld\n", GetLastError());
5158 ok(bytes
== 4, "bytes %lu\n", bytes
);
5160 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5161 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
5166 ovl
.InternalHigh
= -1;
5169 SetLastError(0xdeadbeef);
5170 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
5171 ok(ret
, "ReadFile error %ld\n", GetLastError());
5172 ok(bytes
== sizeof(contents
), "bytes %lu\n", bytes
);
5173 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5174 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", ovl
.InternalHigh
);
5175 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
5176 ok(!memcmp(buf
+ sizeof(contents
) - 4, "ABCD", 4), "file contents mismatch\n");
5178 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5179 ok(off
== sizeof(contents
), "expected sizeof(contents), got %lu\n", off
);
5183 hfile
= create_temp_file(FILE_FLAG_OVERLAPPED
);
5187 SetLastError(0xdeadbeef);
5188 ret
= ReadFile(INVALID_HANDLE_VALUE
, buf
, 0, &bytes
, NULL
);
5189 ok(!ret
, "ReadFile should fail\n");
5190 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
5191 ok(bytes
== 0, "bytes %lu\n", bytes
);
5196 ovl
.InternalHigh
= -1;
5199 SetLastError(0xdeadbeef);
5200 /* ReadFile return value depends on Windows version and testing it is not practical */
5201 ReadFile(hfile
, buf
, 0, &bytes
, &ovl
);
5202 ok(bytes
== 0, "bytes %lu\n", bytes
);
5203 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5204 ok(ovl
.InternalHigh
== 0, "expected 0, got %Iu\n", ovl
.InternalHigh
);
5207 SetLastError(0xdeadbeef);
5208 ret
= WriteFile(hfile
, contents
, sizeof(contents
), &bytes
, NULL
);
5209 ok(!ret
, "WriteFile should fail\n");
5210 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
5211 ok(bytes
== 0, "bytes %lu\n", bytes
);
5214 iob
.Information
= -1;
5215 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), NULL
, NULL
);
5216 ok(status
== STATUS_INVALID_PARAMETER
, "expected STATUS_INVALID_PARAMETER, got %#lx\n", status
);
5217 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
5218 ok(iob
.Information
== -1, "expected -1, got %Id\n", iob
.Information
);
5220 for (i
= -20; i
< -1; i
++)
5223 iob
.Information
= -1;
5224 offset
.QuadPart
= (LONGLONG
)i
;
5225 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), &offset
, NULL
);
5226 ok(status
== STATUS_INVALID_PARAMETER
, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i
, status
);
5227 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
5228 ok(iob
.Information
== -1, "expected -1, got %Id\n", iob
.Information
);
5232 iob
.Information
= -1;
5233 offset
.QuadPart
= 0;
5234 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, contents
, sizeof(contents
), &offset
, NULL
);
5235 ok(status
== STATUS_PENDING
|| broken(status
== STATUS_SUCCESS
) /* before Vista */,
5236 "expected STATUS_PENDING, got %#lx.\n", status
);
5237 if (status
== STATUS_PENDING
)
5239 ret
= WaitForSingleObject(hfile
, 3000);
5240 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %ld\n", ret
);
5242 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5243 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", iob
.Information
);
5245 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5246 ok(off
== 0, "expected 0, got %lu\n", off
);
5249 SetLastError(0xdeadbeef);
5250 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, NULL
);
5251 ok(!ret
, "ReadFile should fail\n");
5252 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
5253 ok(bytes
== 0, "bytes %lu\n", bytes
);
5256 iob
.Information
= -1;
5257 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), NULL
, NULL
);
5258 ok(status
== STATUS_INVALID_PARAMETER
, "expected STATUS_INVALID_PARAMETER, got %#lx\n", status
);
5259 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
5260 ok(iob
.Information
== -1, "expected -1, got %Id\n", iob
.Information
);
5262 for (i
= -20; i
< 0; i
++)
5265 iob
.Information
= -1;
5266 offset
.QuadPart
= (LONGLONG
)i
;
5267 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5268 ok(status
== STATUS_INVALID_PARAMETER
, "%ld: expected STATUS_INVALID_PARAMETER, got %#lx\n", i
, status
);
5269 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
5270 ok(iob
.Information
== -1, "expected -1, got %Id\n", iob
.Information
);
5273 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5274 ok(off
== 0, "expected 0, got %lu\n", off
);
5276 /* test reading beyond EOF */
5277 offset
.QuadPart
= sizeof(contents
);
5278 ovl
.Offset
= offset
.u
.LowPart
;
5279 ovl
.OffsetHigh
= offset
.u
.HighPart
;
5281 ovl
.InternalHigh
= -1;
5284 SetLastError(0xdeadbeef);
5285 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
5286 ok(!ret
, "ReadFile should fail\n");
5287 ret
= GetLastError();
5288 ok(ret
== ERROR_IO_PENDING
|| broken(ret
== ERROR_HANDLE_EOF
) /* before Vista */,
5289 "expected ERROR_IO_PENDING, got %ld\n", ret
);
5290 ok(bytes
== 0, "bytes %lu\n", bytes
);
5292 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5293 ok(off
== 0, "expected 0, got %lu\n", off
);
5295 if (ret
== ERROR_IO_PENDING
)
5298 SetLastError(0xdeadbeef);
5299 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
5300 ok(!ret
, "GetOverlappedResult should report FALSE\n");
5301 ok(GetLastError() == ERROR_HANDLE_EOF
, "expected ERROR_HANDLE_EOF, got %ld\n", GetLastError());
5302 ok(bytes
== 0, "expected 0, read %lu\n", bytes
);
5303 ok((NTSTATUS
)ovl
.Internal
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#Ix\n", ovl
.Internal
);
5304 ok(ovl
.InternalHigh
== 0, "expected 0, got %Iu\n", ovl
.InternalHigh
);
5307 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5308 ok(off
== 0, "expected 0, got %lu\n", off
);
5310 offset
.QuadPart
= sizeof(contents
);
5311 ovl
.Offset
= offset
.u
.LowPart
;
5312 ovl
.OffsetHigh
= offset
.u
.HighPart
;
5314 ovl
.InternalHigh
= -1;
5317 SetLastError(0xdeadbeef);
5318 ret
= ReadFile(hfile
, buf
, 0, &bytes
, &ovl
);
5319 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* before Vista */,
5320 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret
, GetLastError());
5321 ret
= GetLastError();
5322 ok(bytes
== 0, "bytes %lu\n", bytes
);
5324 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5325 ok(off
== 0, "expected 0, got %lu\n", off
);
5327 if (ret
== ERROR_IO_PENDING
)
5330 SetLastError(0xdeadbeef);
5331 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
5332 ok(ret
, "GetOverlappedResult returned FALSE with %lu (expected TRUE)\n", GetLastError());
5333 ok(bytes
== 0, "expected 0, read %lu\n", bytes
);
5334 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5335 ok(ovl
.InternalHigh
== 0, "expected 0, got %Iu\n", ovl
.InternalHigh
);
5338 offset
.QuadPart
= sizeof(contents
);
5339 ovl
.Offset
= offset
.u
.LowPart
;
5340 ovl
.OffsetHigh
= offset
.u
.HighPart
;
5342 ovl
.InternalHigh
= -1;
5345 SetLastError(0xdeadbeef);
5346 ret
= ReadFile(hfile
, NULL
, 0, &bytes
, &ovl
);
5347 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* before Vista */,
5348 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret
, GetLastError());
5349 ret
= GetLastError();
5350 ok(bytes
== 0, "bytes %lu\n", bytes
);
5352 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5353 ok(off
== 0, "expected 0, got %lu\n", off
);
5355 if (ret
== ERROR_IO_PENDING
)
5358 SetLastError(0xdeadbeef);
5359 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
5360 ok(ret
, "GetOverlappedResult returned FALSE with %lu (expected TRUE)\n", GetLastError());
5361 ok(bytes
== 0, "expected 0, read %lu\n", bytes
);
5362 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5363 ok(ovl
.InternalHigh
== 0, "expected 0, got %Iu\n", ovl
.InternalHigh
);
5367 iob
.Information
= -1;
5368 offset
.QuadPart
= sizeof(contents
);
5369 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5370 if (status
== STATUS_PENDING
)
5372 ret
= WaitForSingleObject(hfile
, 3000);
5373 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %ld\n", ret
);
5374 ok(iob
.Status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", iob
.Status
);
5375 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5379 ok(status
== STATUS_END_OF_FILE
, "expected STATUS_END_OF_FILE, got %#lx\n", status
);
5380 ok(iob
.Status
== -1, "expected -1, got %#lx\n", iob
.Status
);
5381 ok(iob
.Information
== -1, "expected -1, got %Iu\n", iob
.Information
);
5384 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5385 ok(off
== 0, "expected 0, got %lu\n", off
);
5388 iob
.Information
= -1;
5389 offset
.QuadPart
= sizeof(contents
);
5390 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, 0, &offset
, NULL
);
5391 ok(status
== STATUS_PENDING
|| broken(status
== STATUS_SUCCESS
) /* before Vista */,
5392 "expected STATUS_PENDING, got %#lx.\n", status
);
5393 if (status
== STATUS_PENDING
)
5395 ret
= WaitForSingleObject(hfile
, 3000);
5396 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %ld\n", ret
);
5397 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5398 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5402 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5403 ok(iob
.Information
== 0, "expected 0, got %Iu\n", iob
.Information
);
5406 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5407 ok(off
== 0, "expected 0, got %lu\n", off
);
5412 ovl
.InternalHigh
= -1;
5415 SetLastError(0xdeadbeef);
5416 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
5417 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* before Vista */,
5418 "Unexpected result, ret %#lx, GetLastError() %lu.\n", ret
, GetLastError());
5420 ok(bytes
== 0, "bytes %lu\n", bytes
);
5422 ok(bytes
== 14, "bytes %lu\n", bytes
);
5423 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5424 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", ovl
.InternalHigh
);
5426 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5427 ok(off
== 0, "expected 0, got %lu\n", off
);
5430 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
5431 ok(ret
, "GetOverlappedResult error %ld\n", GetLastError());
5432 ok(bytes
== sizeof(contents
), "bytes %lu\n", bytes
);
5433 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5434 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", ovl
.InternalHigh
);
5435 ok(!memcmp(contents
, buf
, sizeof(contents
)), "file contents mismatch\n");
5437 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5438 ok(off
== 0, "expected 0, got %lu\n", off
);
5440 SetFilePointer(hfile
, sizeof(contents
) - 4, NULL
, FILE_BEGIN
);
5441 SetEndOfFile(hfile
);
5442 SetFilePointer(hfile
, 0, NULL
, FILE_BEGIN
);
5445 iob
.Information
= -1;
5446 offset
.QuadPart
= (LONGLONG
)-1 /* FILE_WRITE_TO_END_OF_FILE */;
5447 status
= pNtWriteFile(hfile
, 0, NULL
, NULL
, &iob
, "DCBA", 4, &offset
, NULL
);
5448 ok(status
== STATUS_PENDING
|| broken(status
== STATUS_SUCCESS
) /* before Vista */,
5449 "expected STATUS_PENDING, got %#lx.\n", status
);
5450 if (status
== STATUS_PENDING
)
5452 ret
= WaitForSingleObject(hfile
, 3000);
5453 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %ld\n", ret
);
5455 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5456 ok(iob
.Information
== 4, "expected 4, got %Iu\n", iob
.Information
);
5458 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5459 ok(off
== 0, "expected 0, got %lu\n", off
);
5462 iob
.Information
= -1;
5463 offset
.QuadPart
= 0;
5464 status
= pNtReadFile(hfile
, 0, NULL
, NULL
, &iob
, buf
, sizeof(buf
), &offset
, NULL
);
5465 ok(status
== STATUS_PENDING
|| broken(status
== STATUS_SUCCESS
) /* before Vista */,
5466 "expected STATUS_PENDING, got %#lx.\n", status
);
5467 if (status
== STATUS_PENDING
)
5469 ret
= WaitForSingleObject(hfile
, 3000);
5470 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %ld\n", ret
);
5472 ok(iob
.Status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", iob
.Status
);
5473 ok(iob
.Information
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", iob
.Information
);
5475 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5476 ok(off
== 0, "expected 0, got %lu\n", off
);
5478 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
5479 ok(!memcmp(buf
+ sizeof(contents
) - 4, "DCBA", 4), "file contents mismatch\n");
5481 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5482 ok(off
== 0, "expected 0, got %lu\n", off
);
5484 ovl
.Offset
= sizeof(contents
) - 4;
5487 ovl
.InternalHigh
= -1;
5490 SetLastError(0xdeadbeef);
5491 ret
= WriteFile(hfile
, "ABCD", 4, &bytes
, &ovl
);
5492 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* before Vista */,
5493 "Unexpected result %#lx, GetLastError() %lu.\n", ret
, GetLastError());
5496 ok(bytes
== 0, "bytes %lu\n", bytes
);
5497 ret
= WaitForSingleObject(hfile
, 3000);
5498 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %ld\n", ret
);
5500 else ok(bytes
== 4, "bytes %lu\n", bytes
);
5501 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5502 ok(ovl
.InternalHigh
== 4, "expected 4, got %Iu\n", ovl
.InternalHigh
);
5504 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5505 ok(off
== 0, "expected 0, got %lu\n", off
);
5508 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
5509 ok(ret
, "GetOverlappedResult error %ld\n", GetLastError());
5510 ok(bytes
== 4, "bytes %lu\n", bytes
);
5511 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5512 ok(ovl
.InternalHigh
== 4, "expected 4, got %Iu\n", ovl
.InternalHigh
);
5514 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5515 ok(off
== 0, "expected 0, got %lu\n", off
);
5520 ovl
.InternalHigh
= -1;
5523 SetLastError(0xdeadbeef);
5524 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &bytes
, &ovl
);
5525 ok((!ret
&& GetLastError() == ERROR_IO_PENDING
) || broken(ret
) /* before Vista */,
5526 "Unexpected result %#lx, GetLastError() %lu.\n", ret
, GetLastError());
5529 ok(bytes
== 0, "bytes %lu\n", bytes
);
5530 ret
= WaitForSingleObject(hfile
, 3000);
5531 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject error %ld\n", ret
);
5533 else ok(bytes
== 14, "bytes %lu\n", bytes
);
5534 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5535 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", ovl
.InternalHigh
);
5537 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5538 ok(off
== 0, "expected 0, got %lu\n", off
);
5541 ret
= GetOverlappedResult(hfile
, &ovl
, &bytes
, TRUE
);
5542 ok(ret
, "GetOverlappedResult error %ld\n", GetLastError());
5543 ok(bytes
== sizeof(contents
), "bytes %lu\n", bytes
);
5544 ok((NTSTATUS
)ovl
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#Ix\n", ovl
.Internal
);
5545 ok(ovl
.InternalHigh
== sizeof(contents
), "expected sizeof(contents), got %Iu\n", ovl
.InternalHigh
);
5546 ok(!memcmp(contents
, buf
, sizeof(contents
) - 4), "file contents mismatch\n");
5547 ok(!memcmp(buf
+ sizeof(contents
) - 4, "ABCD", 4), "file contents mismatch\n");
5549 off
= SetFilePointer(hfile
, 0, NULL
, FILE_CURRENT
);
5550 ok(off
== 0, "expected 0, got %lu\n", off
);
5556 static void test_ioctl(void)
5558 HANDLE event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
5559 FILE_PIPE_PEEK_BUFFER peek_buf
;
5560 IO_STATUS_BLOCK iosb
;
5564 file
= create_temp_file(FILE_FLAG_OVERLAPPED
);
5565 ok(file
!= INVALID_HANDLE_VALUE
, "could not create temp file\n");
5568 status
= pNtFsControlFile(file
, event
, NULL
, NULL
, &iosb
, 0xdeadbeef, 0, 0, 0, 0);
5570 ok(status
== STATUS_INVALID_DEVICE_REQUEST
, "NtFsControlFile returned %lx\n", status
);
5571 ok(!is_signaled(event
), "event is signaled\n");
5573 status
= pNtFsControlFile(file
, (HANDLE
)0xdeadbeef, NULL
, NULL
, &iosb
, 0xdeadbeef, 0, 0, 0, 0);
5574 ok(status
== STATUS_INVALID_HANDLE
, "NtFsControlFile returned %lx\n", status
);
5576 memset(&iosb
, 0x55, sizeof(iosb
));
5577 status
= pNtFsControlFile(file
, NULL
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0,
5578 &peek_buf
, sizeof(peek_buf
));
5580 ok(status
== STATUS_INVALID_DEVICE_REQUEST
, "NtFsControlFile failed: %lx\n", status
);
5581 ok(iosb
.Status
== 0x55555555, "iosb.Status = %lx\n", iosb
.Status
);
5587 static void test_flush_buffers_file(void)
5589 char path
[MAX_PATH
], buffer
[MAX_PATH
];
5590 HANDLE hfile
, hfileread
;
5592 IO_STATUS_BLOCK io_status_block
;
5594 GetTempPathA(MAX_PATH
, path
);
5595 GetTempFileNameA(path
, "foo", 0, buffer
);
5596 hfile
= CreateFileA(buffer
, GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
,
5597 FILE_ATTRIBUTE_NORMAL
, 0);
5598 ok(hfile
!= INVALID_HANDLE_VALUE
, "failed to create temp file.\n" );
5600 hfileread
= CreateFileA(buffer
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
5601 OPEN_EXISTING
, 0, NULL
);
5602 ok(hfileread
!= INVALID_HANDLE_VALUE
, "could not open temp file, error %ld.\n", GetLastError());
5604 status
= pNtFlushBuffersFile(hfile
, NULL
);
5605 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
, "got %#lx.\n", status
);
5607 status
= pNtFlushBuffersFile(hfile
, (IO_STATUS_BLOCK
*)0xdeadbeaf);
5608 ok(status
== STATUS_ACCESS_VIOLATION
, "expected STATUS_ACCESS_VIOLATION, got %#lx.\n", status
);
5610 io_status_block
.Information
= 0xdeadbeef;
5611 io_status_block
.Status
= 0xdeadbeef;
5612 status
= pNtFlushBuffersFile(hfile
, &io_status_block
);
5613 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx.\n", status
);
5614 ok(io_status_block
.Status
== STATUS_SUCCESS
, "Got unexpected io_status_block.Status %#lx.\n",
5615 io_status_block
.Status
);
5616 ok(!io_status_block
.Information
, "Got unexpected io_status_block.Information %#Ix.\n",
5617 io_status_block
.Information
);
5619 status
= pNtFlushBuffersFile(hfileread
, &io_status_block
);
5620 ok(status
== STATUS_ACCESS_DENIED
, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status
);
5622 io_status_block
.Information
= 0xdeadbeef;
5623 io_status_block
.Status
= 0xdeadbeef;
5624 status
= pNtFlushBuffersFile(NULL
, &io_status_block
);
5625 ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %#lx.\n", status
);
5626 ok(io_status_block
.Status
== 0xdeadbeef, "Got unexpected io_status_block.Status %#lx.\n",
5627 io_status_block
.Status
);
5628 ok(io_status_block
.Information
== 0xdeadbeef, "Got unexpected io_status_block.Information %#Ix.\n",
5629 io_status_block
.Information
);
5631 CloseHandle(hfileread
);
5633 hfile
= CreateFileA(buffer
, FILE_APPEND_DATA
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
5634 OPEN_EXISTING
, 0, NULL
);
5635 ok(hfile
!= INVALID_HANDLE_VALUE
, "could not open temp file, error %ld.\n", GetLastError());
5637 status
= pNtFlushBuffersFile(hfile
, &io_status_block
);
5638 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx.\n", status
);
5640 io_status_block
.Information
= 0xdeadbeef;
5641 io_status_block
.Status
= 0xdeadbeef;
5642 status
= pNtFlushBuffersFile((HANDLE
)0xdeadbeef, &io_status_block
);
5643 ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %#lx.\n", status
);
5644 ok(io_status_block
.Status
== 0xdeadbeef, "Got unexpected io_status_block.Status %#lx.\n",
5645 io_status_block
.Status
);
5646 ok(io_status_block
.Information
== 0xdeadbeef, "Got unexpected io_status_block.Information %#Ix.\n",
5647 io_status_block
.Information
);
5650 DeleteFileA(buffer
);
5653 static void test_query_ea(void)
5655 #define EA_BUFFER_SIZE 4097
5656 unsigned char data
[EA_BUFFER_SIZE
+ 8];
5657 unsigned char *buffer
= (void *)(((DWORD_PTR
)data
+ 7) & ~7);
5658 DWORD buffer_len
, i
;
5663 if (!(handle
= create_temp_file(0))) return;
5665 /* test with INVALID_HANDLE_VALUE */
5666 io
.Status
= 0xdeadbeef;
5667 io
.Information
= 0xdeadbeef;
5668 memset(buffer
, 0xcc, EA_BUFFER_SIZE
);
5669 buffer_len
= EA_BUFFER_SIZE
- 1;
5670 status
= pNtQueryEaFile(INVALID_HANDLE_VALUE
, &io
, buffer
, buffer_len
, TRUE
, NULL
, 0, NULL
, FALSE
);
5671 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#lx\n", status
);
5672 ok(io
.Status
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io
.Status
);
5673 ok(io
.Information
== 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io
.Information
);
5674 ok(buffer
[0] == 0xcc, "data at position 0 overwritten\n");
5676 /* test with 0xdeadbeef */
5677 io
.Status
= 0xdeadbeef;
5678 io
.Information
= 0xdeadbeef;
5679 memset(buffer
, 0xcc, EA_BUFFER_SIZE
);
5680 buffer_len
= EA_BUFFER_SIZE
- 1;
5681 status
= pNtQueryEaFile((void *)0xdeadbeef, &io
, buffer
, buffer_len
, TRUE
, NULL
, 0, NULL
, FALSE
);
5682 ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %#lx\n", status
);
5683 ok(io
.Status
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io
.Status
);
5684 ok(io
.Information
== 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io
.Information
);
5685 ok(buffer
[0] == 0xcc, "data at position 0 overwritten\n");
5687 /* test without buffer */
5688 io
.Status
= 0xdeadbeef;
5689 io
.Information
= 0xdeadbeef;
5690 status
= pNtQueryEaFile(handle
, &io
, NULL
, 0, TRUE
, NULL
, 0, NULL
, FALSE
);
5691 ok(status
== STATUS_NO_EAS_ON_FILE
, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status
);
5692 ok(io
.Status
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io
.Status
);
5693 ok(io
.Information
== 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io
.Information
);
5695 /* test with zero buffer */
5696 io
.Status
= 0xdeadbeef;
5697 io
.Information
= 0xdeadbeef;
5698 status
= pNtQueryEaFile(handle
, &io
, buffer
, 0, TRUE
, NULL
, 0, NULL
, FALSE
);
5699 ok(status
== STATUS_NO_EAS_ON_FILE
, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status
);
5700 ok(io
.Status
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io
.Status
);
5701 ok(io
.Information
== 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io
.Information
);
5703 /* test with very small buffer */
5704 io
.Status
= 0xdeadbeef;
5705 io
.Information
= 0xdeadbeef;
5706 memset(buffer
, 0xcc, EA_BUFFER_SIZE
);
5708 status
= pNtQueryEaFile(handle
, &io
, buffer
, buffer_len
, TRUE
, NULL
, 0, NULL
, FALSE
);
5709 ok(status
== STATUS_NO_EAS_ON_FILE
, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status
);
5710 ok(io
.Status
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io
.Status
);
5711 ok(io
.Information
== 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io
.Information
);
5712 for (i
= 0; i
< buffer_len
&& !buffer
[i
]; i
++);
5713 ok(i
== buffer_len
, "expected %lu bytes filled with 0x00, got %lu bytes\n", buffer_len
, i
);
5714 ok(buffer
[i
] == 0xcc, "data at position %u overwritten\n", buffer
[i
]);
5716 /* test with very big buffer */
5717 io
.Status
= 0xdeadbeef;
5718 io
.Information
= 0xdeadbeef;
5719 memset(buffer
, 0xcc, EA_BUFFER_SIZE
);
5720 buffer_len
= EA_BUFFER_SIZE
- 1;
5721 status
= pNtQueryEaFile(handle
, &io
, buffer
, buffer_len
, TRUE
, NULL
, 0, NULL
, FALSE
);
5722 ok(status
== STATUS_NO_EAS_ON_FILE
, "expected STATUS_NO_EAS_ON_FILE, got %#lx\n", status
);
5723 ok(io
.Status
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", io
.Status
);
5724 ok(io
.Information
== 0xdeadbeef, "expected 0xdeadbeef, got %#Ix\n", io
.Information
);
5725 for (i
= 0; i
< buffer_len
&& !buffer
[i
]; i
++);
5726 ok(i
== buffer_len
, "expected %lu bytes filled with 0x00, got %lu bytes\n", buffer_len
, i
);
5727 ok(buffer
[i
] == 0xcc, "data at position %u overwritten\n", buffer
[i
]);
5729 CloseHandle(handle
);
5730 #undef EA_BUFFER_SIZE
5733 static void test_file_readonly_access(void)
5735 static const DWORD default_sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
5736 static const WCHAR fooW
[] = {'f', 'o', 'o', 0};
5737 WCHAR path
[MAX_PATH
];
5738 OBJECT_ATTRIBUTES attr
;
5739 UNICODE_STRING nameW
;
5746 GetTempPathW(MAX_PATH
, path
);
5747 GetTempFileNameW(path
, fooW
, 0, path
);
5749 pRtlDosPathNameToNtPathName_U(path
, &nameW
, NULL
, NULL
);
5751 attr
.Length
= sizeof(attr
);
5752 attr
.RootDirectory
= NULL
;
5753 attr
.ObjectName
= &nameW
;
5754 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
5755 attr
.SecurityDescriptor
= NULL
;
5756 attr
.SecurityQualityOfService
= NULL
;
5758 status
= pNtCreateFile(&handle
, FILE_GENERIC_WRITE
, &attr
, &io
, NULL
, FILE_ATTRIBUTE_READONLY
, default_sharing
,
5759 FILE_CREATE
, 0, NULL
, 0);
5760 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx.\n", status
);
5761 CloseHandle(handle
);
5763 /* NtCreateFile FILE_GENERIC_WRITE */
5764 status
= pNtCreateFile(&handle
, FILE_GENERIC_WRITE
, &attr
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, default_sharing
,
5765 FILE_OPEN
, FILE_NON_DIRECTORY_FILE
, NULL
, 0);
5766 ok(status
== STATUS_ACCESS_DENIED
, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status
);
5768 /* NtCreateFile DELETE without FILE_DELETE_ON_CLOSE */
5769 status
= pNtCreateFile(&handle
, DELETE
, &attr
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, default_sharing
, FILE_OPEN
,
5770 FILE_NON_DIRECTORY_FILE
, NULL
, 0);
5771 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx.\n", status
);
5772 CloseHandle(handle
);
5774 /* NtCreateFile DELETE with FILE_DELETE_ON_CLOSE */
5775 status
= pNtCreateFile(&handle
, SYNCHRONIZE
| DELETE
, &attr
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, default_sharing
,
5776 FILE_OPEN
, FILE_DELETE_ON_CLOSE
| FILE_NON_DIRECTORY_FILE
, NULL
, 0);
5777 ok(status
== STATUS_CANNOT_DELETE
, "expected STATUS_CANNOT_DELETE, got %#lx.\n", status
);
5779 /* NtOpenFile GENERIC_WRITE */
5780 status
= pNtOpenFile(&handle
, GENERIC_WRITE
, &attr
, &io
, default_sharing
, FILE_NON_DIRECTORY_FILE
);
5781 ok(status
== STATUS_ACCESS_DENIED
, "expected STATUS_ACCESS_DENIED, got %#lx.\n", status
);
5783 /* NtOpenFile DELETE without FILE_DELETE_ON_CLOSE */
5784 status
= pNtOpenFile(&handle
, DELETE
, &attr
, &io
, default_sharing
, FILE_NON_DIRECTORY_FILE
);
5785 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx.\n", status
);
5786 CloseHandle(handle
);
5788 /* NtOpenFile DELETE with FILE_DELETE_ON_CLOSE */
5789 status
= pNtOpenFile(&handle
, DELETE
, &attr
, &io
, default_sharing
, FILE_DELETE_ON_CLOSE
| FILE_NON_DIRECTORY_FILE
);
5790 ok(status
== STATUS_CANNOT_DELETE
, "expected STATUS_CANNOT_DELETE, got %#lx.\n", status
);
5792 ret
= GetFileAttributesW(path
);
5793 ok(ret
& FILE_ATTRIBUTE_READONLY
, "got wrong attribute: %#lx.\n", ret
);
5796 pRtlFreeUnicodeString(&nameW
);
5797 SetFileAttributesW(path
, FILE_ATTRIBUTE_NORMAL
);
5801 static void test_mailslot_name(void)
5803 char buffer
[1024] = {0};
5804 const FILE_NAME_INFORMATION
*name
= (const FILE_NAME_INFORMATION
*)buffer
;
5805 HANDLE server
, client
, device
;
5809 server
= CreateMailslotA( "\\\\.\\mailslot\\winetest", 100, 1000, NULL
);
5810 ok(server
!= INVALID_HANDLE_VALUE
, "got error %lu\n", GetLastError());
5812 ret
= NtQueryInformationFile( server
, &io
, buffer
, 0, FileNameInformation
);
5813 ok(ret
== STATUS_INFO_LENGTH_MISMATCH
, "got %#lx\n", ret
);
5815 memset(buffer
, 0xcc, sizeof(buffer
));
5816 ret
= NtQueryInformationFile( server
, &io
, buffer
,
5817 offsetof(FILE_NAME_INFORMATION
, FileName
[5]), FileNameInformation
);
5818 todo_wine
ok(ret
== STATUS_BUFFER_OVERFLOW
, "got %#lx\n", ret
);
5819 if (ret
== STATUS_BUFFER_OVERFLOW
)
5821 ok(name
->FileNameLength
== 18, "got length %lu\n", name
->FileNameLength
);
5822 ok(!memcmp(name
->FileName
, L
"\\wine", 10), "got %s\n",
5823 debugstr_wn(name
->FileName
, name
->FileNameLength
/ sizeof(WCHAR
)));
5826 memset(buffer
, 0xcc, sizeof(buffer
));
5827 ret
= NtQueryInformationFile( server
, &io
, buffer
, sizeof(buffer
), FileNameInformation
);
5828 todo_wine
ok(!ret
, "got %#lx\n", ret
);
5831 ok(name
->FileNameLength
== 18, "got length %lu\n", name
->FileNameLength
);
5832 ok(!memcmp(name
->FileName
, L
"\\winetest", 18), "got %s\n",
5833 debugstr_wn(name
->FileName
, name
->FileNameLength
/ sizeof(WCHAR
)));
5836 client
= CreateFileA( "\\\\.\\mailslot\\winetest", 0, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
5837 ok(client
!= INVALID_HANDLE_VALUE
, "got error %lu\n", GetLastError());
5839 ret
= NtQueryInformationFile( client
, &io
, buffer
, 0, FileNameInformation
);
5840 ok(ret
== STATUS_INFO_LENGTH_MISMATCH
, "got %#lx\n", ret
);
5842 ret
= NtQueryInformationFile( client
, &io
, buffer
, sizeof(buffer
), FileNameInformation
);
5843 todo_wine
ok(ret
== STATUS_INVALID_PARAMETER
|| !ret
/* win8+ */, "got %#lx\n", ret
);
5846 ok(name
->FileNameLength
== 18, "got length %lu\n", name
->FileNameLength
);
5847 ok(!memcmp(name
->FileName
, L
"\\winetest", 18), "got %s\n",
5848 debugstr_wn(name
->FileName
, name
->FileNameLength
/ sizeof(WCHAR
)));
5851 CloseHandle( server
);
5852 CloseHandle( client
);
5854 device
= CreateFileA("\\\\.\\mailslot", 0, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
5855 ok(device
!= INVALID_HANDLE_VALUE
, "got error %lu\n", GetLastError());
5857 ret
= NtQueryInformationFile( device
, &io
, buffer
, 0, FileNameInformation
);
5858 ok(ret
== STATUS_INFO_LENGTH_MISMATCH
, "got %#lx\n", ret
);
5860 ret
= NtQueryInformationFile( device
, &io
, buffer
, sizeof(buffer
), FileNameInformation
);
5861 todo_wine
ok(ret
== STATUS_INVALID_PARAMETER
, "got %#lx\n", ret
);
5863 CloseHandle( device
);
5866 static void test_reparse_points(void)
5868 OBJECT_ATTRIBUTES attr
;
5872 UNICODE_STRING nameW
;
5873 unsigned char reparse_data
[1];
5875 pRtlInitUnicodeString( &nameW
, L
"\\??\\C:\\" );
5876 InitializeObjectAttributes( &attr
, &nameW
, 0, NULL
, NULL
);
5878 status
= pNtOpenFile( &handle
, READ_CONTROL
, &attr
, &io
, 0, 0 );
5879 ok( !status
, "open %s failed %#lx\n", wine_dbgstr_w(nameW
.Buffer
), status
);
5881 status
= pNtFsControlFile( handle
, NULL
, NULL
, NULL
, &io
, FSCTL_GET_REPARSE_POINT
, NULL
, 0, NULL
, 0 );
5882 ok( status
== STATUS_INVALID_USER_BUFFER
, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER
, status
);
5884 status
= pNtFsControlFile( handle
, NULL
, NULL
, NULL
, &io
, FSCTL_GET_REPARSE_POINT
, NULL
, 0, reparse_data
, 0 );
5885 ok( status
== STATUS_INVALID_USER_BUFFER
, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER
, status
);
5887 /* a volume cannot be a reparse point by definition */
5888 status
= pNtFsControlFile( handle
, NULL
, NULL
, NULL
, &io
, FSCTL_GET_REPARSE_POINT
, NULL
, 0, reparse_data
, 1 );
5889 ok( status
== STATUS_NOT_A_REPARSE_POINT
, "expected %#lx, got %#lx\n", STATUS_NOT_A_REPARSE_POINT
, status
);
5891 CloseHandle( handle
);
5896 HMODULE hkernel32
= GetModuleHandleA("kernel32.dll");
5897 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
5900 skip("not running on NT, skipping test\n");
5904 pGetVolumePathNameW
= (void *)GetProcAddress(hkernel32
, "GetVolumePathNameW");
5905 pGetSystemWow64DirectoryW
= (void *)GetProcAddress(hkernel32
, "GetSystemWow64DirectoryW");
5907 pRtlFreeUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlFreeUnicodeString");
5908 pRtlInitUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlInitUnicodeString");
5909 pRtlDosPathNameToNtPathName_U
= (void *)GetProcAddress(hntdll
, "RtlDosPathNameToNtPathName_U");
5910 pRtlWow64EnableFsRedirectionEx
= (void *)GetProcAddress(hntdll
, "RtlWow64EnableFsRedirectionEx");
5911 pNtCreateMailslotFile
= (void *)GetProcAddress(hntdll
, "NtCreateMailslotFile");
5912 pNtCreateFile
= (void *)GetProcAddress(hntdll
, "NtCreateFile");
5913 pNtOpenFile
= (void *)GetProcAddress(hntdll
, "NtOpenFile");
5914 pNtDeleteFile
= (void *)GetProcAddress(hntdll
, "NtDeleteFile");
5915 pNtReadFile
= (void *)GetProcAddress(hntdll
, "NtReadFile");
5916 pNtWriteFile
= (void *)GetProcAddress(hntdll
, "NtWriteFile");
5917 pNtCancelIoFile
= (void *)GetProcAddress(hntdll
, "NtCancelIoFile");
5918 pNtCancelIoFileEx
= (void *)GetProcAddress(hntdll
, "NtCancelIoFileEx");
5919 pNtClose
= (void *)GetProcAddress(hntdll
, "NtClose");
5920 pNtFsControlFile
= (void *)GetProcAddress(hntdll
, "NtFsControlFile");
5921 pNtCreateIoCompletion
= (void *)GetProcAddress(hntdll
, "NtCreateIoCompletion");
5922 pNtOpenIoCompletion
= (void *)GetProcAddress(hntdll
, "NtOpenIoCompletion");
5923 pNtQueryIoCompletion
= (void *)GetProcAddress(hntdll
, "NtQueryIoCompletion");
5924 pNtRemoveIoCompletion
= (void *)GetProcAddress(hntdll
, "NtRemoveIoCompletion");
5925 pNtRemoveIoCompletionEx
= (void *)GetProcAddress(hntdll
, "NtRemoveIoCompletionEx");
5926 pNtSetIoCompletion
= (void *)GetProcAddress(hntdll
, "NtSetIoCompletion");
5927 pNtSetInformationFile
= (void *)GetProcAddress(hntdll
, "NtSetInformationFile");
5928 pNtQueryAttributesFile
= (void *)GetProcAddress(hntdll
, "NtQueryAttributesFile");
5929 pNtQueryInformationFile
= (void *)GetProcAddress(hntdll
, "NtQueryInformationFile");
5930 pNtQueryDirectoryFile
= (void *)GetProcAddress(hntdll
, "NtQueryDirectoryFile");
5931 pNtQueryVolumeInformationFile
= (void *)GetProcAddress(hntdll
, "NtQueryVolumeInformationFile");
5932 pNtQueryFullAttributesFile
= (void *)GetProcAddress(hntdll
, "NtQueryFullAttributesFile");
5933 pNtFlushBuffersFile
= (void *)GetProcAddress(hntdll
, "NtFlushBuffersFile");
5934 pNtQueryEaFile
= (void *)GetProcAddress(hntdll
, "NtQueryEaFile");
5937 test_NtCreateFile();
5944 test_set_io_completion();
5945 test_file_io_completion();
5946 test_file_basic_information();
5947 test_file_all_information();
5948 test_file_both_information();
5949 test_file_name_information();
5950 test_file_full_size_information();
5951 test_file_all_name_information();
5952 test_file_rename_information(FileRenameInformation
);
5953 test_file_rename_information(FileRenameInformationEx
);
5954 test_file_rename_information_ex();
5955 test_file_link_information(FileLinkInformation
);
5956 test_file_link_information(FileLinkInformationEx
);
5957 test_file_link_information_ex();
5958 test_file_disposition_information();
5959 test_file_completion_information();
5960 test_file_id_information();
5961 test_file_access_information();
5962 test_file_attribute_tag_information();
5963 test_file_stat_information();
5964 test_dotfile_file_attributes();
5966 test_file_readonly_access();
5967 test_query_volume_information_file();
5968 test_query_attribute_information_file();
5971 test_flush_buffers_file();
5972 test_mailslot_name();
5973 test_reparse_points();