1 /* Unit test suite for Ntdll directory functions
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2009 Dan Kegel
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * We use function pointers here as there is no import library for NTDLL on
31 /* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
32 * definition errors when we get to winnt.h
34 #define WIN32_NO_STATUS
36 #include "wine/test.h"
40 static NTSTATUS (WINAPI
*pNtClose
)( PHANDLE
);
41 static NTSTATUS (WINAPI
*pNtOpenFile
) ( PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
, PIO_STATUS_BLOCK
, ULONG
, ULONG
);
42 static NTSTATUS (WINAPI
*pNtQueryDirectoryFile
)(HANDLE
,HANDLE
,PIO_APC_ROUTINE
,PVOID
,PIO_STATUS_BLOCK
,
43 PVOID
,ULONG
,FILE_INFORMATION_CLASS
,BOOLEAN
,PUNICODE_STRING
,BOOLEAN
);
44 static NTSTATUS (WINAPI
*pNtQueryInformationFile
)(HANDLE
,PIO_STATUS_BLOCK
,PVOID
,LONG
,FILE_INFORMATION_CLASS
);
45 static NTSTATUS (WINAPI
*pNtSetInformationFile
)(HANDLE
,PIO_STATUS_BLOCK
,PVOID
,ULONG
,FILE_INFORMATION_CLASS
);
46 static BOOLEAN (WINAPI
*pRtlCreateUnicodeStringFromAsciiz
)(PUNICODE_STRING
,LPCSTR
);
47 static BOOL (WINAPI
*pRtlDosPathNameToNtPathName_U
)( LPCWSTR
, PUNICODE_STRING
, PWSTR
*, CURDIR
* );
48 static VOID (WINAPI
*pRtlInitUnicodeString
)( PUNICODE_STRING
, LPCWSTR
);
49 static VOID (WINAPI
*pRtlFreeUnicodeString
)( PUNICODE_STRING
);
50 static LONG (WINAPI
*pRtlCompareUnicodeString
)( const UNICODE_STRING
*, const UNICODE_STRING
*,BOOLEAN
);
51 static NTSTATUS (WINAPI
*pRtlMultiByteToUnicodeN
)( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
52 LPCSTR src
, DWORD srclen
);
53 static NTSTATUS (WINAPI
*pRtlWow64EnableFsRedirection
)( BOOLEAN enable
);
54 static NTSTATUS (WINAPI
*pRtlWow64EnableFsRedirectionEx
)( ULONG disable
, ULONG
*old_value
);
56 /* The attribute sets to test */
57 static struct testfile_s
{
58 BOOL todo
; /* set if it doesn't work on wine yet */
59 BOOL attr_done
; /* set if attributes were tested for this file already */
60 const DWORD attr
; /* desired attribute */
61 WCHAR name
[20]; /* filename to use */
62 const char *target
; /* what to point to (only for reparse pts) */
63 const char *description
; /* for error messages */
64 int nfound
; /* How many were found (expect 1) */
66 { 0, 0, FILE_ATTRIBUTE_NORMAL
, {'l','o','n','g','f','i','l','e','n','a','m','e','.','t','m','p'}, "normal" },
67 { 0, 0, FILE_ATTRIBUTE_NORMAL
, {'n','.','t','m','p',}, "normal" },
68 { 1, 0, FILE_ATTRIBUTE_HIDDEN
, {'h','.','t','m','p',}, "hidden" },
69 { 1, 0, FILE_ATTRIBUTE_SYSTEM
, {'s','.','t','m','p',}, "system" },
70 { 0, 0, FILE_ATTRIBUTE_DIRECTORY
, {'d','.','t','m','p',}, "directory" },
71 { 0, 0, FILE_ATTRIBUTE_NORMAL
, {0xe9,'a','.','t','m','p'}, "normal" },
72 { 0, 0, FILE_ATTRIBUTE_NORMAL
, {0xc9,'b','.','t','m','p'}, "normal" },
73 { 0, 0, FILE_ATTRIBUTE_NORMAL
, {'e','a','.','t','m','p'}, "normal" },
74 { 0, 0, FILE_ATTRIBUTE_DIRECTORY
, {'.'}, ". directory" },
75 { 0, 0, FILE_ATTRIBUTE_DIRECTORY
, {'.','.'}, ".. directory" }
77 static const int test_dir_count
= sizeof(testfiles
) / sizeof(testfiles
[0]);
78 static const int max_test_dir_size
= sizeof(testfiles
) / sizeof(testfiles
[0]) + 5; /* size of above plus some for .. etc */
80 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
81 static const WCHAR dotW
[] = {'.',0};
82 static const WCHAR dotdotW
[] = {'.','.',0};
83 static const WCHAR backslashW
[] = {'\\',0};
85 /* Create a test directory full of attribute test files, clear counts */
86 static void set_up_attribute_test(const WCHAR
*testdir
)
91 ret
= CreateDirectoryW(testdir
, NULL
);
92 ok(ret
, "couldn't create dir %s, error %d\n", wine_dbgstr_w(testdir
), GetLastError());
94 for (i
=0; i
< test_dir_count
; i
++) {
97 if (lstrcmpW(testfiles
[i
].name
, dotW
) == 0 || lstrcmpW(testfiles
[i
].name
, dotdotW
) == 0)
99 lstrcpyW( buf
, testdir
);
100 lstrcatW( buf
, backslashW
);
101 lstrcatW( buf
, testfiles
[i
].name
);
102 if (testfiles
[i
].attr
& FILE_ATTRIBUTE_DIRECTORY
) {
103 ret
= CreateDirectoryW(buf
, NULL
);
104 ok(ret
, "couldn't create dir %s, error %d\n", wine_dbgstr_w(buf
), GetLastError());
106 HANDLE h
= CreateFileW(buf
,
107 GENERIC_READ
|GENERIC_WRITE
,
108 0, NULL
, CREATE_ALWAYS
,
109 testfiles
[i
].attr
, 0);
110 ok( h
!= INVALID_HANDLE_VALUE
, "failed to create temp file %s\n", wine_dbgstr_w(buf
) );
116 static void reset_found_files(void)
120 for (i
= 0; i
< test_dir_count
; i
++)
121 testfiles
[i
].nfound
= 0;
124 /* Remove the given test directory and the attribute test files, if any */
125 static void tear_down_attribute_test(const WCHAR
*testdir
)
129 for (i
= 0; i
< test_dir_count
; i
++) {
132 if (lstrcmpW(testfiles
[i
].name
, dotW
) == 0 || lstrcmpW(testfiles
[i
].name
, dotdotW
) == 0)
134 lstrcpyW( buf
, testdir
);
135 lstrcatW( buf
, backslashW
);
136 lstrcatW( buf
, testfiles
[i
].name
);
137 if (testfiles
[i
].attr
& FILE_ATTRIBUTE_DIRECTORY
) {
138 ret
= RemoveDirectoryW(buf
);
139 ok(ret
|| (GetLastError() == ERROR_PATH_NOT_FOUND
),
140 "Failed to rmdir %s, error %d\n", wine_dbgstr_w(buf
), GetLastError());
142 ret
= DeleteFileW(buf
);
143 ok(ret
|| (GetLastError() == ERROR_PATH_NOT_FOUND
),
144 "Failed to rm %s, error %d\n", wine_dbgstr_w(buf
), GetLastError());
147 RemoveDirectoryW(testdir
);
150 /* Match one found file against testfiles[], increment count if found */
151 static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION
*dir_info
)
155 (FILE_ATTRIBUTE_SYSTEM
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_REPARSE_POINT
);
156 DWORD attrib
= dir_info
->FileAttributes
& attribmask
;
157 WCHAR
*nameW
= dir_info
->FileName
;
158 int namelen
= dir_info
->FileNameLength
/ sizeof(WCHAR
);
160 for (i
= 0; i
< test_dir_count
; i
++) {
161 int len
= lstrlenW(testfiles
[i
].name
);
162 if (namelen
!= len
|| memcmp(nameW
, testfiles
[i
].name
, len
*sizeof(WCHAR
)))
164 if (!testfiles
[i
].attr_done
) {
165 todo_wine_if (testfiles
[i
].todo
)
166 ok (attrib
== (testfiles
[i
].attr
& attribmask
), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", wine_dbgstr_w(testfiles
[i
].name
), testfiles
[i
].description
, testfiles
[i
].attr
, attrib
);
167 testfiles
[i
].attr_done
= TRUE
;
169 testfiles
[i
].nfound
++;
172 ok(i
< test_dir_count
, "unexpected file found %s\n", wine_dbgstr_wn(dir_info
->FileName
, namelen
));
175 static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES
*attr
, const char *testdirA
,
176 UNICODE_STRING
*mask
,
177 BOOLEAN single_entry
, BOOLEAN restart_flag
)
179 UNICODE_STRING dummy_mask
;
180 HANDLE dirh
, new_dirh
;
182 UINT data_pos
, data_size
;
183 UINT data_len
; /* length of dir data */
184 BYTE data
[8192]; /* directory data */
185 FILE_BOTH_DIRECTORY_INFORMATION
*dir_info
;
191 pRtlInitUnicodeString( &dummy_mask
, dummyW
);
193 data_size
= mask
? offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[256] ) : sizeof(data
);
195 /* Read the directory and note which files are found */
196 status
= pNtOpenFile( &dirh
, SYNCHRONIZE
| FILE_LIST_DIRECTORY
, attr
, &io
, FILE_SHARE_READ
,
197 FILE_SYNCHRONOUS_IO_NONALERT
|FILE_OPEN_FOR_BACKUP_INTENT
|FILE_DIRECTORY_FILE
);
198 ok (status
== STATUS_SUCCESS
, "failed to open dir '%s', ret 0x%x, error %d\n", testdirA
, status
, GetLastError());
199 if (status
!= STATUS_SUCCESS
) {
200 skip("can't test if we can't open the directory\n");
204 U(io
).Status
= 0xdeadbeef;
205 status
= pNtQueryDirectoryFile( dirh
, NULL
, NULL
, NULL
, &io
, data
, data_size
,
206 FileBothDirectoryInformation
, single_entry
, mask
, restart_flag
);
207 ok (status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", status
);
208 ok (U(io
).Status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", U(io
).Status
);
209 data_len
= io
.Information
;
210 ok (data_len
>= sizeof(FILE_BOTH_DIRECTORY_INFORMATION
), "not enough data in directory\n");
212 DuplicateHandle( GetCurrentProcess(), dirh
, GetCurrentProcess(), &new_dirh
,
213 0, FALSE
, DUPLICATE_SAME_ACCESS
);
218 while ((data_pos
< data_len
) && (numfiles
< max_test_dir_size
)) {
219 dir_info
= (FILE_BOTH_DIRECTORY_INFORMATION
*)(data
+ data_pos
);
221 tally_test_file(dir_info
);
223 if (dir_info
->NextEntryOffset
== 0) {
224 U(io
).Status
= 0xdeadbeef;
225 status
= pNtQueryDirectoryFile( new_dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
226 FileBothDirectoryInformation
, single_entry
, &dummy_mask
, FALSE
);
227 ok (U(io
).Status
== status
, "wrong status %x / %x\n", status
, U(io
).Status
);
228 if (status
== STATUS_NO_MORE_FILES
) break;
229 ok (status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", status
);
230 data_len
= io
.Information
;
231 if (data_len
< sizeof(FILE_BOTH_DIRECTORY_INFORMATION
))
235 data_pos
+= dir_info
->NextEntryOffset
;
239 ok(numfiles
< max_test_dir_size
, "too many loops\n");
242 for (i
= 0; i
< test_dir_count
; i
++)
243 ok(testfiles
[i
].nfound
== (testfiles
[i
].name
== mask
->Buffer
),
244 "Wrong number %d of %s files found (single_entry=%d,mask=%s)\n",
245 testfiles
[i
].nfound
, testfiles
[i
].description
, single_entry
,
246 wine_dbgstr_wn(mask
->Buffer
, mask
->Length
/sizeof(WCHAR
) ));
248 for (i
= 0; i
< test_dir_count
; i
++)
249 ok(testfiles
[i
].nfound
== 1, "Wrong number %d of %s files found (single_entry=%d,restart=%d)\n",
250 testfiles
[i
].nfound
, testfiles
[i
].description
, single_entry
, restart_flag
);
254 static void test_directory_sort( const WCHAR
*testdir
)
256 OBJECT_ATTRIBUTES attr
;
257 UNICODE_STRING ntdirname
;
259 UINT data_pos
, data_len
, count
;
261 WCHAR prev
[MAX_PATH
], name
[MAX_PATH
];
262 UNICODE_STRING prev_str
, name_str
;
263 FILE_BOTH_DIRECTORY_INFORMATION
*info
;
268 if (!pRtlDosPathNameToNtPathName_U( testdir
, &ntdirname
, NULL
, NULL
))
270 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
273 InitializeObjectAttributes( &attr
, &ntdirname
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
274 status
= pNtOpenFile( &handle
, SYNCHRONIZE
| FILE_LIST_DIRECTORY
, &attr
, &io
, FILE_SHARE_READ
,
275 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE
);
276 ok(status
== STATUS_SUCCESS
, "failed to open dir %s\n", wine_dbgstr_w(testdir
) );
278 U(io
).Status
= 0xdeadbeef;
279 status
= pNtQueryDirectoryFile( handle
, NULL
, NULL
, NULL
, &io
, data
, sizeof(data
),
280 FileBothDirectoryInformation
, FALSE
, NULL
, TRUE
);
281 ok( status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", status
);
282 ok( U(io
).Status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", U(io
).Status
);
283 data_len
= io
.Information
;
284 ok( data_len
>= sizeof(FILE_BOTH_DIRECTORY_INFORMATION
), "not enough data in directory\n" );
288 while (data_pos
< data_len
)
290 info
= (FILE_BOTH_DIRECTORY_INFORMATION
*)(data
+ data_pos
);
292 memcpy( name
, info
->FileName
, info
->FileNameLength
);
293 name
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
296 case 0: /* first entry must be '.' */
297 ok( !lstrcmpW( name
, dotW
), "wrong name %s\n", wine_dbgstr_w( name
));
299 case 1: /* second entry must be '..' */
300 ok( !lstrcmpW( name
, dotdotW
), "wrong name %s\n", wine_dbgstr_w( name
));
302 case 2: /* nothing to compare against */
305 pRtlInitUnicodeString( &prev_str
, prev
);
306 pRtlInitUnicodeString( &name_str
, name
);
307 res
= pRtlCompareUnicodeString( &prev_str
, &name_str
, TRUE
);
308 ok( res
< 0, "wrong result %d %s %s\n", res
, wine_dbgstr_w( prev
), wine_dbgstr_w( name
));
312 lstrcpyW( prev
, name
);
314 if (info
->NextEntryOffset
== 0)
316 U(io
).Status
= 0xdeadbeef;
317 status
= pNtQueryDirectoryFile( handle
, 0, NULL
, NULL
, &io
, data
, sizeof(data
),
318 FileBothDirectoryInformation
, FALSE
, NULL
, FALSE
);
319 ok (U(io
).Status
== status
, "wrong status %x / %x\n", status
, U(io
).Status
);
320 if (status
== STATUS_NO_MORE_FILES
) break;
321 ok( status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", status
);
322 data_len
= io
.Information
;
325 else data_pos
+= info
->NextEntryOffset
;
329 pRtlFreeUnicodeString( &ntdirname
);
332 static void test_NtQueryDirectoryFile_classes( HANDLE handle
, UNICODE_STRING
*mask
)
340 for (class = 0; class < FileMaximumInformation
; class++)
342 U(io
).Status
= 0xdeadbeef;
343 U(io
).Information
= 0xdeadbeef;
345 memset( data
, 0x55, sizeof(data
) );
347 status
= pNtQueryDirectoryFile( handle
, 0, NULL
, NULL
, &io
, data
, data_size
,
348 class, FALSE
, mask
, TRUE
);
349 ok( U(io
).Status
== 0xdeadbeef, "%u: wrong status %x\n", class, U(io
).Status
);
350 ok( U(io
).Information
== 0xdeadbeef, "%u: wrong info %lx\n", class, U(io
).Information
);
351 ok(data
[0] == 0x55555555, "%u: wrong offset %x\n", class, data
[0] );
355 case FileIdGlobalTxDirectoryInformation
:
356 if (status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
) continue;
358 case FileDirectoryInformation
:
359 case FileFullDirectoryInformation
:
360 case FileBothDirectoryInformation
:
361 case FileNamesInformation
:
362 case FileIdBothDirectoryInformation
:
363 case FileIdFullDirectoryInformation
:
364 case FileObjectIdInformation
:
365 case FileQuotaInformation
:
366 case FileReparsePointInformation
:
367 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "%u: wrong status %x\n", class, status
);
370 ok( status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
,
371 "%u: wrong status %x\n", class, status
);
375 for (data_size
= 1; data_size
< sizeof(data
); data_size
++)
377 status
= pNtQueryDirectoryFile( handle
, 0, NULL
, NULL
, &io
, data
, data_size
,
378 class, FALSE
, mask
, TRUE
);
379 if (status
== STATUS_BUFFER_OVERFLOW
)
381 ok( U(io
).Status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, U(io
).Status
);
382 ok( U(io
).Information
== data_size
, "%u: wrong info %lx\n", class, U(io
).Information
);
383 ok(data
[0] == 0, "%u: wrong offset %x\n", class, data
[0] );
387 ok( U(io
).Status
== 0xdeadbeef, "%u: wrong status %x\n", class, U(io
).Status
);
388 ok( U(io
).Information
== 0xdeadbeef, "%u: wrong info %lx\n", class, U(io
).Information
);
389 ok(data
[0] == 0x55555555, "%u: wrong offset %x\n", class, data
[0] );
391 if (status
!= STATUS_INFO_LENGTH_MISMATCH
) break;
396 case FileDirectoryInformation
:
397 ok( status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, status
);
398 ok( data_size
== ((offsetof( FILE_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7),
399 "%u: wrong size %u\n", class, data_size
);
401 case FileFullDirectoryInformation
:
402 ok( status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, status
);
403 ok( data_size
== ((offsetof( FILE_FULL_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7),
404 "%u: wrong size %u\n", class, data_size
);
406 case FileBothDirectoryInformation
:
407 ok( status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, status
);
408 ok( data_size
== ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7),
409 "%u: wrong size %u\n", class, data_size
);
411 case FileNamesInformation
:
412 ok( status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, status
);
413 ok( data_size
== ((offsetof( FILE_NAMES_INFORMATION
, FileName
[1] ) + 7) & ~7),
414 "%u: wrong size %u\n", class, data_size
);
416 case FileIdBothDirectoryInformation
:
417 ok( status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, status
);
418 ok( data_size
== ((offsetof( FILE_ID_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7),
419 "%u: wrong size %u\n", class, data_size
);
421 case FileIdFullDirectoryInformation
:
422 ok( status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, status
);
423 ok( data_size
== ((offsetof( FILE_ID_FULL_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7),
424 "%u: wrong size %u\n", class, data_size
);
426 case FileIdGlobalTxDirectoryInformation
:
427 ok( status
== STATUS_BUFFER_OVERFLOW
, "%u: wrong status %x\n", class, status
);
428 ok( data_size
== ((offsetof( FILE_ID_GLOBAL_TX_DIR_INFORMATION
, FileName
[1] ) + 7) & ~7),
429 "%u: wrong size %u\n", class, data_size
);
431 case FileObjectIdInformation
:
432 ok( status
== STATUS_INVALID_INFO_CLASS
, "%u: wrong status %x\n", class, status
);
433 ok( data_size
== sizeof(FILE_OBJECTID_INFORMATION
), "%u: wrong size %u\n", class, data_size
);
435 case FileQuotaInformation
:
436 ok( status
== STATUS_INVALID_INFO_CLASS
, "%u: wrong status %x\n", class, status
);
437 ok( data_size
== sizeof(FILE_QUOTA_INFORMATION
), "%u: wrong size %u\n", class, data_size
);
439 case FileReparsePointInformation
:
440 ok( status
== STATUS_INVALID_INFO_CLASS
, "%u: wrong status %x\n", class, status
);
441 ok( data_size
== sizeof(FILE_REPARSE_POINT_INFORMATION
), "%u: wrong size %u\n", class, data_size
);
447 static void test_NtQueryDirectoryFile(void)
449 OBJECT_ATTRIBUTES attr
;
450 UNICODE_STRING ntdirname
, mask
;
451 char testdirA
[MAX_PATH
];
452 WCHAR testdirW
[MAX_PATH
];
455 WCHAR short_name
[12];
458 FILE_BOTH_DIRECTORY_INFORMATION
*next
, *fbdi
= (FILE_BOTH_DIRECTORY_INFORMATION
*)data
;
459 FILE_POSITION_INFORMATION pos_info
;
460 FILE_NAMES_INFORMATION
*names
;
461 const WCHAR
*filename
= fbdi
->FileName
;
465 /* Clean up from prior aborted run, if any, then set up test files */
466 ok(GetTempPathA(MAX_PATH
, testdirA
), "couldn't get temp dir\n");
467 strcat(testdirA
, "NtQueryDirectoryFile.tmp");
468 pRtlMultiByteToUnicodeN(testdirW
, sizeof(testdirW
), NULL
, testdirA
, strlen(testdirA
)+1);
469 tear_down_attribute_test(testdirW
);
470 set_up_attribute_test(testdirW
);
472 if (!pRtlDosPathNameToNtPathName_U(testdirW
, &ntdirname
, NULL
, NULL
))
474 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
477 InitializeObjectAttributes(&attr
, &ntdirname
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
479 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, NULL
, FALSE
, TRUE
);
480 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, NULL
, FALSE
, FALSE
);
481 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, NULL
, TRUE
, TRUE
);
482 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, NULL
, TRUE
, FALSE
);
484 for (i
= 0; i
< test_dir_count
; i
++)
486 if (testfiles
[i
].name
[0] == '.') continue; /* . and .. as masks are broken on Windows */
487 mask
.Buffer
= testfiles
[i
].name
;
488 mask
.Length
= mask
.MaximumLength
= lstrlenW(testfiles
[i
].name
) * sizeof(WCHAR
);
489 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, &mask
, FALSE
, TRUE
);
490 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, &mask
, FALSE
, FALSE
);
491 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, &mask
, TRUE
, TRUE
);
492 test_flags_NtQueryDirectoryFile(&attr
, testdirA
, &mask
, TRUE
, FALSE
);
495 /* short path passed as mask */
496 status
= pNtOpenFile(&dirh
, SYNCHRONIZE
| FILE_LIST_DIRECTORY
, &attr
, &io
, FILE_SHARE_READ
,
497 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE
);
498 ok(status
== STATUS_SUCCESS
, "failed to open dir '%s'\n", testdirA
);
499 if (status
!= STATUS_SUCCESS
) {
500 skip("can't test if we can't open the directory\n");
503 status
= pNtQueryInformationFile( dirh
, &io
, &pos_info
, sizeof(pos_info
), FilePositionInformation
);
504 ok( status
== STATUS_SUCCESS
, "NtQueryInformationFile failed %x\n", status
);
505 ok( pos_info
.CurrentByteOffset
.QuadPart
== 0, "wrong pos %x%08x\n",
506 (DWORD
)(pos_info
.CurrentByteOffset
.QuadPart
>> 32), (DWORD
)pos_info
.CurrentByteOffset
.QuadPart
);
508 pos_info
.CurrentByteOffset
.QuadPart
= 0xbeef;
509 status
= pNtSetInformationFile( dirh
, &io
, &pos_info
, sizeof(pos_info
), FilePositionInformation
);
510 ok( status
== STATUS_SUCCESS
, "NtQueryInformationFile failed %x\n", status
);
512 status
= pNtQueryInformationFile( dirh
, &io
, &pos_info
, sizeof(pos_info
), FilePositionInformation
);
513 ok( status
== STATUS_SUCCESS
, "NtQueryInformationFile failed %x\n", status
);
514 ok( pos_info
.CurrentByteOffset
.QuadPart
== 0xbeef, "wrong pos %x%08x\n",
515 (DWORD
)(pos_info
.CurrentByteOffset
.QuadPart
>> 32), (DWORD
)pos_info
.CurrentByteOffset
.QuadPart
);
517 mask
.Buffer
= testfiles
[0].name
;
518 mask
.Length
= mask
.MaximumLength
= lstrlenW(testfiles
[0].name
) * sizeof(WCHAR
);
519 data_size
= offsetof(FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[256]);
520 U(io
).Status
= 0xdeadbeef;
521 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
522 FileBothDirectoryInformation
, TRUE
, &mask
, FALSE
);
523 ok(status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", status
);
524 ok(U(io
).Status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", U(io
).Status
);
525 ok(fbdi
->ShortName
[0], "ShortName is empty\n");
527 status
= pNtQueryInformationFile( dirh
, &io
, &pos_info
, sizeof(pos_info
), FilePositionInformation
);
528 ok( status
== STATUS_SUCCESS
, "NtQueryInformationFile failed %x\n", status
);
529 ok( pos_info
.CurrentByteOffset
.QuadPart
== 0xbeef, "wrong pos %x%08x\n",
530 (DWORD
)(pos_info
.CurrentByteOffset
.QuadPart
>> 32), (DWORD
)pos_info
.CurrentByteOffset
.QuadPart
);
532 mask
.Length
= mask
.MaximumLength
= fbdi
->ShortNameLength
;
533 memcpy(short_name
, fbdi
->ShortName
, mask
.Length
);
534 mask
.Buffer
= short_name
;
535 U(io
).Status
= 0xdeadbeef;
536 U(io
).Information
= 0xdeadbeef;
537 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
538 FileBothDirectoryInformation
, TRUE
, &mask
, TRUE
);
539 ok(status
== STATUS_SUCCESS
, "failed to query directory status %x\n", status
);
540 ok(U(io
).Status
== STATUS_SUCCESS
, "failed to query directory status %x\n", U(io
).Status
);
541 ok(U(io
).Information
== offsetof(FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[lstrlenW(testfiles
[0].name
)]),
542 "wrong info %lx\n", U(io
).Information
);
543 ok(fbdi
->FileNameLength
== lstrlenW(testfiles
[0].name
)*sizeof(WCHAR
) &&
544 !memcmp(fbdi
->FileName
, testfiles
[0].name
, fbdi
->FileNameLength
),
545 "incorrect long file name: %s\n", wine_dbgstr_wn(fbdi
->FileName
,
546 fbdi
->FileNameLength
/sizeof(WCHAR
)));
548 status
= pNtQueryInformationFile( dirh
, &io
, &pos_info
, sizeof(pos_info
), FilePositionInformation
);
549 ok( status
== STATUS_SUCCESS
, "NtQueryInformationFile failed %x\n", status
);
550 ok( pos_info
.CurrentByteOffset
.QuadPart
== 0xbeef, "wrong pos %x%08x\n",
551 (DWORD
)(pos_info
.CurrentByteOffset
.QuadPart
>> 32), (DWORD
)pos_info
.CurrentByteOffset
.QuadPart
);
553 /* tests with short buffer */
554 memset( data
, 0x55, data_size
);
555 U(io
).Status
= 0xdeadbeef;
556 U(io
).Information
= 0xdeadbeef;
557 data_size
= offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] );
558 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
559 FileBothDirectoryInformation
, TRUE
, &mask
, TRUE
);
560 ok( status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", status
);
561 ok( U(io
).Status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", U(io
).Status
);
562 ok( U(io
).Information
== data_size
|| broken( U(io
).Information
== 0),
563 "wrong info %lx\n", U(io
).Information
);
564 ok( fbdi
->NextEntryOffset
== 0, "wrong offset %x\n", fbdi
->NextEntryOffset
);
565 ok( fbdi
->FileNameLength
== lstrlenW(testfiles
[0].name
) * sizeof(WCHAR
),
566 "wrong length %x\n", fbdi
->FileNameLength
);
567 ok( filename
[0] == testfiles
[0].name
[0], "incorrect long file name: %s\n",
568 wine_dbgstr_wn(fbdi
->FileName
, fbdi
->FileNameLength
/sizeof(WCHAR
)));
569 ok( filename
[1] == 0x5555, "incorrect long file name: %s\n",
570 wine_dbgstr_wn(fbdi
->FileName
, fbdi
->FileNameLength
/sizeof(WCHAR
)));
572 test_NtQueryDirectoryFile_classes( dirh
, &mask
);
574 /* mask may or may not be ignored when restarting the search */
575 pRtlInitUnicodeString( &mask
, dummyW
);
576 U(io
).Status
= 0xdeadbeef;
577 data_size
= offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[256] );
578 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
579 FileBothDirectoryInformation
, TRUE
, &mask
, TRUE
);
580 ok( status
== STATUS_SUCCESS
|| status
== STATUS_NO_MORE_FILES
, "wrong status %x\n", status
);
581 ok( U(io
).Status
== status
, "wrong status %x / %x\n", U(io
).Status
, status
);
583 ok( fbdi
->FileNameLength
== lstrlenW(testfiles
[0].name
)*sizeof(WCHAR
) &&
584 !memcmp(fbdi
->FileName
, testfiles
[0].name
, fbdi
->FileNameLength
),
585 "incorrect long file name: %s\n",
586 wine_dbgstr_wn(fbdi
->FileName
, fbdi
->FileNameLength
/sizeof(WCHAR
)));
590 status
= pNtOpenFile(&dirh
, SYNCHRONIZE
| FILE_LIST_DIRECTORY
, &attr
, &io
, FILE_SHARE_READ
,
591 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE
);
592 ok(status
== STATUS_SUCCESS
, "failed to open dir '%s'\n", testdirA
);
594 memset( data
, 0x55, data_size
);
595 data_size
= sizeof(data
);
596 U(io
).Status
= 0xdeadbeef;
597 U(io
).Information
= 0xdeadbeef;
598 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
599 FileBothDirectoryInformation
, FALSE
, NULL
, TRUE
);
600 ok(status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
601 ok(U(io
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(io
).Status
);
602 ok(U(io
).Information
> 0 && U(io
).Information
< data_size
, "wrong info %lx\n", U(io
).Information
);
603 ok( fbdi
->NextEntryOffset
== ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7),
604 "wrong offset %x\n", fbdi
->NextEntryOffset
);
605 ok( fbdi
->FileNameLength
== sizeof(WCHAR
), "wrong length %x\n", fbdi
->FileNameLength
);
606 ok( fbdi
->FileName
[0] == '.', "incorrect long file name: %s\n",
607 wine_dbgstr_wn(fbdi
->FileName
, fbdi
->FileNameLength
/sizeof(WCHAR
)));
608 next
= (FILE_BOTH_DIRECTORY_INFORMATION
*)(data
+ fbdi
->NextEntryOffset
);
609 ok( next
->NextEntryOffset
== ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[2] ) + 7) & ~7),
610 "wrong offset %x\n", next
->NextEntryOffset
);
611 ok( next
->FileNameLength
== 2 * sizeof(WCHAR
), "wrong length %x\n", next
->FileNameLength
);
612 filename
= next
->FileName
;
613 ok( filename
[0] == '.' && filename
[1] == '.', "incorrect long file name: %s\n",
614 wine_dbgstr_wn(next
->FileName
, next
->FileNameLength
/sizeof(WCHAR
)));
616 data_size
= fbdi
->NextEntryOffset
+ offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ),
617 memset( data
, 0x55, data_size
);
618 U(io
).Status
= 0xdeadbeef;
619 U(io
).Information
= 0xdeadbeef;
620 status
= pNtQueryDirectoryFile( dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
621 FileBothDirectoryInformation
, FALSE
, NULL
, TRUE
);
622 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
623 ok( U(io
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(io
).Status
);
624 ok( U(io
).Information
== offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ),
625 "wrong info %lx\n", U(io
).Information
);
626 ok( fbdi
->NextEntryOffset
== 0, "wrong offset %x\n", fbdi
->NextEntryOffset
);
627 ok( fbdi
->FileNameLength
== sizeof(WCHAR
), "wrong length %x\n", fbdi
->FileNameLength
);
628 ok( fbdi
->FileName
[0] == '.', "incorrect long file name: %s\n",
629 wine_dbgstr_wn(fbdi
->FileName
, fbdi
->FileNameLength
/sizeof(WCHAR
)));
630 next
= (FILE_BOTH_DIRECTORY_INFORMATION
*)&fbdi
->FileName
[1];
631 ok( next
->NextEntryOffset
== 0x55555555, "wrong offset %x\n", next
->NextEntryOffset
);
633 data_size
= fbdi
->NextEntryOffset
+ offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[2] ),
634 memset( data
, 0x55, data_size
);
635 U(io
).Status
= 0xdeadbeef;
636 U(io
).Information
= 0xdeadbeef;
637 status
= pNtQueryDirectoryFile( dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
638 FileBothDirectoryInformation
, FALSE
, NULL
, TRUE
);
639 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
640 ok( U(io
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(io
).Status
);
641 ok( U(io
).Information
== offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ),
642 "wrong info %lx\n", U(io
).Information
);
643 ok( fbdi
->NextEntryOffset
== 0, "wrong offset %x\n", fbdi
->NextEntryOffset
);
645 data_size
= ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7) +
646 offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[2] );
647 memset( data
, 0x55, data_size
);
648 U(io
).Status
= 0xdeadbeef;
649 U(io
).Information
= 0xdeadbeef;
650 status
= pNtQueryDirectoryFile( dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
651 FileBothDirectoryInformation
, FALSE
, NULL
, TRUE
);
652 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
653 ok( U(io
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(io
).Status
);
654 ok( U(io
).Information
== data_size
, "wrong info %lx / %x\n", U(io
).Information
, data_size
);
655 ok( fbdi
->NextEntryOffset
== ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[1] ) + 7) & ~7),
656 "wrong offset %x\n", fbdi
->NextEntryOffset
);
657 ok( fbdi
->FileNameLength
== sizeof(WCHAR
), "wrong length %x\n", fbdi
->FileNameLength
);
658 ok( fbdi
->FileName
[0] == '.', "incorrect long file name: %s\n",
659 wine_dbgstr_wn(fbdi
->FileName
, fbdi
->FileNameLength
/sizeof(WCHAR
)));
660 next
= (FILE_BOTH_DIRECTORY_INFORMATION
*)(data
+ fbdi
->NextEntryOffset
);
661 ok( next
->NextEntryOffset
== 0, "wrong offset %x\n", next
->NextEntryOffset
);
662 ok( next
->FileNameLength
== 2 * sizeof(WCHAR
), "wrong length %x\n", next
->FileNameLength
);
663 filename
= next
->FileName
;
664 ok( filename
[0] == '.' && filename
[1] == '.', "incorrect long file name: %s\n",
665 wine_dbgstr_wn(next
->FileName
, next
->FileNameLength
/sizeof(WCHAR
)));
667 data_size
= ((offsetof( FILE_NAMES_INFORMATION
, FileName
[1] ) + 7) & ~7) +
668 offsetof( FILE_NAMES_INFORMATION
, FileName
[2] );
669 memset( data
, 0x55, data_size
);
670 U(io
).Status
= 0xdeadbeef;
671 U(io
).Information
= 0xdeadbeef;
672 status
= pNtQueryDirectoryFile( dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
673 FileNamesInformation
, FALSE
, NULL
, TRUE
);
674 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
675 ok( U(io
).Status
== STATUS_SUCCESS
, "wrong status %x\n", U(io
).Status
);
676 ok( U(io
).Information
== data_size
, "wrong info %lx / %x\n", U(io
).Information
, data_size
);
677 names
= (FILE_NAMES_INFORMATION
*)data
;
678 ok( names
->NextEntryOffset
== ((offsetof( FILE_NAMES_INFORMATION
, FileName
[1] ) + 7) & ~7),
679 "wrong offset %x\n", names
->NextEntryOffset
);
680 ok( names
->FileNameLength
== sizeof(WCHAR
), "wrong length %x\n", names
->FileNameLength
);
681 ok( names
->FileName
[0] == '.', "incorrect long file name: %s\n",
682 wine_dbgstr_wn(names
->FileName
, names
->FileNameLength
/sizeof(WCHAR
)));
683 names
= (FILE_NAMES_INFORMATION
*)(data
+ names
->NextEntryOffset
);
684 ok( names
->NextEntryOffset
== 0, "wrong offset %x\n", names
->NextEntryOffset
);
685 ok( names
->FileNameLength
== 2 * sizeof(WCHAR
), "wrong length %x\n", names
->FileNameLength
);
686 filename
= names
->FileName
;
687 ok( filename
[0] == '.' && filename
[1] == '.', "incorrect long file name: %s\n",
688 wine_dbgstr_wn(names
->FileName
, names
->FileNameLength
/sizeof(WCHAR
)));
692 /* create new handle to change mask */
693 status
= pNtOpenFile(&dirh
, SYNCHRONIZE
| FILE_LIST_DIRECTORY
, &attr
, &io
, FILE_SHARE_READ
,
694 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE
);
695 ok(status
== STATUS_SUCCESS
, "failed to open dir '%s'\n", testdirA
);
697 pRtlInitUnicodeString( &mask
, dummyW
);
698 U(io
).Status
= 0xdeadbeef;
699 data_size
= sizeof(data
);
700 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
701 FileBothDirectoryInformation
, TRUE
, &mask
, TRUE
);
702 ok(status
== STATUS_NO_SUCH_FILE
, "wrong status %x\n", status
);
703 ok(U(io
).Status
== 0xdeadbeef, "wrong status %x\n", U(io
).Status
);
705 U(io
).Status
= 0xdeadbeef;
706 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
707 FileBothDirectoryInformation
, TRUE
, NULL
, FALSE
);
708 ok(status
== STATUS_NO_MORE_FILES
, "wrong status %x\n", status
);
709 ok(U(io
).Status
== STATUS_NO_MORE_FILES
, "wrong status %x\n", U(io
).Status
);
711 U(io
).Status
= 0xdeadbeef;
712 status
= pNtQueryDirectoryFile(dirh
, 0, NULL
, NULL
, &io
, data
, data_size
,
713 FileBothDirectoryInformation
, TRUE
, NULL
, TRUE
);
714 ok(status
== STATUS_NO_MORE_FILES
, "wrong status %x\n", status
);
715 ok(U(io
).Status
== STATUS_NO_MORE_FILES
, "wrong status %x\n", U(io
).Status
);
719 U(io
).Status
= 0xdeadbeef;
720 status
= pNtQueryDirectoryFile( (HANDLE
)0xbeef, 0, NULL
, NULL
, &io
, data
, data_size
,
721 FileBothDirectoryInformation
, TRUE
, NULL
, TRUE
);
722 ok(status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
723 ok(U(io
).Status
== 0xdeadbeef, "wrong status %x\n", U(io
).Status
);
726 test_directory_sort( testdirW
);
727 tear_down_attribute_test( testdirW
);
728 pRtlFreeUnicodeString(&ntdirname
);
731 static void set_up_case_test(const char *testdir
)
737 ret
= CreateDirectoryA(testdir
, NULL
);
738 ok(ret
, "couldn't create dir '%s', error %d\n", testdir
, GetLastError());
740 sprintf(buf
, "%s\\%s", testdir
, "TesT");
741 h
= CreateFileA(buf
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
742 FILE_ATTRIBUTE_NORMAL
, 0);
743 ok(h
!= INVALID_HANDLE_VALUE
, "failed to create temp file '%s'\n", buf
);
747 static void tear_down_case_test(const char *testdir
)
752 sprintf(buf
, "%s\\%s", testdir
, "TesT");
753 ret
= DeleteFileA(buf
);
754 ok(ret
|| (GetLastError() == ERROR_PATH_NOT_FOUND
),
755 "Failed to rm %s, error %d\n", buf
, GetLastError());
756 RemoveDirectoryA(testdir
);
759 static void test_NtQueryDirectoryFile_case(void)
761 static const char testfile
[] = "TesT";
762 static const WCHAR testfile_w
[] = {'T','e','s','T'};
763 static int testfile_len
= sizeof(testfile
) - 1;
764 static WCHAR testmask
[] = {'t','e','s','t'};
765 OBJECT_ATTRIBUTES attr
;
766 UNICODE_STRING ntdirname
;
767 char testdir
[MAX_PATH
];
768 WCHAR testdir_w
[MAX_PATH
];
772 UINT data_size
, data_len
;
774 FILE_BOTH_DIRECTORY_INFORMATION
*dir_info
= (FILE_BOTH_DIRECTORY_INFORMATION
*)data
;
779 /* Clean up from prior aborted run, if any, then set up test files */
780 ok(GetTempPathA(MAX_PATH
, testdir
), "couldn't get temp dir\n");
781 strcat(testdir
, "case.tmp");
782 tear_down_case_test(testdir
);
783 set_up_case_test(testdir
);
785 pRtlMultiByteToUnicodeN(testdir_w
, sizeof(testdir_w
), NULL
, testdir
, strlen(testdir
) + 1);
786 if (!pRtlDosPathNameToNtPathName_U(testdir_w
, &ntdirname
, NULL
, NULL
))
788 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
791 InitializeObjectAttributes(&attr
, &ntdirname
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
793 data_size
= offsetof(FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[256]);
795 status
= pNtOpenFile(&dirh
, SYNCHRONIZE
| FILE_LIST_DIRECTORY
, &attr
, &io
, FILE_SHARE_READ
,
796 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE
);
797 ok (status
== STATUS_SUCCESS
, "failed to open dir '%s', ret 0x%x, error %d\n", testdir
, status
, GetLastError());
798 if (status
!= STATUS_SUCCESS
)
800 skip("can't test if we can't open the directory\n");
804 mask
.Buffer
= testmask
;
805 mask
.Length
= mask
.MaximumLength
= sizeof(testmask
);
806 pNtQueryDirectoryFile(dirh
, NULL
, NULL
, NULL
, &io
, data
, data_size
,
807 FileBothDirectoryInformation
, TRUE
, &mask
, FALSE
);
808 ok(U(io
).Status
== STATUS_SUCCESS
, "failed to query directory; status %x\n", U(io
).Status
);
809 data_len
= io
.Information
;
810 ok(data_len
>= sizeof(FILE_BOTH_DIRECTORY_INFORMATION
), "not enough data in directory\n");
812 name
= dir_info
->FileName
;
813 name_len
= dir_info
->FileNameLength
/ sizeof(WCHAR
);
815 ok(name_len
== testfile_len
, "unexpected filename length %u\n", name_len
);
816 ok(!memcmp(name
, testfile_w
, testfile_len
* sizeof(WCHAR
)), "unexpected filename %s\n",
817 wine_dbgstr_wn(name
, name_len
));
822 tear_down_case_test(testdir
);
823 pRtlFreeUnicodeString(&ntdirname
);
826 static void test_redirection(void)
831 if (!pRtlWow64EnableFsRedirection
|| !pRtlWow64EnableFsRedirectionEx
)
833 skip( "Wow64 redirection not supported\n" );
836 status
= pRtlWow64EnableFsRedirectionEx( FALSE
, &old
);
837 if (status
== STATUS_NOT_IMPLEMENTED
)
839 skip( "Wow64 redirection not supported\n" );
842 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
844 status
= pRtlWow64EnableFsRedirectionEx( FALSE
, &cur
);
845 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
846 ok( !cur
, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
848 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, &cur
);
849 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
850 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, &cur
);
851 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
852 ok( cur
== 1, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
854 status
= pRtlWow64EnableFsRedirection( TRUE
);
855 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
856 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, &cur
);
857 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
858 ok( !cur
, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
860 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, NULL
);
861 ok( status
== STATUS_ACCESS_VIOLATION
, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status
);
862 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, (void*)1 );
863 ok( status
== STATUS_ACCESS_VIOLATION
, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status
);
864 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, (void*)0xDEADBEEF );
865 ok( status
== STATUS_ACCESS_VIOLATION
, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status
);
867 status
= pRtlWow64EnableFsRedirection( FALSE
);
868 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
869 status
= pRtlWow64EnableFsRedirectionEx( FALSE
, &cur
);
870 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
871 ok( cur
== 1, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
873 pRtlWow64EnableFsRedirectionEx( old
, &cur
);
876 START_TEST(directory
)
878 WCHAR sysdir
[MAX_PATH
];
879 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
882 skip("not running on NT, skipping test\n");
886 pNtClose
= (void *)GetProcAddress(hntdll
, "NtClose");
887 pNtOpenFile
= (void *)GetProcAddress(hntdll
, "NtOpenFile");
888 pNtQueryDirectoryFile
= (void *)GetProcAddress(hntdll
, "NtQueryDirectoryFile");
889 pNtQueryInformationFile
= (void *)GetProcAddress(hntdll
, "NtQueryInformationFile");
890 pNtSetInformationFile
= (void *)GetProcAddress(hntdll
, "NtSetInformationFile");
891 pRtlCreateUnicodeStringFromAsciiz
= (void *)GetProcAddress(hntdll
, "RtlCreateUnicodeStringFromAsciiz");
892 pRtlDosPathNameToNtPathName_U
= (void *)GetProcAddress(hntdll
, "RtlDosPathNameToNtPathName_U");
893 pRtlInitUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlInitUnicodeString");
894 pRtlFreeUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlFreeUnicodeString");
895 pRtlCompareUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlCompareUnicodeString");
896 pRtlMultiByteToUnicodeN
= (void *)GetProcAddress(hntdll
,"RtlMultiByteToUnicodeN");
897 pRtlWow64EnableFsRedirection
= (void *)GetProcAddress(hntdll
,"RtlWow64EnableFsRedirection");
898 pRtlWow64EnableFsRedirectionEx
= (void *)GetProcAddress(hntdll
,"RtlWow64EnableFsRedirectionEx");
900 GetSystemDirectoryW( sysdir
, MAX_PATH
);
901 test_directory_sort( sysdir
);
902 test_NtQueryDirectoryFile();
903 test_NtQueryDirectoryFile_case();