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"
39 static NTSTATUS (WINAPI
*pNtClose
)( PHANDLE
);
40 static NTSTATUS (WINAPI
*pNtOpenFile
) ( PHANDLE
, ACCESS_MASK
, POBJECT_ATTRIBUTES
, PIO_STATUS_BLOCK
, ULONG
, ULONG
);
41 static NTSTATUS (WINAPI
*pNtQueryDirectoryFile
)(HANDLE
,HANDLE
,PIO_APC_ROUTINE
,PVOID
,PIO_STATUS_BLOCK
,
42 PVOID
,ULONG
,FILE_INFORMATION_CLASS
,BOOLEAN
,PUNICODE_STRING
,BOOLEAN
);
43 static BOOLEAN (WINAPI
*pRtlCreateUnicodeStringFromAsciiz
)(PUNICODE_STRING
,LPCSTR
);
44 static BOOL (WINAPI
*pRtlDosPathNameToNtPathName_U
)( LPCWSTR
, PUNICODE_STRING
, PWSTR
*, CURDIR
* );
45 static VOID (WINAPI
*pRtlInitUnicodeString
)( PUNICODE_STRING
, LPCWSTR
);
46 static NTSTATUS (WINAPI
*pRtlMultiByteToUnicodeN
)( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
47 LPCSTR src
, DWORD srclen
);
48 static NTSTATUS (WINAPI
*pRtlWow64EnableFsRedirection
)( BOOLEAN enable
);
49 static NTSTATUS (WINAPI
*pRtlWow64EnableFsRedirectionEx
)( ULONG disable
, ULONG
*old_value
);
51 /* The attribute sets to test */
53 int todo
; /* set if it doesn't work on wine yet */
54 const DWORD attr
; /* desired attribute */
55 const char *name
; /* filename to use */
56 const char *target
; /* what to point to (only for reparse pts) */
57 const char *description
; /* for error messages */
58 int nfound
; /* How many were found (expect 1) */
59 WCHAR nameW
[20]; /* unicode version of name (filled in later) */
61 { 0, FILE_ATTRIBUTE_NORMAL
, "n.tmp", NULL
, "normal" },
62 { 1, FILE_ATTRIBUTE_HIDDEN
, "h.tmp", NULL
, "hidden" },
63 { 1, FILE_ATTRIBUTE_SYSTEM
, "s.tmp", NULL
, "system" },
64 { 0, FILE_ATTRIBUTE_DIRECTORY
, "d.tmp", NULL
, "directory" },
67 static const int max_test_dir_size
= 20; /* size of above plus some for .. etc */
69 /* Create a test directory full of attribute test files, clear counts */
70 static void set_up_attribute_test(const char *testdirA
)
74 ok(CreateDirectoryA(testdirA
, NULL
),
75 "couldn't create dir '%s', error %d\n", testdirA
, GetLastError());
77 for (i
=0; testfiles
[i
].name
; i
++) {
79 pRtlMultiByteToUnicodeN(testfiles
[i
].nameW
, sizeof(testfiles
[i
].nameW
), NULL
, testfiles
[i
].name
, strlen(testfiles
[i
].name
)+1);
81 sprintf(buf
, "%s\\%s", testdirA
, testfiles
[i
].name
);
82 testfiles
[i
].nfound
= 0;
83 if (testfiles
[i
].attr
& FILE_ATTRIBUTE_DIRECTORY
) {
84 ok(CreateDirectoryA(buf
, NULL
),
85 "couldn't create dir '%s', error %d\n", buf
, GetLastError());
87 HANDLE h
= CreateFileA(buf
,
88 GENERIC_READ
|GENERIC_WRITE
,
89 0, NULL
, CREATE_ALWAYS
,
90 testfiles
[i
].attr
, 0);
91 ok( h
!= INVALID_HANDLE_VALUE
, "failed to create temp file '%s'\n", buf
);
97 /* Remove the given test directory and the attribute test files, if any */
98 static void tear_down_attribute_test(const char *testdirA
)
102 for (i
=0; testfiles
[i
].name
; i
++) {
105 sprintf(buf
, "%s\\%s", testdirA
, testfiles
[i
].name
);
106 if (testfiles
[i
].attr
& FILE_ATTRIBUTE_DIRECTORY
) {
107 ret
= RemoveDirectory(buf
);
108 ok(ret
|| (GetLastError() == ERROR_PATH_NOT_FOUND
),
109 "Failed to rmdir %s, error %d\n", buf
, GetLastError());
111 ret
= DeleteFile(buf
);
112 ok(ret
|| (GetLastError() == ERROR_PATH_NOT_FOUND
),
113 "Failed to rm %s, error %d\n", buf
, GetLastError());
116 RemoveDirectoryA(testdirA
);
119 /* Match one found file against testfiles[], increment count if found */
120 static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION
*dir_info
)
124 (FILE_ATTRIBUTE_SYSTEM
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_REPARSE_POINT
);
125 DWORD attrib
= dir_info
->FileAttributes
& attribmask
;
126 WCHAR
*nameW
= dir_info
->FileName
;
127 int namelen
= dir_info
->FileNameLength
/ sizeof(WCHAR
);
132 for (i
=0; testfiles
[i
].name
; i
++) {
133 int len
= strlen(testfiles
[i
].name
);
134 if (namelen
!= len
|| memcmp(nameW
, testfiles
[i
].nameW
, len
*sizeof(WCHAR
)))
136 if (testfiles
[i
].todo
) {
138 ok (attrib
== (testfiles
[i
].attr
& attribmask
), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles
[i
].name
, testfiles
[i
].description
, testfiles
[i
].attr
, attrib
);
140 ok (attrib
== (testfiles
[i
].attr
& attribmask
), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles
[i
].name
, testfiles
[i
].description
, testfiles
[i
].attr
, attrib
);
142 testfiles
[i
].nfound
++;
145 ok(testfiles
[i
].name
!= NULL
, "unexpected file found\n");
148 static void test_NtQueryDirectoryFile(void)
150 OBJECT_ATTRIBUTES attr
;
151 UNICODE_STRING ntdirname
;
152 char testdirA
[MAX_PATH
];
153 WCHAR testdirW
[MAX_PATH
];
157 UINT data_len
; /* length of dir data */
158 BYTE data
[8192]; /* directory data */
159 FILE_BOTH_DIRECTORY_INFORMATION
*dir_info
;
164 /* Clean up from prior aborted run, if any, then set up test files */
165 ok(GetTempPathA(MAX_PATH
, testdirA
), "couldn't get temp dir\n");
166 strcat(testdirA
, "NtQueryDirectoryFile.tmp");
167 tear_down_attribute_test(testdirA
);
168 set_up_attribute_test(testdirA
);
170 /* Read the directory and note which files are found */
171 pRtlMultiByteToUnicodeN(testdirW
, sizeof(testdirW
), NULL
, testdirA
, strlen(testdirA
)+1);
172 if (!pRtlDosPathNameToNtPathName_U(testdirW
, &ntdirname
, NULL
, NULL
))
174 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
177 InitializeObjectAttributes(&attr
, &ntdirname
, 0, 0, NULL
);
178 status
= pNtOpenFile( &dirh
, SYNCHRONIZE
| FILE_LIST_DIRECTORY
, &attr
, &io
,
180 FILE_SYNCHRONOUS_IO_NONALERT
|FILE_OPEN_FOR_BACKUP_INTENT
|FILE_DIRECTORY_FILE
);
181 ok (status
== STATUS_SUCCESS
, "failed to open dir '%s', ret 0x%x, error %d\n", testdirA
, status
, GetLastError());
182 if (status
!= STATUS_SUCCESS
) {
183 skip("can't test if we can't open the directory\n");
187 pNtQueryDirectoryFile( dirh
, NULL
, NULL
, NULL
, &io
, data
, sizeof(data
),
188 FileBothDirectoryInformation
, FALSE
, NULL
, TRUE
);
189 ok (U(io
).Status
== STATUS_SUCCESS
, "filed to query directory; status %x\n", U(io
).Status
);
190 data_len
= io
.Information
;
191 ok (data_len
>= sizeof(FILE_BOTH_DIRECTORY_INFORMATION
), "not enough data in directory\n");
195 while ((data_pos
< data_len
) && (numfiles
< max_test_dir_size
)) {
196 dir_info
= (FILE_BOTH_DIRECTORY_INFORMATION
*)(data
+ data_pos
);
198 tally_test_file(dir_info
);
200 if (dir_info
->NextEntryOffset
== 0) {
201 pNtQueryDirectoryFile( dirh
, 0, NULL
, NULL
, &io
, data
, sizeof(data
),
202 FileBothDirectoryInformation
, FALSE
, NULL
, FALSE
);
203 if (U(io
).Status
== STATUS_NO_MORE_FILES
)
205 ok (U(io
).Status
== STATUS_SUCCESS
, "filed to query directory; status %x\n", U(io
).Status
);
206 data_len
= io
.Information
;
207 if (data_len
< sizeof(FILE_BOTH_DIRECTORY_INFORMATION
))
211 data_pos
+= dir_info
->NextEntryOffset
;
215 ok(numfiles
< max_test_dir_size
, "too many loops\n");
217 for (i
=0; testfiles
[i
].name
; i
++)
218 ok(testfiles
[i
].nfound
== 1, "Wrong number %d of %s files found\n",
219 testfiles
[i
].nfound
, testfiles
[i
].description
);
223 tear_down_attribute_test(testdirA
);
226 static void test_redirection(void)
231 if (!pRtlWow64EnableFsRedirection
|| !pRtlWow64EnableFsRedirectionEx
)
233 skip( "Wow64 redirection not supported\n" );
236 status
= pRtlWow64EnableFsRedirectionEx( FALSE
, &old
);
237 if (status
== STATUS_NOT_IMPLEMENTED
)
239 skip( "Wow64 redirection not supported\n" );
242 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
244 status
= pRtlWow64EnableFsRedirectionEx( FALSE
, &cur
);
245 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
246 ok( !cur
, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
248 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, &cur
);
249 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
250 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, &cur
);
251 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
252 ok( cur
== 1, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
254 status
= pRtlWow64EnableFsRedirection( TRUE
);
255 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
256 status
= pRtlWow64EnableFsRedirectionEx( TRUE
, &cur
);
257 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
258 ok( !cur
, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
260 status
= pRtlWow64EnableFsRedirection( FALSE
);
261 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
262 status
= pRtlWow64EnableFsRedirectionEx( FALSE
, &cur
);
263 ok( !status
, "RtlWow64EnableFsRedirectionEx failed status %x\n", status
);
264 ok( cur
== 1, "RtlWow64EnableFsRedirectionEx got %u\n", cur
);
266 pRtlWow64EnableFsRedirectionEx( old
, &cur
);
269 START_TEST(directory
)
271 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
274 skip("not running on NT, skipping test\n");
278 pNtClose
= (void *)GetProcAddress(hntdll
, "NtClose");
279 pNtOpenFile
= (void *)GetProcAddress(hntdll
, "NtOpenFile");
280 pNtQueryDirectoryFile
= (void *)GetProcAddress(hntdll
, "NtQueryDirectoryFile");
281 pRtlCreateUnicodeStringFromAsciiz
= (void *)GetProcAddress(hntdll
, "RtlCreateUnicodeStringFromAsciiz");
282 pRtlDosPathNameToNtPathName_U
= (void *)GetProcAddress(hntdll
, "RtlDosPathNameToNtPathName_U");
283 pRtlInitUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlInitUnicodeString");
284 pRtlMultiByteToUnicodeN
= (void *)GetProcAddress(hntdll
,"RtlMultiByteToUnicodeN");
285 pRtlWow64EnableFsRedirection
= (void *)GetProcAddress(hntdll
,"RtlWow64EnableFsRedirection");
286 pRtlWow64EnableFsRedirectionEx
= (void *)GetProcAddress(hntdll
,"RtlWow64EnableFsRedirectionEx");
288 test_NtQueryDirectoryFile();