directory.c (c2c66aff) directory.c (f7932ba2)
1/* Unit test suite for Ntdll directory functions
2 *
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2009 Dan Kegel
7 *
8 * This library is free software; you can redistribute it and/or

--- 20 unchanged lines hidden (view full) ---

29
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
33 */
34#define WIN32_NO_STATUS
35
36#include "wine/test.h"
1/* Unit test suite for Ntdll directory functions
2 *
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2009 Dan Kegel
7 *
8 * This library is free software; you can redistribute it and/or

--- 20 unchanged lines hidden (view full) ---

29
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
33 */
34#define WIN32_NO_STATUS
35
36#include "wine/test.h"
37#include "winnls.h"
37#include "wine/winternl.h"
38
39static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
40static NTSTATUS (WINAPI *pNtOpenFile) ( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG );
41static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
42 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
38#include "wine/winternl.h"
39
40static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
41static NTSTATUS (WINAPI *pNtOpenFile) ( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG );
42static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
43 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
44static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,LONG,FILE_INFORMATION_CLASS);
45static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FILE_INFORMATION_CLASS);
43static BOOLEAN (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING,LPCSTR);
44static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
45static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
46static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
46static BOOLEAN (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING,LPCSTR);
47static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
48static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
49static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
50static LONG (WINAPI *pRtlCompareUnicodeString)( const UNICODE_STRING*, const UNICODE_STRING*,BOOLEAN );
47static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
48 LPCSTR src, DWORD srclen );
49static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirection)( BOOLEAN enable );
50static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG disable, ULONG *old_value );
51
52/* The attribute sets to test */
53static struct testfile_s {
54 BOOL attr_done; /* set if attributes were tested for this file already */
55 const DWORD attr; /* desired attribute */
51static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
52 LPCSTR src, DWORD srclen );
53static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirection)( BOOLEAN enable );
54static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG disable, ULONG *old_value );
55
56/* The attribute sets to test */
57static struct testfile_s {
58 BOOL attr_done; /* set if attributes were tested for this file already */
59 const DWORD attr; /* desired attribute */
56 const char *name; /* filename to use */
60 WCHAR name[20]; /* filename to use */
57 const char *target; /* what to point to (only for reparse pts) */
58 const char *description; /* for error messages */
59 int nfound; /* How many were found (expect 1) */
61 const char *target; /* what to point to (only for reparse pts) */
62 const char *description; /* for error messages */
63 int nfound; /* How many were found (expect 1) */
60 WCHAR nameW[20]; /* unicode version of name (filled in later) */
61} testfiles[] = {
64} testfiles[] = {
62 { 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" },
63 { 0, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" },
64 { 0, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" },
65 { 0, FILE_ATTRIBUTE_DIRECTORY, "d.tmp", NULL, "directory" },
66 { 0, FILE_ATTRIBUTE_DIRECTORY, ".", NULL, ". directory" },
67 { 0, FILE_ATTRIBUTE_DIRECTORY, "..", NULL, ".. directory" },
68 { 0, 0, NULL }
65 { 0, FILE_ATTRIBUTE_NORMAL, {'l','o','n','g','f','i','l','e','n','a','m','e','.','t','m','p'}, "normal" },
66 { 0, FILE_ATTRIBUTE_NORMAL, {'n','.','t','m','p',}, "normal" },
67 { 0, FILE_ATTRIBUTE_HIDDEN, {'h','.','t','m','p',}, "hidden" },
68 { 0, FILE_ATTRIBUTE_SYSTEM, {'s','.','t','m','p',}, "system" },
69 { 0, FILE_ATTRIBUTE_DIRECTORY, {'d','.','t','m','p',}, "directory" },
70 { 0, FILE_ATTRIBUTE_NORMAL, {0xe9,'a','.','t','m','p'}, "normal" },
71 { 0, FILE_ATTRIBUTE_NORMAL, {0xc9,'b','.','t','m','p'}, "normal" },
72 { 0, FILE_ATTRIBUTE_NORMAL, {'e','a','.','t','m','p'}, "normal" },
73 { 0, FILE_ATTRIBUTE_DIRECTORY, {'.'}, ". directory" },
74 { 0, FILE_ATTRIBUTE_DIRECTORY, {'.','.'}, ".. directory" }
69};
75};
70static const int max_test_dir_size = 20; /* size of above plus some for .. etc */
76static const int test_dir_count = sizeof(testfiles) / sizeof(testfiles[0]);
77static const int max_test_dir_size = sizeof(testfiles) / sizeof(testfiles[0]) + 5; /* size of above plus some for .. etc */
71
78
79static const WCHAR dummyW[] = {'d','u','m','m','y',0};
80static const WCHAR dotW[] = {'.',0};
81static const WCHAR dotdotW[] = {'.','.',0};
82static const WCHAR backslashW[] = {'\\',0};
83
72/* Create a test directory full of attribute test files, clear counts */
84/* Create a test directory full of attribute test files, clear counts */
73static void set_up_attribute_test(const char *testdirA)
85static void set_up_attribute_test(const WCHAR *testdir)
74{
75 int i;
76 BOOL ret;
77
86{
87 int i;
88 BOOL ret;
89
78 ret = CreateDirectoryA(testdirA, NULL);
79 ok(ret, "couldn't create dir '%s', error %d\n", testdirA, GetLastError());
90 ret = CreateDirectoryW(testdir, NULL);
91 ok(ret, "couldn't create dir %s, error %d\n", wine_dbgstr_w(testdir), GetLastError());
80
92
81 for (i=0; testfiles[i].name; i++) {
82 char buf[MAX_PATH];
83 pRtlMultiByteToUnicodeN(testfiles[i].nameW, sizeof(testfiles[i].nameW), NULL, testfiles[i].name, strlen(testfiles[i].name)+1);
93 for (i=0; i < test_dir_count; i++) {
94 WCHAR buf[MAX_PATH];
84
95
85 if (strcmp(testfiles[i].name, ".") == 0 || strcmp(testfiles[i].name, "..") == 0)
96 if (lstrcmpW(testfiles[i].name, dotW) == 0 || lstrcmpW(testfiles[i].name, dotdotW) == 0)
86 continue;
97 continue;
87 sprintf(buf, "%s\\%s", testdirA, testfiles[i].name);
98 lstrcpyW( buf, testdir );
99 lstrcatW( buf, backslashW );
100 lstrcatW( buf, testfiles[i].name );
88 if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
101 if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
89 ret = CreateDirectoryA(buf, NULL);
90 ok(ret, "couldn't create dir '%s', error %d\n", buf, GetLastError());
102 ret = CreateDirectoryW(buf, NULL);
103 ok(ret, "couldn't create dir %s, error %d\n", wine_dbgstr_w(buf), GetLastError());
91 } else {
104 } else {
92 HANDLE h = CreateFileA(buf,
105 HANDLE h = CreateFileW(buf,
93 GENERIC_READ|GENERIC_WRITE,
94 0, NULL, CREATE_ALWAYS,
95 testfiles[i].attr, 0);
106 GENERIC_READ|GENERIC_WRITE,
107 0, NULL, CREATE_ALWAYS,
108 testfiles[i].attr, 0);
96 ok( h != INVALID_HANDLE_VALUE, "failed to create temp file '%s'\n", buf );
109 ok( h != INVALID_HANDLE_VALUE, "failed to create temp file %s\n", wine_dbgstr_w(buf) );
97 CloseHandle(h);
98 }
99 }
100}
101
102static void reset_found_files(void)
103{
104 int i;
105
110 CloseHandle(h);
111 }
112 }
113}
114
115static void reset_found_files(void)
116{
117 int i;
118
106 for (i = 0; testfiles[i].name; i++)
119 for (i = 0; i < test_dir_count; i++)
107 testfiles[i].nfound = 0;
108}
109
110/* Remove the given test directory and the attribute test files, if any */
120 testfiles[i].nfound = 0;
121}
122
123/* Remove the given test directory and the attribute test files, if any */
111static void tear_down_attribute_test(const char *testdirA)
124static void tear_down_attribute_test(const WCHAR *testdir)
112{
113 int i;
114
125{
126 int i;
127
115 for (i=0; testfiles[i].name; i++) {
128 for (i = 0; i < test_dir_count; i++) {
116 int ret;
129 int ret;
117 char buf[MAX_PATH];
118 if (strcmp(testfiles[i].name, ".") == 0 || strcmp(testfiles[i].name, "..") == 0)
130 WCHAR buf[MAX_PATH];
131 if (lstrcmpW(testfiles[i].name, dotW) == 0 || lstrcmpW(testfiles[i].name, dotdotW) == 0)
119 continue;
132 continue;
120 sprintf(buf, "%s\\%s", testdirA, testfiles[i].name);
133 lstrcpyW( buf, testdir );
134 lstrcatW( buf, backslashW );
135 lstrcatW( buf, testfiles[i].name );
121 if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
136 if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
122 ret = RemoveDirectoryA(buf);
137 ret = RemoveDirectoryW(buf);
123 ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
138 ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
124 "Failed to rmdir %s, error %d\n", buf, GetLastError());
139 "Failed to rmdir %s, error %d\n", wine_dbgstr_w(buf), GetLastError());
125 } else {
140 } else {
126 ret = DeleteFileA(buf);
141 ret = DeleteFileW(buf);
127 ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
142 ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
128 "Failed to rm %s, error %d\n", buf, GetLastError());
143 "Failed to rm %s, error %d\n", wine_dbgstr_w(buf), GetLastError());
129 }
130 }
144 }
145 }
131 RemoveDirectoryA(testdirA);
146 RemoveDirectoryW(testdir);
132}
133
134/* Match one found file against testfiles[], increment count if found */
135static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info)
136{
137 int i;
138 DWORD attribmask =
139 (FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT);
140 DWORD attrib = dir_info->FileAttributes & attribmask;
141 WCHAR *nameW = dir_info->FileName;
142 int namelen = dir_info->FileNameLength / sizeof(WCHAR);
143
147}
148
149/* Match one found file against testfiles[], increment count if found */
150static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info)
151{
152 int i;
153 DWORD attribmask =
154 (FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT);
155 DWORD attrib = dir_info->FileAttributes & attribmask;
156 WCHAR *nameW = dir_info->FileName;
157 int namelen = dir_info->FileNameLength / sizeof(WCHAR);
158
144 for (i=0; testfiles[i].name; i++) {
145 int len = strlen(testfiles[i].name);
146 if (namelen != len || memcmp(nameW, testfiles[i].nameW, len*sizeof(WCHAR)))
159 for (i = 0; i < test_dir_count; i++) {
160 int len = lstrlenW(testfiles[i].name);
161 if (namelen != len || memcmp(nameW, testfiles[i].name, len*sizeof(WCHAR)))
147 continue;
148 if (!testfiles[i].attr_done) {
162 continue;
163 if (!testfiles[i].attr_done) {
149 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);
164 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);
150 testfiles[i].attr_done = TRUE;
151 }
152 testfiles[i].nfound++;
153 break;
154 }
165 testfiles[i].attr_done = TRUE;
166 }
167 testfiles[i].nfound++;
168 break;
169 }
155 ok(testfiles[i].name != NULL, "unexpected file found\n");
170 ok(i < test_dir_count, "unexpected file found %s\n", wine_dbgstr_wn(dir_info->FileName, namelen));
156}
157
158static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char *testdirA,
159 UNICODE_STRING *mask,
160 BOOLEAN single_entry, BOOLEAN restart_flag)
161{
171}
172
173static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char *testdirA,
174 UNICODE_STRING *mask,
175 BOOLEAN single_entry, BOOLEAN restart_flag)
176{
162 HANDLE dirh;
177 UNICODE_STRING dummy_mask;
178 HANDLE dirh, new_dirh;
163 IO_STATUS_BLOCK io;
164 UINT data_pos, data_size;
165 UINT data_len; /* length of dir data */
166 BYTE data[8192]; /* directory data */
167 FILE_BOTH_DIRECTORY_INFORMATION *dir_info;
179 IO_STATUS_BLOCK io;
180 UINT data_pos, data_size;
181 UINT data_len; /* length of dir data */
182 BYTE data[8192]; /* directory data */
183 FILE_BOTH_DIRECTORY_INFORMATION *dir_info;
168 DWORD status;
184 NTSTATUS status;
169 int numfiles;
170 int i;
171
172 reset_found_files();
185 int numfiles;
186 int i;
187
188 reset_found_files();
189 pRtlInitUnicodeString( &dummy_mask, dummyW );
173
174 data_size = mask ? offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] ) : sizeof(data);
175
176 /* Read the directory and note which files are found */
177 status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, attr, &io, FILE_SHARE_READ,
178 FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_DIRECTORY_FILE);
179 ok (status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%x, error %d\n", testdirA, status, GetLastError());
180 if (status != STATUS_SUCCESS) {
181 skip("can't test if we can't open the directory\n");
182 return;
183 }
184
190
191 data_size = mask ? offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] ) : sizeof(data);
192
193 /* Read the directory and note which files are found */
194 status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, attr, &io, FILE_SHARE_READ,
195 FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_DIRECTORY_FILE);
196 ok (status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%x, error %d\n", testdirA, status, GetLastError());
197 if (status != STATUS_SUCCESS) {
198 skip("can't test if we can't open the directory\n");
199 return;
200 }
201
185 pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, data_size,
186 FileBothDirectoryInformation, single_entry, mask, restart_flag );
202 U(io).Status = 0xdeadbeef;
203 status = pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, data_size,
204 FileBothDirectoryInformation, single_entry, mask, restart_flag );
205 ok (status == STATUS_SUCCESS, "failed to query directory; status %x\n", status);
187 ok (U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
188 data_len = io.Information;
189 ok (data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n");
190
206 ok (U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
207 data_len = io.Information;
208 ok (data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n");
209
210 DuplicateHandle( GetCurrentProcess(), dirh, GetCurrentProcess(), &new_dirh,
211 0, FALSE, DUPLICATE_SAME_ACCESS );
212 pNtClose(dirh);
213
191 data_pos = 0;
192 numfiles = 0;
193 while ((data_pos < data_len) && (numfiles < max_test_dir_size)) {
194 dir_info = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + data_pos);
195
196 tally_test_file(dir_info);
197
198 if (dir_info->NextEntryOffset == 0) {
214 data_pos = 0;
215 numfiles = 0;
216 while ((data_pos < data_len) && (numfiles < max_test_dir_size)) {
217 dir_info = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + data_pos);
218
219 tally_test_file(dir_info);
220
221 if (dir_info->NextEntryOffset == 0) {
199 pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
200 FileBothDirectoryInformation, single_entry, mask, FALSE );
201 if (U(io).Status == STATUS_NO_MORE_FILES)
202 break;
203 ok (U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
222 U(io).Status = 0xdeadbeef;
223 status = pNtQueryDirectoryFile( new_dirh, 0, NULL, NULL, &io, data, data_size,
224 FileBothDirectoryInformation, single_entry, &dummy_mask, FALSE );
225 ok (U(io).Status == status, "wrong status %x / %x\n", status, U(io).Status);
226 if (status == STATUS_NO_MORE_FILES) break;
227 ok (status == STATUS_SUCCESS, "failed to query directory; status %x\n", status);
204 data_len = io.Information;
205 if (data_len < sizeof(FILE_BOTH_DIRECTORY_INFORMATION))
206 break;
207 data_pos = 0;
208 } else {
209 data_pos += dir_info->NextEntryOffset;
210 }
211 numfiles++;
212 }
213 ok(numfiles < max_test_dir_size, "too many loops\n");
214
215 if (mask)
228 data_len = io.Information;
229 if (data_len < sizeof(FILE_BOTH_DIRECTORY_INFORMATION))
230 break;
231 data_pos = 0;
232 } else {
233 data_pos += dir_info->NextEntryOffset;
234 }
235 numfiles++;
236 }
237 ok(numfiles < max_test_dir_size, "too many loops\n");
238
239 if (mask)
216 for (i=0; testfiles[i].name; i++)
217 ok(testfiles[i].nfound == (testfiles[i].nameW == mask->Buffer),
240 for (i = 0; i < test_dir_count; i++)
241 ok(testfiles[i].nfound == (testfiles[i].name == mask->Buffer),
218 "Wrong number %d of %s files found (single_entry=%d,mask=%s)\n",
219 testfiles[i].nfound, testfiles[i].description, single_entry,
220 wine_dbgstr_wn(mask->Buffer, mask->Length/sizeof(WCHAR) ));
221 else
242 "Wrong number %d of %s files found (single_entry=%d,mask=%s)\n",
243 testfiles[i].nfound, testfiles[i].description, single_entry,
244 wine_dbgstr_wn(mask->Buffer, mask->Length/sizeof(WCHAR) ));
245 else
222 for (i=0; testfiles[i].name; i++)
246 for (i = 0; i < test_dir_count; i++)
223 ok(testfiles[i].nfound == 1, "Wrong number %d of %s files found (single_entry=%d,restart=%d)\n",
224 testfiles[i].nfound, testfiles[i].description, single_entry, restart_flag);
247 ok(testfiles[i].nfound == 1, "Wrong number %d of %s files found (single_entry=%d,restart=%d)\n",
248 testfiles[i].nfound, testfiles[i].description, single_entry, restart_flag);
225 pNtClose(dirh);
249 pNtClose(new_dirh);
226}
227
250}
251
228static void test_NtQueryDirectoryFile(void)
252static void test_directory_sort( const WCHAR *testdir )
229{
230 OBJECT_ATTRIBUTES attr;
231 UNICODE_STRING ntdirname;
253{
254 OBJECT_ATTRIBUTES attr;
255 UNICODE_STRING ntdirname;
256 IO_STATUS_BLOCK io;
257 UINT data_pos, data_len, count;
258 BYTE data[8192];
259 WCHAR prev[MAX_PATH], name[MAX_PATH];
260 UNICODE_STRING prev_str, name_str;
261 FILE_BOTH_DIRECTORY_INFORMATION *info;
262 NTSTATUS status;
263 HANDLE handle;
264 int res;
265
266 if (!pRtlDosPathNameToNtPathName_U( testdir, &ntdirname, NULL, NULL ))
267 {
268 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
269 return;
270 }
271 InitializeObjectAttributes( &attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL );
272 status = pNtOpenFile( &handle, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
273 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE );
274 ok(status == STATUS_SUCCESS, "failed to open dir %s\n", wine_dbgstr_w(testdir) );
275
276 U(io).Status = 0xdeadbeef;
277 status = pNtQueryDirectoryFile( handle, NULL, NULL, NULL, &io, data, sizeof(data),
278 FileBothDirectoryInformation, FALSE, NULL, TRUE );
279 ok( status == STATUS_SUCCESS, "failed to query directory; status %x\n", status );
280 ok( U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status );
281 data_len = io.Information;
282 ok( data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n" );
283 data_pos = 0;
284 count = 0;
285
286 while (data_pos < data_len)
287 {
288 info = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + data_pos);
289
290 memcpy( name, info->FileName, info->FileNameLength );
291 name[info->FileNameLength / sizeof(WCHAR)] = 0;
292 switch (count)
293 {
294 case 0: /* first entry must be '.' */
295 ok( !lstrcmpW( name, dotW ), "wrong name %s\n", wine_dbgstr_w( name ));
296 break;
297 case 1: /* second entry must be '..' */
298 ok( !lstrcmpW( name, dotdotW ), "wrong name %s\n", wine_dbgstr_w( name ));
299 break;
300 case 2: /* nothing to compare against */
301 break;
302 default:
303 pRtlInitUnicodeString( &prev_str, prev );
304 pRtlInitUnicodeString( &name_str, name );
305 res = pRtlCompareUnicodeString( &prev_str, &name_str, TRUE );
306 ok( res < 0, "wrong result %d %s %s\n", res, wine_dbgstr_w( prev ), wine_dbgstr_w( name ));
307 break;
308 }
309 count++;
310 lstrcpyW( prev, name );
311
312 if (info->NextEntryOffset == 0)
313 {
314 U(io).Status = 0xdeadbeef;
315 status = pNtQueryDirectoryFile( handle, 0, NULL, NULL, &io, data, sizeof(data),
316 FileBothDirectoryInformation, FALSE, NULL, FALSE );
317 ok (U(io).Status == status, "wrong status %x / %x\n", status, U(io).Status);
318 if (status == STATUS_NO_MORE_FILES) break;
319 ok( status == STATUS_SUCCESS, "failed to query directory; status %x\n", status );
320 data_len = io.Information;
321 data_pos = 0;
322 }
323 else data_pos += info->NextEntryOffset;
324 }
325
326 pNtClose( handle );
327 pRtlFreeUnicodeString( &ntdirname );
328}
329
330static void test_NtQueryDirectoryFile_classes( HANDLE handle, UNICODE_STRING *mask )
331{
332 IO_STATUS_BLOCK io;
333 UINT data_size;
334 ULONG data[256];
335 NTSTATUS status;
336 int class;
337
338 for (class = 0; class < FileMaximumInformation; class++)
339 {
340 U(io).Status = 0xdeadbeef;
341 U(io).Information = 0xdeadbeef;
342 data_size = 0;
343 memset( data, 0x55, sizeof(data) );
344
345 status = pNtQueryDirectoryFile( handle, 0, NULL, NULL, &io, data, data_size,
346 class, FALSE, mask, TRUE );
347 ok( U(io).Status == 0xdeadbeef, "%u: wrong status %x\n", class, U(io).Status );
348 ok( U(io).Information == 0xdeadbeef, "%u: wrong info %lx\n", class, U(io).Information );
349 ok(data[0] == 0x55555555, "%u: wrong offset %x\n", class, data[0] );
350
351 switch (class)
352 {
353 case FileIdGlobalTxDirectoryInformation:
354 case FileIdExtdDirectoryInformation:
355 case FileIdExtdBothDirectoryInformation:
356 if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED) continue;
357 /* fall through */
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 );
368 break;
369 default:
370 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED,
371 "%u: wrong status %x\n", class, status );
372 continue;
373 }
374
375 for (data_size = 1; data_size < sizeof(data); data_size++)
376 {
377 status = pNtQueryDirectoryFile( handle, 0, NULL, NULL, &io, data, data_size,
378 class, FALSE, mask, TRUE );
379 if (status == STATUS_BUFFER_OVERFLOW)
380 {
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] );
384 }
385 else
386 {
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] );
390 }
391 if (status != STATUS_INFO_LENGTH_MISMATCH) break;
392 }
393
394 switch (class)
395 {
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 );
400 break;
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 );
405 break;
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 );
410 break;
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 );
415 break;
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 );
420 break;
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 );
425 break;
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 );
430 break;
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 );
434 break;
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 );
438 break;
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 );
442 break;
443 }
444 }
445}
446
447static void test_NtQueryDirectoryFile(void)
448{
449 OBJECT_ATTRIBUTES attr;
450 UNICODE_STRING ntdirname, mask;
232 char testdirA[MAX_PATH];
233 WCHAR testdirW[MAX_PATH];
234 int i;
451 char testdirA[MAX_PATH];
452 WCHAR testdirW[MAX_PATH];
453 int i;
454 IO_STATUS_BLOCK io;
455 WCHAR short_name[12];
456 UINT data_size;
457 BYTE data[8192];
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;
462 NTSTATUS status;
463 HANDLE dirh;
235
236 /* Clean up from prior aborted run, if any, then set up test files */
237 ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n");
238 strcat(testdirA, "NtQueryDirectoryFile.tmp");
464
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");
239 tear_down_attribute_test(testdirA);
240 set_up_attribute_test(testdirA);
241
242 pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1);
468 pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1);
469 tear_down_attribute_test(testdirW);
470 set_up_attribute_test(testdirW);
471
243 if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL))
244 {
245 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
246 goto done;
247 }
248 InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
249
250 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, TRUE);
251 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, FALSE);
252 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, TRUE);
253 test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, FALSE);
254
472 if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL))
473 {
474 ok(0, "RtlDosPathNametoNtPathName_U failed\n");
475 goto done;
476 }
477 InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
478
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);
483
255 for (i = 0; testfiles[i].name; i++)
484 for (i = 0; i < test_dir_count; i++)
256 {
485 {
257 UNICODE_STRING mask;
258
259 if (testfiles[i].nameW[0] == '.') continue; /* . and .. as masks are broken on Windows */
260 mask.Buffer = testfiles[i].nameW;
261 mask.Length = mask.MaximumLength = lstrlenW(testfiles[i].nameW) * sizeof(WCHAR);
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);
262 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, TRUE);
263 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, FALSE);
264 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, TRUE);
265 test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, FALSE);
266 }
267
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);
493 }
494
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");
501 return;
502 }
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 %s\n",
506 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart));
507
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 );
511
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 %s\n",
515 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart));
516
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");
526
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 %s\n",
530 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart) );
531
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)));
547
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 %s\n",
551 wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart) );
552
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)));
571
572 test_NtQueryDirectoryFile_classes( dirh, &mask );
573
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 );
582 if (!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)));
587
588 pNtClose(dirh);
589
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);
593
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)));
615
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 );
632
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 );
644
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)));
666
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)));
689
690 pNtClose(dirh);
691
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);
696
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);
704
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);
710
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);
716
717 pNtClose(dirh);
718
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);
724
268done:
725done:
269 tear_down_attribute_test(testdirA);
726 test_directory_sort( testdirW );
727 tear_down_attribute_test( testdirW );
270 pRtlFreeUnicodeString(&ntdirname);
271}
272
273static void set_up_case_test(const char *testdir)
274{
275 BOOL ret;
276 char buf[MAX_PATH];
277 HANDLE h;

--- 120 unchanged lines hidden (view full) ---

398 status = pRtlWow64EnableFsRedirectionEx( TRUE, &cur );
399 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
400 ok( !cur, "RtlWow64EnableFsRedirectionEx got %u\n", cur );
401
402 status = pRtlWow64EnableFsRedirectionEx( TRUE, NULL );
403 ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
404 status = pRtlWow64EnableFsRedirectionEx( TRUE, (void*)1 );
405 ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
728 pRtlFreeUnicodeString(&ntdirname);
729}
730
731static void set_up_case_test(const char *testdir)
732{
733 BOOL ret;
734 char buf[MAX_PATH];
735 HANDLE h;

--- 120 unchanged lines hidden (view full) ---

856 status = pRtlWow64EnableFsRedirectionEx( TRUE, &cur );
857 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
858 ok( !cur, "RtlWow64EnableFsRedirectionEx got %u\n", cur );
859
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 );
406
407 status = pRtlWow64EnableFsRedirection( FALSE );
408 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
409 status = pRtlWow64EnableFsRedirectionEx( FALSE, &cur );
410 ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
411 ok( cur == 1, "RtlWow64EnableFsRedirectionEx got %u\n", cur );
412
413 pRtlWow64EnableFsRedirectionEx( old, &cur );
414}
415
416START_TEST(directory)
417{
866
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 );
872
873 pRtlWow64EnableFsRedirectionEx( old, &cur );
874}
875
876START_TEST(directory)
877{
878 WCHAR sysdir[MAX_PATH];
418 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
419 if (!hntdll)
420 {
421 skip("not running on NT, skipping test\n");
422 return;
423 }
424
425 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
426 pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
427 pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
879 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
880 if (!hntdll)
881 {
882 skip("not running on NT, skipping test\n");
883 return;
884 }
885
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");
428 pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
429 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
430 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
431 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
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");
432 pRtlMultiByteToUnicodeN = (void *)GetProcAddress(hntdll,"RtlMultiByteToUnicodeN");
433 pRtlWow64EnableFsRedirection = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirection");
434 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirectionEx");
435
896 pRtlMultiByteToUnicodeN = (void *)GetProcAddress(hntdll,"RtlMultiByteToUnicodeN");
897 pRtlWow64EnableFsRedirection = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirection");
898 pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirectionEx");
899
900 GetSystemDirectoryW( sysdir, MAX_PATH );
901 test_directory_sort( sysdir );
436 test_NtQueryDirectoryFile();
437 test_NtQueryDirectoryFile_case();
438 test_redirection();
439}
902 test_NtQueryDirectoryFile();
903 test_NtQueryDirectoryFile_case();
904 test_redirection();
905}