d2d1: Add a helper to set error state.
[wine.git] / dlls / ntdll / tests / directory.c
blob2c6170b8b451c16a21b2bd54b1d71a508520bf91
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
22 * NOTES
23 * We use function pointers here as there is no import library for NTDLL on
24 * windows.
27 #include <stdio.h>
28 #include <stdarg.h>
30 #include "ntstatus.h"
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"
37 #include "winnls.h"
38 #include "winternl.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) */
65 } testfiles[] = {
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 = ARRAY_SIZE(testfiles);
78 static const int max_test_dir_size = ARRAY_SIZE(testfiles) + 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)
88 int i;
89 BOOL ret;
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++) {
95 WCHAR buf[MAX_PATH];
97 if (lstrcmpW(testfiles[i].name, dotW) == 0 || lstrcmpW(testfiles[i].name, dotdotW) == 0)
98 continue;
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());
105 } else {
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) );
111 CloseHandle(h);
116 static void reset_found_files(void)
118 int i;
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)
127 int i;
129 for (i = 0; i < test_dir_count; i++) {
130 int ret;
131 WCHAR buf[MAX_PATH];
132 if (lstrcmpW(testfiles[i].name, dotW) == 0 || lstrcmpW(testfiles[i].name, dotdotW) == 0)
133 continue;
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());
141 } else {
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)
153 int i;
154 DWORD attribmask =
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)))
163 continue;
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++;
170 break;
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;
181 IO_STATUS_BLOCK io;
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;
186 NTSTATUS status;
187 int numfiles;
188 int i;
190 reset_found_files();
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");
201 return;
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 );
214 pNtClose(dirh);
216 data_pos = 0;
217 numfiles = 0;
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))
232 break;
233 data_pos = 0;
234 } else {
235 data_pos += dir_info->NextEntryOffset;
237 numfiles++;
239 ok(numfiles < max_test_dir_size, "too many loops\n");
241 if (mask)
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) ));
247 else
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);
251 pNtClose(new_dirh);
254 static void test_directory_sort( const WCHAR *testdir )
256 OBJECT_ATTRIBUTES attr;
257 UNICODE_STRING ntdirname;
258 IO_STATUS_BLOCK io;
259 UINT data_pos, data_len, count;
260 BYTE data[8192];
261 WCHAR prev[MAX_PATH], name[MAX_PATH];
262 UNICODE_STRING prev_str, name_str;
263 FILE_BOTH_DIRECTORY_INFORMATION *info;
264 NTSTATUS status;
265 HANDLE handle;
266 int res;
268 if (!pRtlDosPathNameToNtPathName_U( testdir, &ntdirname, NULL, NULL ))
270 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
271 return;
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" );
285 data_pos = 0;
286 count = 0;
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;
294 switch (count)
296 case 0: /* first entry must be '.' */
297 ok( !lstrcmpW( name, dotW ), "wrong name %s\n", wine_dbgstr_w( name ));
298 break;
299 case 1: /* second entry must be '..' */
300 ok( !lstrcmpW( name, dotdotW ), "wrong name %s\n", wine_dbgstr_w( name ));
301 break;
302 case 2: /* nothing to compare against */
303 break;
304 default:
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 ));
309 break;
311 count++;
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;
323 data_pos = 0;
325 else data_pos += info->NextEntryOffset;
328 pNtClose( handle );
329 pRtlFreeUnicodeString( &ntdirname );
332 static void test_NtQueryDirectoryFile_classes( HANDLE handle, UNICODE_STRING *mask )
334 IO_STATUS_BLOCK io;
335 UINT data_size;
336 ULONG data[256];
337 NTSTATUS status;
338 int class;
340 for (class = 0; class < FileMaximumInformation; class++)
342 U(io).Status = 0xdeadbeef;
343 U(io).Information = 0xdeadbeef;
344 data_size = 0;
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] );
353 switch (class)
355 case FileIdGlobalTxDirectoryInformation:
356 case FileIdExtdDirectoryInformation:
357 case FileIdExtdBothDirectoryInformation:
358 if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED) continue;
359 /* fall through */
360 case FileDirectoryInformation:
361 case FileFullDirectoryInformation:
362 case FileBothDirectoryInformation:
363 case FileNamesInformation:
364 case FileIdBothDirectoryInformation:
365 case FileIdFullDirectoryInformation:
366 case FileObjectIdInformation:
367 case FileQuotaInformation:
368 case FileReparsePointInformation:
369 ok( status == STATUS_INFO_LENGTH_MISMATCH, "%u: wrong status %x\n", class, status );
370 break;
371 default:
372 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED,
373 "%u: wrong status %x\n", class, status );
374 continue;
377 for (data_size = 1; data_size < sizeof(data); data_size++)
379 status = pNtQueryDirectoryFile( handle, 0, NULL, NULL, &io, data, data_size,
380 class, FALSE, mask, TRUE );
381 if (status == STATUS_BUFFER_OVERFLOW)
383 ok( U(io).Status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, U(io).Status );
384 ok( U(io).Information == data_size, "%u: wrong info %lx\n", class, U(io).Information );
385 ok(data[0] == 0, "%u: wrong offset %x\n", class, data[0] );
387 else
389 ok( U(io).Status == 0xdeadbeef, "%u: wrong status %x\n", class, U(io).Status );
390 ok( U(io).Information == 0xdeadbeef, "%u: wrong info %lx\n", class, U(io).Information );
391 ok(data[0] == 0x55555555, "%u: wrong offset %x\n", class, data[0] );
393 if (status != STATUS_INFO_LENGTH_MISMATCH) break;
396 switch (class)
398 case FileDirectoryInformation:
399 ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
400 ok( data_size == ((offsetof( FILE_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
401 "%u: wrong size %u\n", class, data_size );
402 break;
403 case FileFullDirectoryInformation:
404 ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
405 ok( data_size == ((offsetof( FILE_FULL_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
406 "%u: wrong size %u\n", class, data_size );
407 break;
408 case FileBothDirectoryInformation:
409 ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
410 ok( data_size == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
411 "%u: wrong size %u\n", class, data_size );
412 break;
413 case FileNamesInformation:
414 ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
415 ok( data_size == ((offsetof( FILE_NAMES_INFORMATION, FileName[1] ) + 7) & ~7),
416 "%u: wrong size %u\n", class, data_size );
417 break;
418 case FileIdBothDirectoryInformation:
419 ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
420 ok( data_size == ((offsetof( FILE_ID_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
421 "%u: wrong size %u\n", class, data_size );
422 break;
423 case FileIdFullDirectoryInformation:
424 ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
425 ok( data_size == ((offsetof( FILE_ID_FULL_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
426 "%u: wrong size %u\n", class, data_size );
427 break;
428 case FileIdGlobalTxDirectoryInformation:
429 ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
430 ok( data_size == ((offsetof( FILE_ID_GLOBAL_TX_DIR_INFORMATION, FileName[1] ) + 7) & ~7),
431 "%u: wrong size %u\n", class, data_size );
432 break;
433 case FileObjectIdInformation:
434 ok( status == STATUS_INVALID_INFO_CLASS, "%u: wrong status %x\n", class, status );
435 ok( data_size == sizeof(FILE_OBJECTID_INFORMATION), "%u: wrong size %u\n", class, data_size );
436 break;
437 case FileQuotaInformation:
438 ok( status == STATUS_INVALID_INFO_CLASS, "%u: wrong status %x\n", class, status );
439 ok( data_size == sizeof(FILE_QUOTA_INFORMATION), "%u: wrong size %u\n", class, data_size );
440 break;
441 case FileReparsePointInformation:
442 ok( status == STATUS_INVALID_INFO_CLASS, "%u: wrong status %x\n", class, status );
443 ok( data_size == sizeof(FILE_REPARSE_POINT_INFORMATION), "%u: wrong size %u\n", class, data_size );
444 break;
449 static void test_NtQueryDirectoryFile(void)
451 OBJECT_ATTRIBUTES attr;
452 UNICODE_STRING ntdirname, mask;
453 char testdirA[MAX_PATH];
454 WCHAR testdirW[MAX_PATH];
455 int i;
456 IO_STATUS_BLOCK io;
457 WCHAR short_name[12];
458 UINT data_size;
459 BYTE data[8192];
460 FILE_BOTH_DIRECTORY_INFORMATION *next, *fbdi = (FILE_BOTH_DIRECTORY_INFORMATION*)data;
461 FILE_POSITION_INFORMATION pos_info;
462 FILE_NAMES_INFORMATION *names;
463 const WCHAR *filename = fbdi->FileName;
464 NTSTATUS status;
465 HANDLE dirh;
467 /* Clean up from prior aborted run, if any, then set up test files */
468 ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n");
469 strcat(testdirA, "NtQueryDirectoryFile.tmp");
470 pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1);
471 tear_down_attribute_test(testdirW);
472 set_up_attribute_test(testdirW);
474 if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL))
476 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
477 goto done;
479 InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
481 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, TRUE);
482 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, FALSE);
483 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, TRUE);
484 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, FALSE);
486 for (i = 0; i < test_dir_count; i++)
488 if (testfiles[i].name[0] == '.') continue; /* . and .. as masks are broken on Windows */
489 mask.Buffer = testfiles[i].name;
490 mask.Length = mask.MaximumLength = lstrlenW(testfiles[i].name) * sizeof(WCHAR);
491 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, TRUE);
492 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, FALSE);
493 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, TRUE);
494 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, FALSE);
497 /* short path passed as mask */
498 status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
499 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
500 ok(status == STATUS_SUCCESS, "failed to open dir '%s'\n", testdirA);
501 if (status != STATUS_SUCCESS) {
502 skip("can't test if we can't open the directory\n");
503 return;
505 status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
506 ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
507 ok( pos_info.CurrentByteOffset.QuadPart == 0, "wrong pos %s\n",
508 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart));
510 pos_info.CurrentByteOffset.QuadPart = 0xbeef;
511 status = pNtSetInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
512 ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
514 status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
515 ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
516 ok( pos_info.CurrentByteOffset.QuadPart == 0xbeef, "wrong pos %s\n",
517 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart));
519 mask.Buffer = testfiles[0].name;
520 mask.Length = mask.MaximumLength = lstrlenW(testfiles[0].name) * sizeof(WCHAR);
521 data_size = offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[256]);
522 U(io).Status = 0xdeadbeef;
523 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
524 FileBothDirectoryInformation, TRUE, &mask, FALSE);
525 ok(status == STATUS_SUCCESS, "failed to query directory; status %x\n", status);
526 ok(U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
527 ok(fbdi->ShortName[0], "ShortName is empty\n");
529 status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
530 ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
531 ok( pos_info.CurrentByteOffset.QuadPart == 0xbeef, "wrong pos %s\n",
532 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart) );
534 mask.Length = mask.MaximumLength = fbdi->ShortNameLength;
535 memcpy(short_name, fbdi->ShortName, mask.Length);
536 mask.Buffer = short_name;
537 U(io).Status = 0xdeadbeef;
538 U(io).Information = 0xdeadbeef;
539 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
540 FileBothDirectoryInformation, TRUE, &mask, TRUE);
541 ok(status == STATUS_SUCCESS, "failed to query directory status %x\n", status);
542 ok(U(io).Status == STATUS_SUCCESS, "failed to query directory status %x\n", U(io).Status);
543 ok(U(io).Information == offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[lstrlenW(testfiles[0].name)]),
544 "wrong info %lx\n", U(io).Information);
545 ok(fbdi->FileNameLength == lstrlenW(testfiles[0].name)*sizeof(WCHAR) &&
546 !memcmp(fbdi->FileName, testfiles[0].name, fbdi->FileNameLength),
547 "incorrect long file name: %s\n", wine_dbgstr_wn(fbdi->FileName,
548 fbdi->FileNameLength/sizeof(WCHAR)));
550 status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
551 ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
552 ok( pos_info.CurrentByteOffset.QuadPart == 0xbeef, "wrong pos %s\n",
553 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart) );
555 /* tests with short buffer */
556 memset( data, 0x55, data_size );
557 U(io).Status = 0xdeadbeef;
558 U(io).Information = 0xdeadbeef;
559 data_size = offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] );
560 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
561 FileBothDirectoryInformation, TRUE, &mask, TRUE);
562 ok( status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", status );
563 ok( U(io).Status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", U(io).Status );
564 ok( U(io).Information == data_size || broken( U(io).Information == 0),
565 "wrong info %lx\n", U(io).Information );
566 ok( fbdi->NextEntryOffset == 0, "wrong offset %x\n", fbdi->NextEntryOffset );
567 ok( fbdi->FileNameLength == lstrlenW(testfiles[0].name) * sizeof(WCHAR),
568 "wrong length %x\n", fbdi->FileNameLength );
569 ok( filename[0] == testfiles[0].name[0], "incorrect long file name: %s\n",
570 wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
571 ok( filename[1] == 0x5555, "incorrect long file name: %s\n",
572 wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
574 test_NtQueryDirectoryFile_classes( dirh, &mask );
576 /* mask may or may not be ignored when restarting the search */
577 pRtlInitUnicodeString( &mask, dummyW );
578 U(io).Status = 0xdeadbeef;
579 data_size = offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] );
580 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
581 FileBothDirectoryInformation, TRUE, &mask, TRUE);
582 ok( status == STATUS_SUCCESS || status == STATUS_NO_MORE_FILES, "wrong status %x\n", status );
583 ok( U(io).Status == status, "wrong status %x / %x\n", U(io).Status, status );
584 if (!status)
585 ok( fbdi->FileNameLength == lstrlenW(testfiles[0].name)*sizeof(WCHAR) &&
586 !memcmp(fbdi->FileName, testfiles[0].name, fbdi->FileNameLength),
587 "incorrect long file name: %s\n",
588 wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
590 pNtClose(dirh);
592 status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
593 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
594 ok(status == STATUS_SUCCESS, "failed to open dir '%s'\n", testdirA);
596 memset( data, 0x55, data_size );
597 data_size = sizeof(data);
598 U(io).Status = 0xdeadbeef;
599 U(io).Information = 0xdeadbeef;
600 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
601 FileBothDirectoryInformation, FALSE, NULL, TRUE);
602 ok(status == STATUS_SUCCESS, "wrong status %x\n", status);
603 ok(U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status);
604 ok(U(io).Information > 0 && U(io).Information < data_size, "wrong info %lx\n", U(io).Information);
605 ok( fbdi->NextEntryOffset == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
606 "wrong offset %x\n", fbdi->NextEntryOffset );
607 ok( fbdi->FileNameLength == sizeof(WCHAR), "wrong length %x\n", fbdi->FileNameLength );
608 ok( fbdi->FileName[0] == '.', "incorrect long file name: %s\n",
609 wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
610 next = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + fbdi->NextEntryOffset);
611 ok( next->NextEntryOffset == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[2] ) + 7) & ~7),
612 "wrong offset %x\n", next->NextEntryOffset );
613 ok( next->FileNameLength == 2 * sizeof(WCHAR), "wrong length %x\n", next->FileNameLength );
614 filename = next->FileName;
615 ok( filename[0] == '.' && filename[1] == '.', "incorrect long file name: %s\n",
616 wine_dbgstr_wn(next->FileName, next->FileNameLength/sizeof(WCHAR)));
618 data_size = fbdi->NextEntryOffset + offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ),
619 memset( data, 0x55, data_size );
620 U(io).Status = 0xdeadbeef;
621 U(io).Information = 0xdeadbeef;
622 status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
623 FileBothDirectoryInformation, FALSE, NULL, TRUE );
624 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
625 ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
626 ok( U(io).Information == offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ),
627 "wrong info %lx\n", U(io).Information );
628 ok( fbdi->NextEntryOffset == 0, "wrong offset %x\n", fbdi->NextEntryOffset );
629 ok( fbdi->FileNameLength == sizeof(WCHAR), "wrong length %x\n", fbdi->FileNameLength );
630 ok( fbdi->FileName[0] == '.', "incorrect long file name: %s\n",
631 wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
632 next = (FILE_BOTH_DIRECTORY_INFORMATION *)&fbdi->FileName[1];
633 ok( next->NextEntryOffset == 0x55555555, "wrong offset %x\n", next->NextEntryOffset );
635 data_size = fbdi->NextEntryOffset + offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[2] ),
636 memset( data, 0x55, data_size );
637 U(io).Status = 0xdeadbeef;
638 U(io).Information = 0xdeadbeef;
639 status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
640 FileBothDirectoryInformation, FALSE, NULL, TRUE );
641 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
642 ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
643 ok( U(io).Information == offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ),
644 "wrong info %lx\n", U(io).Information );
645 ok( fbdi->NextEntryOffset == 0, "wrong offset %x\n", fbdi->NextEntryOffset );
647 data_size = ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7) +
648 offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[2] );
649 memset( data, 0x55, data_size );
650 U(io).Status = 0xdeadbeef;
651 U(io).Information = 0xdeadbeef;
652 status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
653 FileBothDirectoryInformation, FALSE, NULL, TRUE );
654 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
655 ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
656 ok( U(io).Information == data_size, "wrong info %lx / %x\n", U(io).Information, data_size );
657 ok( fbdi->NextEntryOffset == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
658 "wrong offset %x\n", fbdi->NextEntryOffset );
659 ok( fbdi->FileNameLength == sizeof(WCHAR), "wrong length %x\n", fbdi->FileNameLength );
660 ok( fbdi->FileName[0] == '.', "incorrect long file name: %s\n",
661 wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
662 next = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + fbdi->NextEntryOffset);
663 ok( next->NextEntryOffset == 0, "wrong offset %x\n", next->NextEntryOffset );
664 ok( next->FileNameLength == 2 * sizeof(WCHAR), "wrong length %x\n", next->FileNameLength );
665 filename = next->FileName;
666 ok( filename[0] == '.' && filename[1] == '.', "incorrect long file name: %s\n",
667 wine_dbgstr_wn(next->FileName, next->FileNameLength/sizeof(WCHAR)));
669 data_size = ((offsetof( FILE_NAMES_INFORMATION, FileName[1] ) + 7) & ~7) +
670 offsetof( FILE_NAMES_INFORMATION, FileName[2] );
671 memset( data, 0x55, data_size );
672 U(io).Status = 0xdeadbeef;
673 U(io).Information = 0xdeadbeef;
674 status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
675 FileNamesInformation, FALSE, NULL, TRUE );
676 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
677 ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
678 ok( U(io).Information == data_size, "wrong info %lx / %x\n", U(io).Information, data_size );
679 names = (FILE_NAMES_INFORMATION *)data;
680 ok( names->NextEntryOffset == ((offsetof( FILE_NAMES_INFORMATION, FileName[1] ) + 7) & ~7),
681 "wrong offset %x\n", names->NextEntryOffset );
682 ok( names->FileNameLength == sizeof(WCHAR), "wrong length %x\n", names->FileNameLength );
683 ok( names->FileName[0] == '.', "incorrect long file name: %s\n",
684 wine_dbgstr_wn(names->FileName, names->FileNameLength/sizeof(WCHAR)));
685 names = (FILE_NAMES_INFORMATION *)(data + names->NextEntryOffset);
686 ok( names->NextEntryOffset == 0, "wrong offset %x\n", names->NextEntryOffset );
687 ok( names->FileNameLength == 2 * sizeof(WCHAR), "wrong length %x\n", names->FileNameLength );
688 filename = names->FileName;
689 ok( filename[0] == '.' && filename[1] == '.', "incorrect long file name: %s\n",
690 wine_dbgstr_wn(names->FileName, names->FileNameLength/sizeof(WCHAR)));
692 pNtClose(dirh);
694 /* create new handle to change mask */
695 status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
696 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
697 ok(status == STATUS_SUCCESS, "failed to open dir '%s'\n", testdirA);
699 pRtlInitUnicodeString( &mask, dummyW );
700 U(io).Status = 0xdeadbeef;
701 data_size = sizeof(data);
702 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
703 FileBothDirectoryInformation, TRUE, &mask, TRUE);
704 ok(status == STATUS_NO_SUCH_FILE, "wrong status %x\n", status);
705 ok(U(io).Status == 0xdeadbeef, "wrong status %x\n", U(io).Status);
707 U(io).Status = 0xdeadbeef;
708 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
709 FileBothDirectoryInformation, TRUE, NULL, FALSE);
710 ok(status == STATUS_NO_MORE_FILES, "wrong status %x\n", status);
711 ok(U(io).Status == STATUS_NO_MORE_FILES, "wrong status %x\n", U(io).Status);
713 U(io).Status = 0xdeadbeef;
714 status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
715 FileBothDirectoryInformation, TRUE, NULL, TRUE);
716 ok(status == STATUS_NO_MORE_FILES, "wrong status %x\n", status);
717 ok(U(io).Status == STATUS_NO_MORE_FILES, "wrong status %x\n", U(io).Status);
719 pNtClose(dirh);
721 U(io).Status = 0xdeadbeef;
722 status = pNtQueryDirectoryFile( (HANDLE)0xbeef, 0, NULL, NULL, &io, data, data_size,
723 FileBothDirectoryInformation, TRUE, NULL, TRUE );
724 ok(status == STATUS_INVALID_HANDLE, "wrong status %x\n", status);
725 ok(U(io).Status == 0xdeadbeef, "wrong status %x\n", U(io).Status);
727 done:
728 test_directory_sort( testdirW );
729 tear_down_attribute_test( testdirW );
730 pRtlFreeUnicodeString(&ntdirname);
733 static void set_up_case_test(const char *testdir)
735 BOOL ret;
736 char buf[MAX_PATH];
737 HANDLE h;
739 ret = CreateDirectoryA(testdir, NULL);
740 ok(ret, "couldn't create dir '%s', error %d\n", testdir, GetLastError());
742 sprintf(buf, "%s\\%s", testdir, "TesT");
743 h = CreateFileA(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
744 FILE_ATTRIBUTE_NORMAL, 0);
745 ok(h != INVALID_HANDLE_VALUE, "failed to create temp file '%s'\n", buf);
746 CloseHandle(h);
749 static void tear_down_case_test(const char *testdir)
751 int ret;
752 char buf[MAX_PATH];
754 sprintf(buf, "%s\\%s", testdir, "TesT");
755 ret = DeleteFileA(buf);
756 ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
757 "Failed to rm %s, error %d\n", buf, GetLastError());
758 RemoveDirectoryA(testdir);
761 static void test_NtQueryDirectoryFile_case(void)
763 static const char testfile[] = "TesT";
764 static const WCHAR testfile_w[] = {'T','e','s','T'};
765 static int testfile_len = sizeof(testfile) - 1;
766 static WCHAR testmask[] = {'t','e','s','t'};
767 OBJECT_ATTRIBUTES attr;
768 UNICODE_STRING ntdirname;
769 char testdir[MAX_PATH];
770 WCHAR testdir_w[MAX_PATH];
771 HANDLE dirh;
772 UNICODE_STRING mask;
773 IO_STATUS_BLOCK io;
774 UINT data_size, data_len;
775 BYTE data[8192];
776 FILE_BOTH_DIRECTORY_INFORMATION *dir_info = (FILE_BOTH_DIRECTORY_INFORMATION *)data;
777 DWORD status;
778 WCHAR *name;
779 ULONG name_len;
781 /* Clean up from prior aborted run, if any, then set up test files */
782 ok(GetTempPathA(MAX_PATH, testdir), "couldn't get temp dir\n");
783 strcat(testdir, "case.tmp");
784 tear_down_case_test(testdir);
785 set_up_case_test(testdir);
787 pRtlMultiByteToUnicodeN(testdir_w, sizeof(testdir_w), NULL, testdir, strlen(testdir) + 1);
788 if (!pRtlDosPathNameToNtPathName_U(testdir_w, &ntdirname, NULL, NULL))
790 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
791 goto done;
793 InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
795 data_size = offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[256]);
797 status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
798 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
799 ok (status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%x, error %d\n", testdir, status, GetLastError());
800 if (status != STATUS_SUCCESS)
802 skip("can't test if we can't open the directory\n");
803 return;
806 mask.Buffer = testmask;
807 mask.Length = mask.MaximumLength = sizeof(testmask);
808 pNtQueryDirectoryFile(dirh, NULL, NULL, NULL, &io, data, data_size,
809 FileBothDirectoryInformation, TRUE, &mask, FALSE);
810 ok(U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
811 data_len = io.Information;
812 ok(data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n");
814 name = dir_info->FileName;
815 name_len = dir_info->FileNameLength / sizeof(WCHAR);
817 ok(name_len == testfile_len, "unexpected filename length %u\n", name_len);
818 ok(!memcmp(name, testfile_w, testfile_len * sizeof(WCHAR)), "unexpected filename %s\n",
819 wine_dbgstr_wn(name, name_len));
821 pNtClose(dirh);
823 done:
824 tear_down_case_test(testdir);
825 pRtlFreeUnicodeString(&ntdirname);
828 static void test_redirection(void)
830 ULONG old, cur;
831 NTSTATUS status;
833 if (!pRtlWow64EnableFsRedirection || !pRtlWow64EnableFsRedirectionEx)
835 skip( "Wow64 redirection not supported\n" );
836 return;
838 status = pRtlWow64EnableFsRedirectionEx( FALSE, &old );
839 if (status == STATUS_NOT_IMPLEMENTED)
841 skip( "Wow64 redirection not supported\n" );
842 return;
844 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
846 status = pRtlWow64EnableFsRedirectionEx( FALSE, &cur );
847 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
848 ok( !cur, "RtlWow64EnableFsRedirectionEx got %u\n", cur );
850 status = pRtlWow64EnableFsRedirectionEx( TRUE, &cur );
851 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
852 status = pRtlWow64EnableFsRedirectionEx( TRUE, &cur );
853 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
854 ok( cur == 1, "RtlWow64EnableFsRedirectionEx got %u\n", cur );
856 status = pRtlWow64EnableFsRedirection( TRUE );
857 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
858 status = pRtlWow64EnableFsRedirectionEx( TRUE, &cur );
859 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
860 ok( !cur, "RtlWow64EnableFsRedirectionEx got %u\n", cur );
862 status = pRtlWow64EnableFsRedirectionEx( TRUE, NULL );
863 ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
864 status = pRtlWow64EnableFsRedirectionEx( TRUE, (void*)1 );
865 ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
866 status = pRtlWow64EnableFsRedirectionEx( TRUE, (void*)0xDEADBEEF );
867 ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
869 status = pRtlWow64EnableFsRedirection( FALSE );
870 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
871 status = pRtlWow64EnableFsRedirectionEx( FALSE, &cur );
872 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
873 ok( cur == 1, "RtlWow64EnableFsRedirectionEx got %u\n", cur );
875 pRtlWow64EnableFsRedirectionEx( old, &cur );
878 START_TEST(directory)
880 WCHAR sysdir[MAX_PATH];
881 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
882 if (!hntdll)
884 skip("not running on NT, skipping test\n");
885 return;
888 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
889 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
890 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
891 pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
892 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
893 pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
894 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
895 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
896 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
897 pRtlCompareUnicodeString = (void *)GetProcAddress(hntdll, "RtlCompareUnicodeString");
898 pRtlMultiByteToUnicodeN = (void *)GetProcAddress(hntdll,"RtlMultiByteToUnicodeN");
899 pRtlWow64EnableFsRedirection = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirection");
900 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirectionEx");
902 GetSystemDirectoryW( sysdir, MAX_PATH );
903 test_directory_sort( sysdir );
904 test_NtQueryDirectoryFile();
905 test_NtQueryDirectoryFile_case();
906 test_redirection();