36ca9fc0cfd28a57df088378e5cc4f15dfe7d297
[reactos.git] / modules / rostests / winetests / ntdll / file.c
1 /* Unit test suite for Ntdll file functions
2 *
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2011 Dmitry Timoshkov
7 *
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.
12 *
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.
17 *
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
21 *
22 * NOTES
23 * We use function pointers here as there is no import library for NTDLL on
24 * windows.
25 */
26
27 #include "ntdll_test.h"
28
29 /* FIXME */
30 typedef struct _REPARSE_DATA_BUFFER {
31 ULONG ReparseTag;
32 USHORT ReparseDataLength;
33 USHORT Reserved;
34 _ANONYMOUS_UNION union {
35 struct {
36 USHORT SubstituteNameOffset;
37 USHORT SubstituteNameLength;
38 USHORT PrintNameOffset;
39 USHORT PrintNameLength;
40 ULONG Flags;
41 WCHAR PathBuffer[1];
42 } SymbolicLinkReparseBuffer;
43 struct {
44 USHORT SubstituteNameOffset;
45 USHORT SubstituteNameLength;
46 USHORT PrintNameOffset;
47 USHORT PrintNameLength;
48 WCHAR PathBuffer[1];
49 } MountPointReparseBuffer;
50 struct {
51 UCHAR DataBuffer[1];
52 } GenericReparseBuffer;
53 } DUMMYUNIONNAME;
54 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
55
56 #ifndef IO_COMPLETION_ALL_ACCESS
57 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
58 #endif
59
60 static BOOL (WINAPI * pGetVolumePathNameW)(LPCWSTR, LPWSTR, DWORD);
61 static UINT (WINAPI *pGetSystemWow64DirectoryW)( LPWSTR, UINT );
62
63 static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
64 static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
65 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
66 static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
67
68 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
69 ULONG, ULONG, ULONG, PLARGE_INTEGER );
70 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
71 static NTSTATUS (WINAPI *pNtOpenFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
72 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
73 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
74 PIO_APC_ROUTINE apc, void* apc_user,
75 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
76 PLARGE_INTEGER offset, PULONG key);
77 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
78 PIO_APC_ROUTINE apc, void* apc_user,
79 PIO_STATUS_BLOCK io_status,
80 const void* buffer, ULONG length,
81 PLARGE_INTEGER offset, PULONG key);
82 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
83 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
84 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
85 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);
86
87 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
88 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
89 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
90 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
91 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
92 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
93 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
94 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
95 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
96 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
97 static NTSTATUS (WINAPI *pNtQueryFullAttributesFile)(const OBJECT_ATTRIBUTES*, FILE_NETWORK_OPEN_INFORMATION*);
98 static NTSTATUS (WINAPI *pNtFlushBuffersFile)(HANDLE, IO_STATUS_BLOCK*);
99 static NTSTATUS (WINAPI *pNtQueryEaFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,BOOLEAN,PVOID,ULONG,PULONG,BOOLEAN);
100
101 static inline BOOL is_signaled( HANDLE obj )
102 {
103 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
104 }
105
106 #define TEST_BUF_LEN 3
107
108 static HANDLE create_temp_file( ULONG flags )
109 {
110 char path[MAX_PATH], buffer[MAX_PATH];
111 HANDLE handle;
112
113 GetTempPathA( MAX_PATH, path );
114 GetTempFileNameA( path, "foo", 0, buffer );
115 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
116 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
117 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
118 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
119 }
120
121 #define CVALUE_FIRST 0xfffabbcc
122 #define CKEY_FIRST 0x1030341
123 #define CKEY_SECOND 0x132E46
124
125 static ULONG_PTR completionKey;
126 static IO_STATUS_BLOCK ioSb;
127 static ULONG_PTR completionValue;
128
129 static ULONG get_pending_msgs(HANDLE h)
130 {
131 NTSTATUS res;
132 ULONG a, req;
133
134 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
135 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
136 if (res != STATUS_SUCCESS) return -1;
137 ok( req == sizeof(a), "Unexpected response size: %x\n", req );
138 return a;
139 }
140
141 static BOOL get_msg(HANDLE h)
142 {
143 LARGE_INTEGER timeout = {{-10000000*3}};
144 DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
145 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
146 if (res != STATUS_SUCCESS)
147 {
148 completionKey = completionValue = 0;
149 memset(&ioSb, 0, sizeof(ioSb));
150 return FALSE;
151 }
152 return TRUE;
153 }
154
155
156 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
157 {
158 int *count = arg;
159
160 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
161 iosb, U(*iosb).Status, iosb->Information );
162 (*count)++;
163 ok( !reserved, "reserved is not 0: %x\n", reserved );
164 }
165
166 static void create_file_test(void)
167 {
168 static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0};
169 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
170 '\\','f','a','i','l','i','n','g',0};
171 static const WCHAR systemrootExplorerW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
172 '\\','e','x','p','l','o','r','e','r','.','e','x','e',0};
173 static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
174 static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
175 static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
176 static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
177 static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
178 static const char testdata[] = "Hello World";
179 static const WCHAR sepW[] = {'\\',0};
180 FILE_NETWORK_OPEN_INFORMATION info;
181 NTSTATUS status;
182 HANDLE dir, file;
183 WCHAR path[MAX_PATH], temp[MAX_PATH];
184 OBJECT_ATTRIBUTES attr;
185 IO_STATUS_BLOCK io;
186 UNICODE_STRING nameW;
187 LARGE_INTEGER offset;
188 char buf[32];
189 DWORD ret;
190
191 GetCurrentDirectoryW( MAX_PATH, path );
192 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
193 attr.Length = sizeof(attr);
194 attr.RootDirectory = 0;
195 attr.ObjectName = &nameW;
196 attr.Attributes = OBJ_CASE_INSENSITIVE;
197 attr.SecurityDescriptor = NULL;
198 attr.SecurityQualityOfService = NULL;
199
200 /* try various open modes and options on directories */
201 status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0,
202 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
203 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
204
205 U(io).Status = 0xdeadbeef;
206 offset.QuadPart = 0;
207 status = pNtReadFile( dir, NULL, NULL, NULL, &io, buf, sizeof(buf), &offset, NULL );
208 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtReadFile error %08x\n", status );
209 if (status == STATUS_PENDING)
210 {
211 ret = WaitForSingleObject( dir, 1000 );
212 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
213 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
214 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
215 }
216
217 U(io).Status = 0xdeadbeef;
218 offset.QuadPart = 0;
219 status = pNtWriteFile( dir, NULL, NULL, NULL, &io, testdata, sizeof(testdata), &offset, NULL);
220 todo_wine
221 ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtWriteFile error %08x\n", status );
222 if (status == STATUS_PENDING)
223 {
224 ret = WaitForSingleObject( dir, 1000 );
225 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
226 ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
227 "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
228 }
229
230 CloseHandle( dir );
231
232 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
233 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
234 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
235 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
236
237 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
238 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
239 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
240 CloseHandle( dir );
241
242 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
243 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
244 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
245
246 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
247 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
248 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
249
250 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
251 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
252 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
253
254 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
255 FILE_OPEN, 0, NULL, 0 );
256 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
257 CloseHandle( dir );
258
259 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
260 FILE_CREATE, 0, NULL, 0 );
261 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
262 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
263
264 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
265 FILE_OPEN_IF, 0, NULL, 0 );
266 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
267 CloseHandle( dir );
268
269 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
270 FILE_SUPERSEDE, 0, NULL, 0 );
271 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
272 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
273
274 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
275 FILE_OVERWRITE, 0, NULL, 0 );
276 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
277 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
278
279 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
280 FILE_OVERWRITE_IF, 0, NULL, 0 );
281 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
282 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
283
284 pRtlFreeUnicodeString( &nameW );
285
286 pRtlInitUnicodeString( &nameW, systemrootW );
287 attr.Length = sizeof(attr);
288 attr.RootDirectory = NULL;
289 attr.ObjectName = &nameW;
290 attr.Attributes = OBJ_CASE_INSENSITIVE;
291 attr.SecurityDescriptor = NULL;
292 attr.SecurityQualityOfService = NULL;
293 dir = NULL;
294 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
295 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
296 todo_wine
297 ok( status == STATUS_INVALID_PARAMETER,
298 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
299
300 /* Invalid chars in file/dirnames */
301 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
302 attr.ObjectName = &nameW;
303 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
304 FILE_SHARE_READ, FILE_CREATE,
305 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
306 ok(status == STATUS_OBJECT_NAME_INVALID,
307 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
308
309 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
310 0, FILE_CREATE,
311 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
312 ok(status == STATUS_OBJECT_NAME_INVALID,
313 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
314 pRtlFreeUnicodeString(&nameW);
315
316 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
317 attr.ObjectName = &nameW;
318 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
319 FILE_SHARE_READ, FILE_CREATE,
320 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
321 ok(status == STATUS_OBJECT_NAME_INVALID,
322 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
323
324 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
325 0, FILE_CREATE,
326 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
327 ok(status == STATUS_OBJECT_NAME_INVALID,
328 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
329 pRtlFreeUnicodeString(&nameW);
330
331 pRtlInitUnicodeString( &nameW, pathInvalidNtW );
332 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
333 FILE_SHARE_READ, FILE_CREATE,
334 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
335 ok( status == STATUS_OBJECT_NAME_INVALID,
336 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
337
338 status = pNtQueryFullAttributesFile( &attr, &info );
339 todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
340 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
341
342 pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
343 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
344 FILE_SHARE_READ, FILE_CREATE,
345 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
346 ok( status == STATUS_OBJECT_NAME_INVALID,
347 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
348
349 status = pNtQueryFullAttributesFile( &attr, &info );
350 ok( status == STATUS_OBJECT_NAME_INVALID,
351 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
352
353 pRtlInitUnicodeString( &nameW, pathInvalidDosW );
354 status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
355 FILE_SHARE_READ, FILE_CREATE,
356 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
357 ok( status == STATUS_OBJECT_NAME_INVALID,
358 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
359
360 status = pNtQueryFullAttributesFile( &attr, &info );
361 ok( status == STATUS_OBJECT_NAME_INVALID,
362 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
363
364 GetWindowsDirectoryW( path, MAX_PATH );
365 path[2] = 0;
366 ok( QueryDosDeviceW( path, temp, MAX_PATH ),
367 "QueryDosDeviceW failed with error %u\n", GetLastError() );
368 lstrcatW( temp, sepW );
369 lstrcatW( temp, path+3 );
370 lstrcatW( temp, sepW );
371 lstrcatW( temp, notepadW );
372
373 pRtlInitUnicodeString( &nameW, temp );
374 status = pNtQueryFullAttributesFile( &attr, &info );
375 ok( status == STATUS_SUCCESS,
376 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
377
378 pRtlInitUnicodeString( &nameW, systemrootExplorerW );
379 status = pNtQueryFullAttributesFile( &attr, &info );
380 ok( status == STATUS_SUCCESS,
381 "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
382 }
383
384 static void open_file_test(void)
385 {
386 static const char testdata[] = "Hello World";
387 static WCHAR fooW[] = {'f','o','o',0};
388 NTSTATUS status;
389 HANDLE dir, root, handle, file;
390 WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
391 BYTE data[1024];
392 OBJECT_ATTRIBUTES attr;
393 IO_STATUS_BLOCK io;
394 UNICODE_STRING nameW;
395 UINT i, len;
396 BOOL ret, restart = TRUE;
397 DWORD numbytes;
398
399 len = GetWindowsDirectoryW( path, MAX_PATH );
400 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
401 attr.Length = sizeof(attr);
402 attr.RootDirectory = 0;
403 attr.ObjectName = &nameW;
404 attr.Attributes = OBJ_CASE_INSENSITIVE;
405 attr.SecurityDescriptor = NULL;
406 attr.SecurityQualityOfService = NULL;
407 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
408 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
409 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
410 pRtlFreeUnicodeString( &nameW );
411
412 path[3] = 0; /* root of the drive */
413 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
414 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
415 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
416 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
417 pRtlFreeUnicodeString( &nameW );
418
419 /* test opening system dir with RootDirectory set to windows dir */
420 GetSystemDirectoryW( path, MAX_PATH );
421 while (path[len] == '\\') len++;
422 nameW.Buffer = path + len;
423 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
424 attr.RootDirectory = dir;
425 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
426 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
427 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
428 CloseHandle( handle );
429
430 /* try uppercase name */
431 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
432 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
433 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
434 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
435 CloseHandle( handle );
436
437 /* try with leading backslash */
438 nameW.Buffer--;
439 nameW.Length += sizeof(WCHAR);
440 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
441 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
442 ok( status == STATUS_INVALID_PARAMETER ||
443 status == STATUS_OBJECT_NAME_INVALID ||
444 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
445 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
446 if (!status) CloseHandle( handle );
447
448 /* try with empty name */
449 nameW.Length = 0;
450 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
451 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
452 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
453 CloseHandle( handle );
454
455 /* try open by file id */
456
457 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
458 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
459 {
460 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
461
462 restart = FALSE;
463
464 if (!info->FileId.QuadPart) continue;
465
466 nameW.Buffer = (WCHAR *)&info->FileId;
467 nameW.Length = sizeof(info->FileId);
468 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
469 attr.RootDirectory = dir;
470 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
471 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
472 FILE_SHARE_READ,
473 FILE_OPEN_BY_FILE_ID |
474 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
475 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
476 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
477 if (status == STATUS_NOT_IMPLEMENTED)
478 {
479 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
480 break;
481 }
482 if (status == STATUS_SHARING_VIOLATION)
483 trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
484 if (!status)
485 {
486 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
487
488 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
489 {
490 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
491
492 /* check that it's the same file/directory */
493
494 /* don't check the size for directories */
495 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
496 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
497 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
498
499 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
500 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
501 }
502 CloseHandle( handle );
503
504 /* try same thing from drive root */
505 attr.RootDirectory = root;
506 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
507 FILE_SHARE_READ|FILE_SHARE_WRITE,
508 FILE_OPEN_BY_FILE_ID |
509 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
510 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
511 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
512 if (!status) CloseHandle( handle );
513 }
514 }
515
516 CloseHandle( dir );
517 CloseHandle( root );
518
519 GetTempPathW( MAX_PATH, path );
520 GetTempFileNameW( path, fooW, 0, tmpfile );
521 pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
522
523 file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
524 ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
525 numbytes = 0xdeadbeef;
526 ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
527 ok( ret, "WriteFile failed with error %u\n", GetLastError() );
528 ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
529 CloseHandle( file );
530
531 attr.Length = sizeof(attr);
532 attr.RootDirectory = 0;
533 attr.ObjectName = &nameW;
534 attr.Attributes = OBJ_CASE_INSENSITIVE;
535 attr.SecurityDescriptor = NULL;
536 attr.SecurityQualityOfService = NULL;
537 status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
538 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
539 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
540 pRtlFreeUnicodeString( &nameW );
541
542 numbytes = 0xdeadbeef;
543 memset( data, 0, sizeof(data) );
544 ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
545 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
546 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
547 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
548
549 nameW.Length = sizeof(fooW) - sizeof(WCHAR);
550 nameW.Buffer = fooW;
551 attr.RootDirectory = file;
552 attr.ObjectName = &nameW;
553 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
554 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
555 ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
556 "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
557
558 nameW.Length = 0;
559 nameW.Buffer = NULL;
560 attr.RootDirectory = file;
561 attr.ObjectName = &nameW;
562 status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
563 FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
564 ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
565
566 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
567 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
568 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
569 ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
570
571 numbytes = 0xdeadbeef;
572 memset( data, 0, sizeof(data) );
573 ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
574 ok( ret, "ReadFile failed with error %u\n", GetLastError() );
575 ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
576 ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
577
578 numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
579 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
580 numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
581 ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
582
583 CloseHandle( file );
584 CloseHandle( root );
585 DeleteFileW( tmpfile );
586 }
587
588 static void delete_file_test(void)
589 {
590 NTSTATUS ret;
591 OBJECT_ATTRIBUTES attr;
592 UNICODE_STRING nameW;
593 WCHAR pathW[MAX_PATH];
594 WCHAR pathsubW[MAX_PATH];
595 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
596 static const WCHAR subdirW[] = {'\\','s','u','b',0};
597
598 ret = GetTempPathW(MAX_PATH, pathW);
599 if (!ret)
600 {
601 ok(0, "couldn't get temp dir\n");
602 return;
603 }
604 if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
605 {
606 ok(0, "MAX_PATH exceeded in constructing paths\n");
607 return;
608 }
609
610 lstrcatW(pathW, testdirW);
611 lstrcpyW(pathsubW, pathW);
612 lstrcatW(pathsubW, subdirW);
613
614 ret = CreateDirectoryW(pathW, NULL);
615 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
616 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
617 {
618 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
619 return;
620 }
621
622 attr.Length = sizeof(attr);
623 attr.RootDirectory = 0;
624 attr.Attributes = OBJ_CASE_INSENSITIVE;
625 attr.ObjectName = &nameW;
626 attr.SecurityDescriptor = NULL;
627 attr.SecurityQualityOfService = NULL;
628
629 /* test NtDeleteFile on an empty directory */
630 ret = pNtDeleteFile(&attr);
631 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
632 ret = RemoveDirectoryW(pathW);
633 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
634
635 /* test NtDeleteFile on a non-empty directory */
636 ret = CreateDirectoryW(pathW, NULL);
637 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
638 ret = CreateDirectoryW(pathsubW, NULL);
639 ok(ret == TRUE, "couldn't create directory subdir\n");
640 ret = pNtDeleteFile(&attr);
641 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
642 ret = RemoveDirectoryW(pathsubW);
643 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
644 ret = RemoveDirectoryW(pathW);
645 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
646
647 pRtlFreeUnicodeString( &nameW );
648 }
649
650 static void read_file_test(void)
651 {
652 const char text[] = "foobar";
653 HANDLE handle;
654 IO_STATUS_BLOCK iosb;
655 NTSTATUS status;
656 int apc_count = 0;
657 char buffer[128];
658 LARGE_INTEGER offset;
659 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
660
661 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
662 apc_count = 0;
663 U(iosb).Status = 0xdeadbabe;
664 iosb.Information = 0xdeadbeef;
665 offset.QuadPart = 0;
666 ResetEvent( event );
667 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
668 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
669 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
670 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
671 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
672 ok( is_signaled( event ), "event is not signaled\n" );
673 ok( !apc_count, "apc was called\n" );
674 SleepEx( 1, TRUE ); /* alertable sleep */
675 ok( apc_count == 1, "apc was not called\n" );
676
677 apc_count = 0;
678 U(iosb).Status = 0xdeadbabe;
679 iosb.Information = 0xdeadbeef;
680 offset.QuadPart = 0;
681 ResetEvent( event );
682 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
683 ok( status == STATUS_SUCCESS ||
684 status == STATUS_PENDING, /* vista */
685 "wrong status %x\n", status );
686 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
687 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
688 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
689 ok( is_signaled( event ), "event is not signaled\n" );
690 ok( !apc_count, "apc was called\n" );
691 SleepEx( 1, TRUE ); /* alertable sleep */
692 ok( apc_count == 1, "apc was not called\n" );
693
694 /* read beyond eof */
695 apc_count = 0;
696 U(iosb).Status = 0xdeadbabe;
697 iosb.Information = 0xdeadbeef;
698 offset.QuadPart = strlen(text) + 2;
699 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
700 ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
701 if (status == STATUS_PENDING) /* vista */
702 {
703 WaitForSingleObject( event, 1000 );
704 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
705 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
706 ok( is_signaled( event ), "event is not signaled\n" );
707 ok( !apc_count, "apc was called\n" );
708 SleepEx( 1, TRUE ); /* alertable sleep */
709 ok( apc_count == 1, "apc was not called\n" );
710 }
711 CloseHandle( handle );
712
713 /* now a non-overlapped file */
714 if (!(handle = create_temp_file(0))) return;
715 apc_count = 0;
716 U(iosb).Status = 0xdeadbabe;
717 iosb.Information = 0xdeadbeef;
718 offset.QuadPart = 0;
719 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
720 ok( status == STATUS_END_OF_FILE ||
721 status == STATUS_SUCCESS ||
722 status == STATUS_PENDING, /* vista */
723 "wrong status %x\n", status );
724 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
725 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
726 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
727 ok( is_signaled( event ), "event is not signaled\n" );
728 ok( !apc_count, "apc was called\n" );
729 SleepEx( 1, TRUE ); /* alertable sleep */
730 ok( apc_count == 1, "apc was not called\n" );
731
732 apc_count = 0;
733 U(iosb).Status = 0xdeadbabe;
734 iosb.Information = 0xdeadbeef;
735 offset.QuadPart = 0;
736 ResetEvent( event );
737 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
738 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
739 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
740 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
741 ok( is_signaled( event ), "event is not signaled\n" );
742 ok( !apc_count, "apc was called\n" );
743 SleepEx( 1, TRUE ); /* alertable sleep */
744 todo_wine ok( !apc_count, "apc was called\n" );
745
746 /* read beyond eof */
747 apc_count = 0;
748 U(iosb).Status = 0xdeadbabe;
749 iosb.Information = 0xdeadbeef;
750 offset.QuadPart = strlen(text) + 2;
751 ResetEvent( event );
752 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
753 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
754 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
755 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
756 ok( is_signaled( event ), "event is not signaled\n" );
757 ok( !apc_count, "apc was called\n" );
758 SleepEx( 1, TRUE ); /* alertable sleep */
759 ok( !apc_count, "apc was called\n" );
760
761 CloseHandle( handle );
762
763 CloseHandle( event );
764 }
765
766 static void append_file_test(void)
767 {
768 static const char text[6] = "foobar";
769 HANDLE handle;
770 NTSTATUS status;
771 IO_STATUS_BLOCK iosb;
772 LARGE_INTEGER offset;
773 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
774 DWORD ret;
775
776 GetTempPathA( MAX_PATH, path );
777 GetTempFileNameA( path, "foo", 0, buffer );
778
779 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
780 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
781
782 U(iosb).Status = -1;
783 iosb.Information = -1;
784 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
785 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
786 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
787 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
788
789 CloseHandle(handle);
790
791 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
792 It matches the O_WRONLY|O_APPEND open() posix behavior */
793 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
794 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
795
796 U(iosb).Status = -1;
797 iosb.Information = -1;
798 offset.QuadPart = 1;
799 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
800 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
801 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
802 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
803
804 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
805 ok(ret == 4, "expected 4, got %u\n", ret);
806
807 U(iosb).Status = -1;
808 iosb.Information = -1;
809 offset.QuadPart = 3;
810 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
811 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
812 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
813 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
814
815 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
816 ok(ret == 6, "expected 6, got %u\n", ret);
817
818 CloseHandle(handle);
819
820 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
821 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
822
823 memset(buf, 0, sizeof(buf));
824 U(iosb).Status = -1;
825 iosb.Information = -1;
826 offset.QuadPart = 0;
827 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
828 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
829 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
830 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
831 buf[6] = 0;
832 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
833
834 U(iosb).Status = -1;
835 iosb.Information = -1;
836 offset.QuadPart = 0;
837 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
838 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
839 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
840 ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
841
842 memset(buf, 0, sizeof(buf));
843 U(iosb).Status = -1;
844 iosb.Information = -1;
845 offset.QuadPart = 0;
846 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
847 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
848 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
849 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
850 buf[6] = 0;
851 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
852
853 CloseHandle(handle);
854 DeleteFileA(buffer);
855 }
856
857 static void nt_mailslot_test(void)
858 {
859 HANDLE hslot;
860 ACCESS_MASK DesiredAccess;
861 OBJECT_ATTRIBUTES attr;
862
863 ULONG CreateOptions;
864 ULONG MailslotQuota;
865 ULONG MaxMessageSize;
866 LARGE_INTEGER TimeOut;
867 IO_STATUS_BLOCK IoStatusBlock;
868 NTSTATUS rc;
869 UNICODE_STRING str;
870 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
871 'R',':','\\','F','R','E','D','\0' };
872
873 TimeOut.QuadPart = -1;
874
875 pRtlInitUnicodeString(&str, buffer1);
876 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
877 CreateOptions = MailslotQuota = MaxMessageSize = 0;
878 DesiredAccess = GENERIC_READ;
879
880 /*
881 * Check for NULL pointer handling
882 */
883 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
884 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
885 &TimeOut);
886 ok( rc == STATUS_ACCESS_VIOLATION ||
887 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
888 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
889
890 /*
891 * Test to see if the Timeout can be NULL
892 */
893 hslot = (HANDLE)0xdeadbeef;
894 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
895 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
896 NULL);
897 ok( rc == STATUS_SUCCESS ||
898 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
899 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
900 ok( hslot != 0, "Handle is invalid\n");
901
902 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
903
904 /*
905 * Test a valid call
906 */
907 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
908 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
909 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
910 &TimeOut);
911 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
912 ok( hslot != 0, "Handle is invalid\n");
913
914 rc = pNtClose(hslot);
915 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
916 }
917
918 static void test_iocp_setcompletion(HANDLE h)
919 {
920 NTSTATUS res;
921 ULONG count;
922 SIZE_T size = 3;
923
924 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
925
926 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
927 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
928
929 count = get_pending_msgs(h);
930 ok( count == 1, "Unexpected msg count: %d\n", count );
931
932 if (get_msg(h))
933 {
934 ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
935 ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
936 ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
937 ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
938 }
939
940 count = get_pending_msgs(h);
941 ok( !count, "Unexpected msg count: %d\n", count );
942 }
943
944 static void test_iocp_fileio(HANDLE h)
945 {
946 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
947
948 IO_STATUS_BLOCK iosb;
949 FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
950 HANDLE hPipeSrv, hPipeClt;
951 NTSTATUS res;
952
953 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
954 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
955 if (hPipeSrv != INVALID_HANDLE_VALUE )
956 {
957 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
958 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
959 if (hPipeClt != INVALID_HANDLE_VALUE)
960 {
961 U(iosb).Status = 0xdeadbeef;
962 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
963 ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
964 ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
965 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
966 CloseHandle(hPipeClt);
967 }
968 CloseHandle( hPipeSrv );
969 }
970
971 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
972 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
973 if (hPipeSrv == INVALID_HANDLE_VALUE )
974 return;
975
976 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
977 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
978 if (hPipeClt != INVALID_HANDLE_VALUE)
979 {
980 OVERLAPPED o = {0,};
981 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
982 DWORD read;
983 long count;
984
985 U(iosb).Status = 0xdeadbeef;
986 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
987 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
988 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
989
990 memset( send_buf, 0, TEST_BUF_LEN );
991 memset( recv_buf, 0xde, TEST_BUF_LEN );
992 count = get_pending_msgs(h);
993 ok( !count, "Unexpected msg count: %ld\n", count );
994 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
995 count = get_pending_msgs(h);
996 ok( !count, "Unexpected msg count: %ld\n", count );
997 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
998
999 if (get_msg(h))
1000 {
1001 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1002 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1003 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1004 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1005 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1006 }
1007 count = get_pending_msgs(h);
1008 ok( !count, "Unexpected msg count: %ld\n", count );
1009
1010 memset( send_buf, 0, TEST_BUF_LEN );
1011 memset( recv_buf, 0xde, TEST_BUF_LEN );
1012 WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1013 count = get_pending_msgs(h);
1014 ok( !count, "Unexpected msg count: %ld\n", count );
1015 ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1016 count = get_pending_msgs(h);
1017 ok( count == 1, "Unexpected msg count: %ld\n", count );
1018 if (get_msg(h))
1019 {
1020 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1021 ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1022 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1023 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1024 ok( !memcmp( send_buf, recv_buf, 2 ), "Receive buffer (%x %x) did not match send buffer (%x %x)\n", recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
1025 }
1026
1027 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1028 CloseHandle( hPipeSrv );
1029 count = get_pending_msgs(h);
1030 ok( count == 1, "Unexpected msg count: %ld\n", count );
1031 if (get_msg(h))
1032 {
1033 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1034 ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1035 /* wine sends wrong status here */
1036 ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1037 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1038 }
1039 }
1040
1041 CloseHandle( hPipeClt );
1042
1043 /* test associating a completion port with a handle after an async is queued */
1044 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1045 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1046 if (hPipeSrv == INVALID_HANDLE_VALUE )
1047 return;
1048 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1049 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1050 if (hPipeClt != INVALID_HANDLE_VALUE)
1051 {
1052 OVERLAPPED o = {0,};
1053 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1054 int apc_count = 0;
1055 DWORD read;
1056 long count;
1057
1058 memset( send_buf, 0, TEST_BUF_LEN );
1059 memset( recv_buf, 0xde, TEST_BUF_LEN );
1060 count = get_pending_msgs(h);
1061 ok( !count, "Unexpected msg count: %ld\n", count );
1062 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1063
1064 U(iosb).Status = 0xdeadbeef;
1065 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1066 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1067 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1068 count = get_pending_msgs(h);
1069 ok( !count, "Unexpected msg count: %ld\n", count );
1070
1071 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1072
1073 if (get_msg(h))
1074 {
1075 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1076 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1077 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1078 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1079 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1080 }
1081 count = get_pending_msgs(h);
1082 ok( !count, "Unexpected msg count: %ld\n", count );
1083
1084 /* using APCs on handle with associated completion port is not allowed */
1085 res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1086 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1087 }
1088
1089 CloseHandle( hPipeSrv );
1090 CloseHandle( hPipeClt );
1091
1092 /* test associating a completion port with a handle after an async using APC is queued */
1093 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1094 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1095 if (hPipeSrv == INVALID_HANDLE_VALUE )
1096 return;
1097 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1098 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1099 if (hPipeClt != INVALID_HANDLE_VALUE)
1100 {
1101 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1102 int apc_count = 0;
1103 DWORD read;
1104 long count;
1105
1106 memset( send_buf, 0, TEST_BUF_LEN );
1107 memset( recv_buf, 0xde, TEST_BUF_LEN );
1108 count = get_pending_msgs(h);
1109 ok( !count, "Unexpected msg count: %ld\n", count );
1110
1111 res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1112 ok(res == STATUS_PENDING, "NtReadFile returned %x\n", res);
1113
1114 U(iosb).Status = 0xdeadbeef;
1115 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1116 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1117 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1118 count = get_pending_msgs(h);
1119 ok( !count, "Unexpected msg count: %ld\n", count );
1120
1121 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1122
1123 ok(!apc_count, "apc_count = %u\n", apc_count);
1124 count = get_pending_msgs(h);
1125 ok( !count, "Unexpected msg count: %ld\n", count );
1126
1127 SleepEx(1, TRUE); /* alertable sleep */
1128 ok(apc_count == 1, "apc was not called\n");
1129 count = get_pending_msgs(h);
1130 ok( !count, "Unexpected msg count: %ld\n", count );
1131
1132 /* using APCs on handle with associated completion port is not allowed */
1133 res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1134 ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1135 }
1136
1137 CloseHandle( hPipeSrv );
1138 CloseHandle( hPipeClt );
1139 }
1140
1141 static void test_file_full_size_information(void)
1142 {
1143 IO_STATUS_BLOCK io;
1144 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1145 FILE_FS_SIZE_INFORMATION fsi;
1146 HANDLE h;
1147 NTSTATUS res;
1148
1149 if(!(h = create_temp_file(0))) return ;
1150
1151 memset(&ffsi,0,sizeof(ffsi));
1152 memset(&fsi,0,sizeof(fsi));
1153
1154 /* Assume No Quota Settings configured on Wine Testbot */
1155 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1156 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1157 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1158 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1159
1160 /* Test for FileFsSizeInformation */
1161 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1162 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1163 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1164 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1165 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1166 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1167
1168 /* Assume file system is NTFS */
1169 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1170 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1171
1172 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1173 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1174 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1175 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1176 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1177 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1178 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1179 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1180 wine_dbgstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1181 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1182 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1183 wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1184 wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1185 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1186 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1187 wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1188 wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1189
1190 /* Assume file system is NTFS */
1191 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1192 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1193
1194 CloseHandle( h );
1195 }
1196
1197 static void test_file_basic_information(void)
1198 {
1199 IO_STATUS_BLOCK io;
1200 FILE_BASIC_INFORMATION fbi;
1201 HANDLE h;
1202 int res;
1203 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1204
1205 if (!(h = create_temp_file(0))) return;
1206
1207 /* Check default first */
1208 memset(&fbi, 0, sizeof(fbi));
1209 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1210 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1211 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1212 "attribute %x not expected\n", fbi.FileAttributes );
1213
1214 /* Then SYSTEM */
1215 /* Clear fbi to avoid setting times */
1216 memset(&fbi, 0, sizeof(fbi));
1217 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1218 U(io).Status = 0xdeadbeef;
1219 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1220 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1221 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1222
1223 memset(&fbi, 0, sizeof(fbi));
1224 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1225 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1226 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fbi.FileAttributes );
1227
1228 /* Then HIDDEN */
1229 memset(&fbi, 0, sizeof(fbi));
1230 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1231 U(io).Status = 0xdeadbeef;
1232 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1233 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1234 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1235
1236 memset(&fbi, 0, sizeof(fbi));
1237 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1238 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1239 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fbi.FileAttributes );
1240
1241 /* Check NORMAL last of all (to make sure we can clear attributes) */
1242 memset(&fbi, 0, sizeof(fbi));
1243 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1244 U(io).Status = 0xdeadbeef;
1245 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1246 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1247 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1248
1249 memset(&fbi, 0, sizeof(fbi));
1250 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1251 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1252 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1253
1254 CloseHandle( h );
1255 }
1256
1257 static void test_file_all_information(void)
1258 {
1259 IO_STATUS_BLOCK io;
1260 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1261 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1262 * don't leave enough room there.
1263 */
1264 struct {
1265 FILE_ALL_INFORMATION fai;
1266 WCHAR buf[256];
1267 } fai_buf;
1268 HANDLE h;
1269 int res;
1270 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1271
1272 if (!(h = create_temp_file(0))) return;
1273
1274 /* Check default first */
1275 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1276 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1277 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1278 "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1279
1280 /* Then SYSTEM */
1281 /* Clear fbi to avoid setting times */
1282 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1283 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1284 U(io).Status = 0xdeadbeef;
1285 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1286 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1287 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1288 U(io).Status = 0xdeadbeef;
1289 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1290 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1291 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1292
1293 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1294 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1295 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1296 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
1297
1298 /* Then HIDDEN */
1299 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1300 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1301 U(io).Status = 0xdeadbeef;
1302 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1303 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1304 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1305
1306 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1307 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1308 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1309 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
1310
1311 /* Check NORMAL last of all (to make sure we can clear attributes) */
1312 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1313 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1314 U(io).Status = 0xdeadbeef;
1315 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1316 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1317 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1318
1319 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1320 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1321 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1322 todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not FILE_ATTRIBUTE_NORMAL\n", fai_buf.fai.BasicInformation.FileAttributes );
1323
1324 CloseHandle( h );
1325 }
1326
1327 static void delete_object( WCHAR *path )
1328 {
1329 BOOL ret = DeleteFileW( path );
1330 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1331 "DeleteFileW failed with %u\n", GetLastError() );
1332 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1333 {
1334 ret = RemoveDirectoryW( path );
1335 ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
1336 }
1337 }
1338
1339 static void test_file_rename_information(void)
1340 {
1341 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1342 static const WCHAR fooW[] = {'f','o','o',0};
1343 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1344 FILE_RENAME_INFORMATION *fri;
1345 FILE_NAME_INFORMATION *fni;
1346 BOOL success, fileDeleted;
1347 UNICODE_STRING name_str;
1348 HANDLE handle, handle2;
1349 IO_STATUS_BLOCK io;
1350 NTSTATUS res;
1351
1352 GetTempPathW( MAX_PATH, tmp_path );
1353
1354 /* oldpath is a file, newpath doesn't exist */
1355 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1356 ok( res != 0, "failed to create temp file\n" );
1357 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1358 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1359
1360 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1361 ok( res != 0, "failed to create temp file\n" );
1362 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1363 DeleteFileW( newpath );
1364 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1365 fri->Replace = FALSE;
1366 fri->RootDir = NULL;
1367 fri->FileNameLength = name_str.Length;
1368 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1369 pRtlFreeUnicodeString( &name_str );
1370
1371 U(io).Status = 0xdeadbeef;
1372 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1373 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1374 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1375 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1376 ok( fileDeleted, "file should not exist\n" );
1377 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1378 ok( !fileDeleted, "file should exist\n" );
1379
1380 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1381 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1382 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1383 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1384 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1385 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1386 HeapFree( GetProcessHeap(), 0, fni );
1387
1388 CloseHandle( handle );
1389 HeapFree( GetProcessHeap(), 0, fri );
1390 delete_object( oldpath );
1391 delete_object( newpath );
1392
1393 /* oldpath is a file, newpath is a file, Replace = FALSE */
1394 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1395 ok( res != 0, "failed to create temp file\n" );
1396 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1397 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1398
1399 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1400 ok( res != 0, "failed to create temp file\n" );
1401 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1402 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1403 fri->Replace = FALSE;
1404 fri->RootDir = NULL;
1405 fri->FileNameLength = name_str.Length;
1406 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1407 pRtlFreeUnicodeString( &name_str );
1408
1409 U(io).Status = 0xdeadbeef;
1410 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1411 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1412 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1413 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1414 ok( !fileDeleted, "file should exist\n" );
1415 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1416 ok( !fileDeleted, "file should exist\n" );
1417
1418 CloseHandle( handle );
1419 HeapFree( GetProcessHeap(), 0, fri );
1420 delete_object( oldpath );
1421 delete_object( newpath );
1422
1423 /* oldpath is a file, newpath is a file, Replace = TRUE */
1424 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1425 ok( res != 0, "failed to create temp file\n" );
1426 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1427 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1428
1429 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1430 ok( res != 0, "failed to create temp file\n" );
1431 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1432 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1433 fri->Replace = TRUE;
1434 fri->RootDir = NULL;
1435 fri->FileNameLength = name_str.Length;
1436 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1437 pRtlFreeUnicodeString( &name_str );
1438
1439 U(io).Status = 0xdeadbeef;
1440 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1441 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1442 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1443 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1444 ok( fileDeleted, "file should not exist\n" );
1445 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1446 ok( !fileDeleted, "file should exist\n" );
1447
1448 CloseHandle( handle );
1449 HeapFree( GetProcessHeap(), 0, fri );
1450 delete_object( oldpath );
1451 delete_object( newpath );
1452
1453 /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1454 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1455 ok( res != 0, "failed to create temp file\n" );
1456 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1457 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1458
1459 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1460 ok( res != 0, "failed to create temp file\n" );
1461 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1462 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1463
1464 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1465 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1466 fri->Replace = FALSE;
1467 fri->RootDir = NULL;
1468 fri->FileNameLength = name_str.Length;
1469 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1470 pRtlFreeUnicodeString( &name_str );
1471
1472 U(io).Status = 0xdeadbeef;
1473 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1474 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1475 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1476 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1477 ok( !fileDeleted, "file should exist\n" );
1478 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1479 ok( !fileDeleted, "file should exist\n" );
1480
1481 CloseHandle( handle );
1482 CloseHandle( handle2 );
1483 HeapFree( GetProcessHeap(), 0, fri );
1484 delete_object( oldpath );
1485 delete_object( newpath );
1486
1487 /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1488 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1489 ok( res != 0, "failed to create temp file\n" );
1490 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1491 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1492
1493 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1494 ok( res != 0, "failed to create temp file\n" );
1495 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1496 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1497
1498 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1499 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1500 fri->Replace = TRUE;
1501 fri->RootDir = NULL;
1502 fri->FileNameLength = name_str.Length;
1503 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1504 pRtlFreeUnicodeString( &name_str );
1505
1506 U(io).Status = 0xdeadbeef;
1507 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1508 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1509 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1510 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1511 ok( !fileDeleted, "file should exist\n" );
1512 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1513 ok( !fileDeleted, "file should exist\n" );
1514
1515 CloseHandle( handle );
1516 CloseHandle( handle2 );
1517 HeapFree( GetProcessHeap(), 0, fri );
1518 delete_object( oldpath );
1519 delete_object( newpath );
1520
1521 /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1522 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1523 ok( res != 0, "failed to create temp file\n" );
1524 DeleteFileW( oldpath );
1525 success = CreateDirectoryW( oldpath, NULL );
1526 ok( success != 0, "failed to create temp directory\n" );
1527 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1528 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1529
1530 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1531 ok( res != 0, "failed to create temp file\n" );
1532 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1533 DeleteFileW( newpath );
1534 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1535 fri->Replace = FALSE;
1536 fri->RootDir = NULL;
1537 fri->FileNameLength = name_str.Length;
1538 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1539 pRtlFreeUnicodeString( &name_str );
1540
1541 U(io).Status = 0xdeadbeef;
1542 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1543 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1544 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1545 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1546 ok( fileDeleted, "file should not exist\n" );
1547 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1548 ok( !fileDeleted, "file should exist\n" );
1549
1550 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1551 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1552 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1553 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1554 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1555 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1556 HeapFree( GetProcessHeap(), 0, fni );
1557
1558 CloseHandle( handle );
1559 HeapFree( GetProcessHeap(), 0, fri );
1560 delete_object( oldpath );
1561 delete_object( newpath );
1562
1563 /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1564 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1565 ok( res != 0, "failed to create temp file\n" );
1566 DeleteFileW( oldpath );
1567 success = CreateDirectoryW( oldpath, NULL );
1568 ok( success != 0, "failed to create temp directory\n" );
1569 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1570 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1571
1572 lstrcpyW( newpath, oldpath );
1573 lstrcatW( newpath, foo_txtW );
1574 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1575 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1576
1577 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1578 ok( res != 0, "failed to create temp file\n" );
1579 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1580 DeleteFileW( newpath );
1581 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1582 fri->Replace = FALSE;
1583 fri->RootDir = NULL;
1584 fri->FileNameLength = name_str.Length;
1585 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1586 pRtlFreeUnicodeString( &name_str );
1587
1588 U(io).Status = 0xdeadbeef;
1589 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1590 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1591 todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1592 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1593 todo_wine ok( !fileDeleted, "file should exist\n" );
1594 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1595 todo_wine ok( fileDeleted, "file should not exist\n" );
1596
1597 CloseHandle( handle );
1598 CloseHandle( handle2 );
1599 HeapFree( GetProcessHeap(), 0, fri );
1600 delete_object( oldpath );
1601 if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1602 {
1603 lstrcpyW( oldpath, newpath );
1604 lstrcatW( oldpath, foo_txtW );
1605 delete_object( oldpath );
1606 }
1607 delete_object( newpath );
1608
1609 /* oldpath is a directory, newpath is a file, Replace = FALSE */
1610 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1611 ok( res != 0, "failed to create temp file\n" );
1612 DeleteFileW( oldpath );
1613 success = CreateDirectoryW( oldpath, NULL );
1614 ok( success != 0, "failed to create temp directory\n" );
1615 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1616 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1617
1618 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1619 ok( res != 0, "failed to create temp file\n" );
1620 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1621 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1622 fri->Replace = FALSE;
1623 fri->RootDir = NULL;
1624 fri->FileNameLength = name_str.Length;
1625 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1626 pRtlFreeUnicodeString( &name_str );
1627
1628 U(io).Status = 0xdeadbeef;
1629 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1630 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1631 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1632 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1633 ok( !fileDeleted, "file should exist\n" );
1634 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1635 ok( !fileDeleted, "file should exist\n" );
1636
1637 CloseHandle( handle );
1638 HeapFree( GetProcessHeap(), 0, fri );
1639 delete_object( oldpath );
1640 delete_object( newpath );
1641
1642 /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1643 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1644 ok( res != 0, "failed to create temp file\n" );
1645 DeleteFileW( oldpath );
1646 success = CreateDirectoryW( oldpath, NULL );
1647 ok( success != 0, "failed to create temp directory\n" );
1648 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1649 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1650
1651 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1652 ok( res != 0, "failed to create temp file\n" );
1653 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1654 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1655
1656 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1657 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1658 fri->Replace = FALSE;
1659 fri->RootDir = NULL;
1660 fri->FileNameLength = name_str.Length;
1661 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1662 pRtlFreeUnicodeString( &name_str );
1663
1664 U(io).Status = 0xdeadbeef;
1665 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1666 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1667 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1668 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1669 ok( !fileDeleted, "file should exist\n" );
1670 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1671 ok( !fileDeleted, "file should exist\n" );
1672
1673 CloseHandle( handle );
1674 CloseHandle( handle2 );
1675 HeapFree( GetProcessHeap(), 0, fri );
1676 delete_object( oldpath );
1677 delete_object( newpath );
1678
1679 /* oldpath is a directory, newpath is a file, Replace = TRUE */
1680 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1681 ok( res != 0, "failed to create temp file\n" );
1682 DeleteFileW( oldpath );
1683 success = CreateDirectoryW( oldpath, NULL );
1684 ok( success != 0, "failed to create temp directory\n" );
1685 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1686 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1687
1688 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1689 ok( res != 0, "failed to create temp file\n" );
1690 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1691 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1692 fri->Replace = TRUE;
1693 fri->RootDir = NULL;
1694 fri->FileNameLength = name_str.Length;
1695 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1696 pRtlFreeUnicodeString( &name_str );
1697
1698 U(io).Status = 0xdeadbeef;
1699 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1700 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1701 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1702 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1703 ok( fileDeleted, "file should not exist\n" );
1704 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1705 ok( !fileDeleted, "file should exist\n" );
1706
1707 CloseHandle( handle );
1708 HeapFree( GetProcessHeap(), 0, fri );
1709 delete_object( oldpath );
1710 delete_object( newpath );
1711
1712 /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1713 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1714 ok( res != 0, "failed to create temp file\n" );
1715 DeleteFileW( oldpath );
1716 success = CreateDirectoryW( oldpath, NULL );
1717 ok( success != 0, "failed to create temp directory\n" );
1718 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1719 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1720
1721 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1722 ok( res != 0, "failed to create temp file\n" );
1723 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1724 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1725
1726 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1727 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1728 fri->Replace = TRUE;
1729 fri->RootDir = NULL;
1730 fri->FileNameLength = name_str.Length;
1731 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1732 pRtlFreeUnicodeString( &name_str );
1733
1734 U(io).Status = 0xdeadbeef;
1735 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1736 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1737 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1738 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1739 ok( !fileDeleted, "file should exist\n" );
1740 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1741 ok( !fileDeleted, "file should exist\n" );
1742
1743 CloseHandle( handle );
1744 CloseHandle( handle2 );
1745 HeapFree( GetProcessHeap(), 0, fri );
1746 delete_object( oldpath );
1747 delete_object( newpath );
1748
1749 /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1750 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1751 ok( res != 0, "failed to create temp file\n" );
1752 DeleteFileW( oldpath );
1753 success = CreateDirectoryW( oldpath, NULL );
1754 ok( success != 0, "failed to create temp directory\n" );
1755 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1756 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1757
1758 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1759 ok( res != 0, "failed to create temp file\n" );
1760 DeleteFileW( newpath );
1761 success = CreateDirectoryW( newpath, NULL );
1762 ok( success != 0, "failed to create temp directory\n" );
1763 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1764 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1765 fri->Replace = FALSE;
1766 fri->RootDir = NULL;
1767 fri->FileNameLength = name_str.Length;
1768 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1769 pRtlFreeUnicodeString( &name_str );
1770
1771 U(io).Status = 0xdeadbeef;
1772 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1773 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1774 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1775 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1776 ok( !fileDeleted, "file should exist\n" );
1777 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1778 ok( !fileDeleted, "file should exist\n" );
1779
1780 CloseHandle( handle );
1781 HeapFree( GetProcessHeap(), 0, fri );
1782 delete_object( oldpath );
1783 delete_object( newpath );
1784
1785 /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1786 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1787 ok( res != 0, "failed to create temp file\n" );
1788 DeleteFileW( oldpath );
1789 success = CreateDirectoryW( oldpath, NULL );
1790 ok( success != 0, "failed to create temp directory\n" );
1791 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1792 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1793
1794 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1795 ok( res != 0, "failed to create temp file\n" );
1796 DeleteFileW( newpath );
1797 success = CreateDirectoryW( newpath, NULL );
1798 ok( success != 0, "failed to create temp directory\n" );
1799 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1800 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1801 fri->Replace = TRUE;
1802 fri->RootDir = NULL;
1803 fri->FileNameLength = name_str.Length;
1804 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1805 pRtlFreeUnicodeString( &name_str );
1806
1807 U(io).Status = 0xdeadbeef;
1808 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1809 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1810 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1811 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1812 ok( !fileDeleted, "file should exist\n" );
1813 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1814 ok( !fileDeleted, "file should exist\n" );
1815
1816 CloseHandle( handle );
1817 HeapFree( GetProcessHeap(), 0, fri );
1818 delete_object( oldpath );
1819 delete_object( newpath );
1820
1821 /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
1822 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1823 ok( res != 0, "failed to create temp file\n" );
1824 DeleteFileW( oldpath );
1825 success = CreateDirectoryW( oldpath, NULL );
1826 ok( success != 0, "failed to create temp directory\n" );
1827 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1828 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1829
1830 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1831 ok( res != 0, "failed to create temp file\n" );
1832 DeleteFileW( newpath );
1833 success = CreateDirectoryW( newpath, NULL );
1834 ok( success != 0, "failed to create temp directory\n" );
1835 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1836 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1837
1838 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1839 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1840 fri->Replace = TRUE;
1841 fri->RootDir = NULL;
1842 fri->FileNameLength = name_str.Length;
1843 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1844 pRtlFreeUnicodeString( &name_str );
1845
1846 U(io).Status = 0xdeadbeef;
1847 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1848 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1849 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1850 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1851 ok( !fileDeleted, "file should exist\n" );
1852 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1853 ok( !fileDeleted, "file should exist\n" );
1854
1855 CloseHandle( handle );
1856 CloseHandle( handle2 );
1857 HeapFree( GetProcessHeap(), 0, fri );
1858 delete_object( oldpath );
1859 delete_object( newpath );
1860
1861 /* oldpath is a file, newpath is a directory, Replace = FALSE */
1862 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1863 ok( res != 0, "failed to create temp file\n" );
1864 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1865 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1866
1867 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1868 ok( res != 0, "failed to create temp file\n" );
1869 DeleteFileW( newpath );
1870 success = CreateDirectoryW( newpath, NULL );
1871 ok( success != 0, "failed to create temp directory\n" );
1872 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1873 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1874 fri->Replace = FALSE;
1875 fri->RootDir = NULL;
1876 fri->FileNameLength = name_str.Length;
1877 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1878 pRtlFreeUnicodeString( &name_str );
1879
1880 U(io).Status = 0xdeadbeef;
1881 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1882 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1883 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1884 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1885 ok( !fileDeleted, "file should exist\n" );
1886 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1887 ok( !fileDeleted, "file should exist\n" );
1888
1889 CloseHandle( handle );
1890 HeapFree( GetProcessHeap(), 0, fri );
1891 delete_object( oldpath );
1892 delete_object( newpath );
1893
1894 /* oldpath is a file, newpath is a directory, Replace = TRUE */
1895 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1896 ok( res != 0, "failed to create temp file\n" );
1897 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1898 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1899
1900 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1901 ok( res != 0, "failed to create temp file\n" );
1902 DeleteFileW( newpath );
1903 success = CreateDirectoryW( newpath, NULL );
1904 ok( success != 0, "failed to create temp directory\n" );
1905 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1906 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1907 fri->Replace = TRUE;
1908 fri->RootDir = NULL;
1909 fri->FileNameLength = name_str.Length;
1910 memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1911 pRtlFreeUnicodeString( &name_str );
1912
1913 U(io).Status = 0xdeadbeef;
1914 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1915 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1916 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1917 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1918 ok( !fileDeleted, "file should exist\n" );
1919 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1920 ok( !fileDeleted, "file should exist\n" );
1921
1922 CloseHandle( handle );
1923 HeapFree( GetProcessHeap(), 0, fri );
1924 delete_object( oldpath );
1925 delete_object( newpath );
1926
1927 /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
1928 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1929 ok( res != 0, "failed to create temp file\n" );
1930 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1931 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1932
1933 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1934 ok( res != 0, "failed to create temp file\n" );
1935 DeleteFileW( newpath );
1936 for (filename = newpath, p = newpath; *p; p++)
1937 if (*p == '\\') filename = p + 1;
1938 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1939 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1940
1941 fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
1942 fri->Replace = FALSE;
1943 fri->RootDir = handle2;
1944 fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
1945 memcpy( fri->FileName, filename, fri->FileNameLength );
1946
1947 U(io).Status = 0xdeadbeef;
1948 res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1949 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1950 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1951 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1952 ok( fileDeleted, "file should not exist\n" );
1953 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1954 ok( !fileDeleted, "file should exist\n" );
1955
1956 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1957 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1958 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1959 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1960 ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1961 wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1962 HeapFree( GetProcessHeap(), 0, fni );
1963
1964 CloseHandle( handle );
1965 CloseHandle( handle2 );
1966 HeapFree( GetProcessHeap(), 0, fri );
1967 delete_object( oldpath );
1968 delete_object( newpath );
1969 }
1970
1971 static void test_file_link_information(void)
1972 {
1973 static const WCHAR pipeW[] = {'\\','\\','.','\\','p','i','p','e','\\','w','i','n','e','_','t','e','s','t',0};
1974 static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1975 static const WCHAR fooW[] = {'f','o','o',0};
1976 WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1977 FILE_LINK_INFORMATION *fli;
1978 FILE_NAME_INFORMATION *fni;
1979 BOOL success, fileDeleted;
1980 UNICODE_STRING name_str;
1981 HANDLE handle, handle2;
1982 IO_STATUS_BLOCK io;
1983 NTSTATUS res;
1984
1985 GetTempPathW( MAX_PATH, tmp_path );
1986
1987 /* oldpath is a file, newpath doesn't exist */
1988 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1989 ok( res != 0, "failed to create temp file\n" );
1990 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1991 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1992
1993 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1994 ok( res != 0, "failed to create temp file\n" );
1995 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1996 DeleteFileW( newpath );
1997 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
1998 fli->ReplaceIfExists = FALSE;
1999 fli->RootDirectory = NULL;
2000 fli->FileNameLength = name_str.Length;
2001 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2002 pRtlFreeUnicodeString( &name_str );
2003
2004 U(io).Status = 0xdeadbeef;
2005 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2006 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2007 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\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" );
2012
2013 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2014 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2015 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2016 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2017 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2018 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2019 HeapFree( GetProcessHeap(), 0, fni );
2020
2021 CloseHandle( handle );
2022 HeapFree( GetProcessHeap(), 0, fli );
2023 delete_object( oldpath );
2024 delete_object( newpath );
2025
2026 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2027 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2028 ok( res != 0, "failed to create temp file\n" );
2029 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2030 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2031
2032 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2033 ok( res != 0, "failed to create temp file\n" );
2034 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2035 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2036 fli->ReplaceIfExists = FALSE;
2037 fli->RootDirectory = NULL;
2038 fli->FileNameLength = name_str.Length;
2039 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2040 pRtlFreeUnicodeString( &name_str );
2041
2042 U(io).Status = 0xdeadbeef;
2043 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2044 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2045 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2046 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2047 ok( !fileDeleted, "file should exist\n" );
2048 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2049 ok( !fileDeleted, "file should exist\n" );
2050
2051 CloseHandle( handle );
2052 HeapFree( GetProcessHeap(), 0, fli );
2053 delete_object( oldpath );
2054 delete_object( newpath );
2055
2056 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2057 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2058 ok( res != 0, "failed to create temp file\n" );
2059 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2060 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2061
2062 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2063 ok( res != 0, "failed to create temp file\n" );
2064 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2065 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2066 fli->ReplaceIfExists = TRUE;
2067 fli->RootDirectory = NULL;
2068 fli->FileNameLength = name_str.Length;
2069 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2070 pRtlFreeUnicodeString( &name_str );
2071
2072 U(io).Status = 0xdeadbeef;
2073 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2074 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2075 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2076 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2077 ok( !fileDeleted, "file should exist\n" );
2078 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2079 ok( !fileDeleted, "file should exist\n" );
2080
2081 CloseHandle( handle );
2082 HeapFree( GetProcessHeap(), 0, fli );
2083 delete_object( oldpath );
2084 delete_object( newpath );
2085
2086 /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2087 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2088 ok( res != 0, "failed to create temp file\n" );
2089 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2090 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2091
2092 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2093 ok( res != 0, "failed to create temp file\n" );
2094 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2095 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2096
2097 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2098 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2099 fli->ReplaceIfExists = FALSE;
2100 fli->RootDirectory = NULL;
2101 fli->FileNameLength = name_str.Length;
2102 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2103 pRtlFreeUnicodeString( &name_str );
2104
2105 U(io).Status = 0xdeadbeef;
2106 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2107 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2108 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2109 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2110 ok( !fileDeleted, "file should exist\n" );
2111 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2112 ok( !fileDeleted, "file should exist\n" );
2113
2114 CloseHandle( handle );
2115 CloseHandle( handle2 );
2116 HeapFree( GetProcessHeap(), 0, fli );
2117 delete_object( oldpath );
2118 delete_object( newpath );
2119
2120 /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2121 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2122 ok( res != 0, "failed to create temp file\n" );
2123 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2124 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2125
2126 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2127 ok( res != 0, "failed to create temp file\n" );
2128 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2129 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2130
2131 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2132 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2133 fli->ReplaceIfExists = TRUE;
2134 fli->RootDirectory = NULL;
2135 fli->FileNameLength = name_str.Length;
2136 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2137 pRtlFreeUnicodeString( &name_str );
2138
2139 U(io).Status = 0xdeadbeef;
2140 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2141 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2142 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2143 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2144 ok( !fileDeleted, "file should exist\n" );
2145 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2146 ok( !fileDeleted, "file should exist\n" );
2147
2148 CloseHandle( handle );
2149 CloseHandle( handle2 );
2150 HeapFree( GetProcessHeap(), 0, fli );
2151 delete_object( oldpath );
2152 delete_object( newpath );
2153
2154 /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2155 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2156 ok( res != 0, "failed to create temp file\n" );
2157 DeleteFileW( oldpath );
2158 success = CreateDirectoryW( oldpath, NULL );
2159 ok( success != 0, "failed to create temp directory\n" );
2160 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2161 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2162
2163 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2164 ok( res != 0, "failed to create temp file\n" );
2165 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2166 DeleteFileW( newpath );
2167 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2168 fli->ReplaceIfExists = FALSE;
2169 fli->RootDirectory = NULL;
2170 fli->FileNameLength = name_str.Length;
2171 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2172 pRtlFreeUnicodeString( &name_str );
2173
2174 U(io).Status = 0xdeadbeef;
2175 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2176 todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2177 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2178 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2179 ok( !fileDeleted, "file should exist\n" );
2180 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2181 ok( fileDeleted, "file should not exist\n" );
2182
2183 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2184 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2185 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2186 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2187 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2188 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2189 HeapFree( GetProcessHeap(), 0, fni );
2190
2191 CloseHandle( handle );
2192 HeapFree( GetProcessHeap(), 0, fli );
2193 delete_object( oldpath );
2194 delete_object( newpath );
2195
2196 /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2197 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2198 ok( res != 0, "failed to create temp file\n" );
2199 DeleteFileW( oldpath );
2200 success = CreateDirectoryW( oldpath, NULL );
2201 ok( success != 0, "failed to create temp directory\n" );
2202 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2203 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2204
2205 lstrcpyW( newpath, oldpath );
2206 lstrcatW( newpath, foo_txtW );
2207 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2208 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2209
2210 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2211 ok( res != 0, "failed to create temp file\n" );
2212 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2213 DeleteFileW( newpath );
2214 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2215 fli->ReplaceIfExists = FALSE;
2216 fli->RootDirectory = NULL;
2217 fli->FileNameLength = name_str.Length;
2218 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2219 pRtlFreeUnicodeString( &name_str );
2220
2221 U(io).Status = 0xdeadbeef;
2222 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2223 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2224 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2225 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2226 ok( !fileDeleted, "file should exist\n" );
2227 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2228 ok( fileDeleted, "file should not exist\n" );
2229
2230 CloseHandle( handle );
2231 CloseHandle( handle2 );
2232 HeapFree( GetProcessHeap(), 0, fli );
2233 delete_object( oldpath );
2234 delete_object( newpath );
2235
2236 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2237 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2238 ok( res != 0, "failed to create temp file\n" );
2239 DeleteFileW( oldpath );
2240 success = CreateDirectoryW( oldpath, NULL );
2241 ok( success != 0, "failed to create temp directory\n" );
2242 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2243 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2244
2245 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2246 ok( res != 0, "failed to create temp file\n" );
2247 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2248 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2249 fli->ReplaceIfExists = FALSE;
2250 fli->RootDirectory = NULL;
2251 fli->FileNameLength = name_str.Length;
2252 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2253 pRtlFreeUnicodeString( &name_str );
2254
2255 U(io).Status = 0xdeadbeef;
2256 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2257 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2258 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2259 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2260 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2261 ok( !fileDeleted, "file should exist\n" );
2262 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2263 ok( !fileDeleted, "file should exist\n" );
2264
2265 CloseHandle( handle );
2266 HeapFree( GetProcessHeap(), 0, fli );
2267 delete_object( oldpath );
2268 delete_object( newpath );
2269
2270 /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2271 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2272 ok( res != 0, "failed to create temp file\n" );
2273 DeleteFileW( oldpath );
2274 success = CreateDirectoryW( oldpath, NULL );
2275 ok( success != 0, "failed to create temp directory\n" );
2276 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2277 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2278
2279 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2280 ok( res != 0, "failed to create temp file\n" );
2281 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2282 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2283
2284 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2285 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2286 fli->ReplaceIfExists = FALSE;
2287 fli->RootDirectory = NULL;
2288 fli->FileNameLength = name_str.Length;
2289 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2290 pRtlFreeUnicodeString( &name_str );
2291
2292 U(io).Status = 0xdeadbeef;
2293 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2294 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2295 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2296 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2297 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2298 ok( !fileDeleted, "file should exist\n" );
2299 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2300 ok( !fileDeleted, "file should exist\n" );
2301
2302 CloseHandle( handle );
2303 CloseHandle( handle2 );
2304 HeapFree( GetProcessHeap(), 0, fli );
2305 delete_object( oldpath );
2306 delete_object( newpath );
2307
2308 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2309 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2310 ok( res != 0, "failed to create temp file\n" );
2311 DeleteFileW( oldpath );
2312 success = CreateDirectoryW( oldpath, NULL );
2313 ok( success != 0, "failed to create temp directory\n" );
2314 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2315 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2316
2317 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2318 ok( res != 0, "failed to create temp file\n" );
2319 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2320 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2321 fli->ReplaceIfExists = TRUE;
2322 fli->RootDirectory = NULL;
2323 fli->FileNameLength = name_str.Length;
2324 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2325 pRtlFreeUnicodeString( &name_str );
2326
2327 U(io).Status = 0xdeadbeef;
2328 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2329 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2330 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2331 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2332 ok( !fileDeleted, "file should exist\n" );
2333 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2334 ok( !fileDeleted, "file should exist\n" );
2335
2336 CloseHandle( handle );
2337 HeapFree( GetProcessHeap(), 0, fli );
2338 delete_object( oldpath );
2339 delete_object( newpath );
2340
2341 /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2342 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2343 ok( res != 0, "failed to create temp file\n" );
2344 DeleteFileW( oldpath );
2345 success = CreateDirectoryW( oldpath, NULL );
2346 ok( success != 0, "failed to create temp directory\n" );
2347 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2348 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2349
2350 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2351 ok( res != 0, "failed to create temp file\n" );
2352 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2353 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2354
2355 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2356 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2357 fli->ReplaceIfExists = TRUE;
2358 fli->RootDirectory = NULL;
2359 fli->FileNameLength = name_str.Length;
2360 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2361 pRtlFreeUnicodeString( &name_str );
2362
2363 U(io).Status = 0xdeadbeef;
2364 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2365 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2366 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2367 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2368 ok( !fileDeleted, "file should exist\n" );
2369 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2370 ok( !fileDeleted, "file should exist\n" );
2371
2372 CloseHandle( handle );
2373 CloseHandle( handle2 );
2374 HeapFree( GetProcessHeap(), 0, fli );
2375 delete_object( oldpath );
2376 delete_object( newpath );
2377
2378 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2379 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2380 ok( res != 0, "failed to create temp file\n" );
2381 DeleteFileW( oldpath );
2382 success = CreateDirectoryW( oldpath, NULL );
2383 ok( success != 0, "failed to create temp directory\n" );
2384 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2385 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2386
2387 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2388 ok( res != 0, "failed to create temp file\n" );
2389 DeleteFileW( newpath );
2390 success = CreateDirectoryW( newpath, NULL );
2391 ok( success != 0, "failed to create temp directory\n" );
2392 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2393 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2394 fli->ReplaceIfExists = FALSE;
2395 fli->RootDirectory = NULL;
2396 fli->FileNameLength = name_str.Length;
2397 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2398 pRtlFreeUnicodeString( &name_str );
2399
2400 U(io).Status = 0xdeadbeef;
2401 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2402 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2403 ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2404 "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\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" );
2409
2410 CloseHandle( handle );
2411 HeapFree( GetProcessHeap(), 0, fli );
2412 delete_object( oldpath );
2413 delete_object( newpath );
2414
2415 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2416 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2417 ok( res != 0, "failed to create temp file\n" );
2418 DeleteFileW( oldpath );
2419 success = CreateDirectoryW( oldpath, NULL );
2420 ok( success != 0, "failed to create temp directory\n" );
2421 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2422 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2423
2424 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2425 ok( res != 0, "failed to create temp file\n" );
2426 DeleteFileW( newpath );
2427 success = CreateDirectoryW( newpath, NULL );
2428 ok( success != 0, "failed to create temp directory\n" );
2429 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2430 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2431 fli->ReplaceIfExists = TRUE;
2432 fli->RootDirectory = NULL;
2433 fli->FileNameLength = name_str.Length;
2434 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2435 pRtlFreeUnicodeString( &name_str );
2436
2437 U(io).Status = 0xdeadbeef;
2438 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2439 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2440 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2441 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2442 ok( !fileDeleted, "file should exist\n" );
2443 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2444 ok( !fileDeleted, "file should exist\n" );
2445
2446 CloseHandle( handle );
2447 HeapFree( GetProcessHeap(), 0, fli );
2448 delete_object( oldpath );
2449 delete_object( newpath );
2450
2451 /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2452 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2453 ok( res != 0, "failed to create temp file\n" );
2454 DeleteFileW( oldpath );
2455 success = CreateDirectoryW( oldpath, NULL );
2456 ok( success != 0, "failed to create temp directory\n" );
2457 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2458 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2459
2460 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2461 ok( res != 0, "failed to create temp file\n" );
2462 DeleteFileW( newpath );
2463 success = CreateDirectoryW( newpath, NULL );
2464 ok( success != 0, "failed to create temp directory\n" );
2465 handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2466 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2467
2468 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2469 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2470 fli->ReplaceIfExists = TRUE;
2471 fli->RootDirectory = NULL;
2472 fli->FileNameLength = name_str.Length;
2473 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2474 pRtlFreeUnicodeString( &name_str );
2475
2476 U(io).Status = 0xdeadbeef;
2477 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2478 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2479 ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2480 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2481 ok( !fileDeleted, "file should exist\n" );
2482 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2483 ok( !fileDeleted, "file should exist\n" );
2484
2485 CloseHandle( handle );
2486 CloseHandle( handle2 );
2487 HeapFree( GetProcessHeap(), 0, fli );
2488 delete_object( oldpath );
2489 delete_object( newpath );
2490
2491 /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2492 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2493 ok( res != 0, "failed to create temp file\n" );
2494 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2495 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2496
2497 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2498 ok( res != 0, "failed to create temp file\n" );
2499 DeleteFileW( newpath );
2500 success = CreateDirectoryW( newpath, NULL );
2501 ok( success != 0, "failed to create temp directory\n" );
2502 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2503 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2504 fli->ReplaceIfExists = FALSE;
2505 fli->RootDirectory = NULL;
2506 fli->FileNameLength = name_str.Length;
2507 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2508 pRtlFreeUnicodeString( &name_str );
2509
2510 U(io).Status = 0xdeadbeef;
2511 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2512 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2513 ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2514 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2515 ok( !fileDeleted, "file should exist\n" );
2516 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2517 ok( !fileDeleted, "file should exist\n" );
2518
2519 CloseHandle( handle );
2520 HeapFree( GetProcessHeap(), 0, fli );
2521 delete_object( oldpath );
2522 delete_object( newpath );
2523
2524 /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2525 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2526 ok( res != 0, "failed to create temp file\n" );
2527 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2528 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2529
2530 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2531 ok( res != 0, "failed to create temp file\n" );
2532 DeleteFileW( newpath );
2533 success = CreateDirectoryW( newpath, NULL );
2534 ok( success != 0, "failed to create temp directory\n" );
2535 pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2536 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2537 fli->ReplaceIfExists = TRUE;
2538 fli->RootDirectory = NULL;
2539 fli->FileNameLength = name_str.Length;
2540 memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2541 pRtlFreeUnicodeString( &name_str );
2542
2543 U(io).Status = 0xdeadbeef;
2544 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2545 todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2546 ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2547 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2548 ok( !fileDeleted, "file should exist\n" );
2549 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2550 ok( !fileDeleted, "file should exist\n" );
2551
2552 CloseHandle( handle );
2553 HeapFree( GetProcessHeap(), 0, fli );
2554 delete_object( oldpath );
2555 delete_object( newpath );
2556
2557 /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2558 res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2559 ok( res != 0, "failed to create temp file\n" );
2560 handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2561 ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2562
2563 res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2564 ok( res != 0, "failed to create temp file\n" );
2565 DeleteFileW( newpath );
2566 for (filename = newpath, p = newpath; *p; p++)
2567 if (*p == '\\') filename = p + 1;
2568 handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2569 ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2570
2571 fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2572 fli->ReplaceIfExists = FALSE;
2573 fli->RootDirectory = handle2;
2574 fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2575 memcpy( fli->FileName, filename, fli->FileNameLength );
2576
2577 U(io).Status = 0xdeadbeef;
2578 res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2579 ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2580 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2581 fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2582 ok( !fileDeleted, "file should exist\n" );
2583 fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2584 ok( !fileDeleted, "file should exist\n" );
2585
2586 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2587 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2588 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2589 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2590 ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2591 wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2592 HeapFree( GetProcessHeap(), 0, fni );
2593
2594 CloseHandle( handle );
2595 CloseHandle( handle2 );
2596
2597 handle = CreateEventA( NULL, FALSE, FALSE, "wine_test_event" );
2598 ok( !!handle, "Failed to create event: %u\n", GetLastError());
2599
2600 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2601 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2602 ok( res == STATUS_OBJECT_TYPE_MISMATCH, "res expected STATUS_OBJECT_TYPE_MISMATCH, got %x\n", res );
2603 HeapFree( GetProcessHeap(), 0, fni );
2604
2605 CloseHandle( handle );
2606
2607 handle = CreateNamedPipeW( pipeW, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_READMODE_BYTE, 10, 512, 512, 0, NULL);
2608 ok( handle != INVALID_HANDLE_VALUE, "Failed to create named pipe: %u\n", GetLastError());
2609
2610 fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2611 res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2612 ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2613 fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2614 ok( !lstrcmpiW(fni->FileName, pipeW + 8), "FileName expected %s, got %s\n",
2615 wine_dbgstr_w(pipeW + 8), wine_dbgstr_w(fni->FileName) );
2616 HeapFree( GetProcessHeap(), 0, fni );
2617
2618 CloseHandle( handle );
2619
2620 HeapFree( GetProcessHeap(), 0, fli );
2621 delete_object( oldpath );
2622 delete_object( newpath );
2623 }
2624
2625 static void test_file_both_information(void)
2626 {
2627 IO_STATUS_BLOCK io;
2628 FILE_BOTH_DIR_INFORMATION fbi;
2629 HANDLE h;
2630 int res;
2631
2632 if (!(h = create_temp_file(0))) return;
2633
2634 memset(&fbi, 0, sizeof(fbi));
2635 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
2636 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
2637
2638 CloseHandle( h );
2639 }
2640
2641 static void test_file_disposition_information(void)
2642 {
2643 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
2644 DWORD dirpos;
2645 HANDLE handle, handle2, mapping;
2646 NTSTATUS res;
2647 IO_STATUS_BLOCK io;
2648 FILE_DISPOSITION_INFORMATION fdi;
2649 BOOL fileDeleted;
2650 DWORD fdi2;
2651 void *ptr;
2652
2653 GetTempPathA( MAX_PATH, tmp_path );
2654
2655 /* tests for info struct size */
2656 GetTempFileNameA( tmp_path, "dis", 0, buffer );
2657 handle = CreateFileA( buffer