[PATCH 4/4] ntdll/tests: Add a test for NtQueryDirectoryFile returning partial results.
Matteo Bruni
mbruni at codeweavers.com
Thu Aug 27 14:08:41 CDT 2015
---
dlls/ntdll/tests/directory.c | 169 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
diff --git a/dlls/ntdll/tests/directory.c b/dlls/ntdll/tests/directory.c
index 5850858..c83c91e 100644
--- a/dlls/ntdll/tests/directory.c
+++ b/dlls/ntdll/tests/directory.c
@@ -374,6 +374,174 @@ done:
pRtlFreeUnicodeString(&ntdirname);
}
+static void set_up_partial_test(const char *testdir)
+{
+ static const char suffix[] = ".tmp";
+ char buf[MAX_PATH], i;
+ BOOL ret;
+ HANDLE h;
+
+ ret = CreateDirectoryA(testdir, NULL);
+ ok(ret, "Failed to create dir '%s', error %d.\n", testdir, GetLastError());
+
+ for (i = 'a'; i <= 'z'; i++)
+ {
+ sprintf(buf, "%s\\%c%s", testdir, i, suffix);
+ h = CreateFileA(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ ok(h != INVALID_HANDLE_VALUE, "failed to create temp file %s.\n", buf);
+ CloseHandle(h);
+ }
+}
+
+static void tear_down_partial_test(const char *testdir)
+{
+ static const char suffix[] = ".tmp";
+ char buf[MAX_PATH], i;
+ int ret;
+
+ for (i = 'a'; i <= 'z'; i++)
+ {
+ sprintf(buf, "%s\\%c%s", testdir, i, suffix);
+ ret = DeleteFileA(buf);
+ ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
+ "Failed to delete %s, error %d.\n", buf, GetLastError());
+ }
+ RemoveDirectoryA(testdir);
+}
+
+static void test_NtQueryDirectoryFile_partial(void)
+{
+ static const WCHAR dotdot[] = {'.','.'};
+ static WCHAR testmask[] = {'*','.','*'};
+ WCHAR testsuffix[] = {'.','t','m','p'};
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING ntdirname;
+ char testdir[MAX_PATH];
+ WCHAR testdir_w[MAX_PATH];
+ HANDLE dirh;
+ UNICODE_STRING mask;
+ IO_STATUS_BLOCK io;
+ UINT data_size = sizeof(FILE_BOTH_DIRECTORY_INFORMATION), data_len;
+ BYTE data[8192];
+ FILE_BOTH_DIRECTORY_INFORMATION *dir_info = (FILE_BOTH_DIRECTORY_INFORMATION *)data;
+ DWORD status;
+ WCHAR *name;
+ ULONG name_len;
+ unsigned int found[28], i, data_pos;
+ BOOL overflow;
+
+ /* Clean up from prior aborted run, if any, then set up test files */
+ ok(GetTempPathA(MAX_PATH, testdir), "Failed to get temp dir.\n");
+ strcat(testdir, "partial.tmp");
+ tear_down_partial_test(testdir);
+ set_up_partial_test(testdir);
+
+ pRtlMultiByteToUnicodeN(testdir_w, sizeof(testdir_w), NULL, testdir, strlen(testdir) + 1);
+ if (!pRtlDosPathNameToNtPathName_U(testdir_w, &ntdirname, NULL, NULL))
+ {
+ ok(0, "RtlDosPathNametoNtPathName_U failed.\n");
+ goto done;
+ }
+ InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
+
+ status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
+ ok(status == STATUS_SUCCESS, "Failed to open dir '%s', ret 0x%x, error %d.\n", testdir, status, GetLastError());
+ if (status != STATUS_SUCCESS)
+ {
+ skip("Skipping the test.\n");
+ return;
+ }
+
+ mask.Buffer = testmask;
+ mask.Length = mask.MaximumLength = sizeof(testmask);
+
+ for (;;)
+ {
+ memset(found, 0, sizeof(found));
+ data_pos = 0;
+ overflow = FALSE;
+
+ memset(data, 0xaa, sizeof(data));
+ pNtQueryDirectoryFile(dirh, NULL, NULL, NULL, &io, data, data_size,
+ FileBothDirectoryInformation, FALSE, &mask, TRUE);
+ ok(U(io).Status == STATUS_SUCCESS || U(io).Status == STATUS_BUFFER_OVERFLOW,
+ "Unexpected status %#x.\n", U(io).Status);
+ if (U(io).Status == STATUS_BUFFER_OVERFLOW)
+ {
+ data_size += sizeof(*dir_info);
+ continue;
+ }
+
+ data_len = io.Information;
+ ok(data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "Unexpected data_len %u.\n", data_len);
+ for (i = data_len; i < sizeof(data); i++)
+ ok(data[i] == 0xaa, "Byte %u modified, value %u.\n", i, data[i]);
+
+ for (;;)
+ {
+ dir_info = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + data_pos);
+
+ name = dir_info->FileName;
+ name_len = dir_info->FileNameLength / sizeof(WCHAR);
+
+ ok(!(dir_info->NextEntryOffset & 0x7), "Entry not aligned to 8 bytes, offset %u.\n", dir_info->NextEntryOffset);
+
+ if (name_len == 1 && !memcmp(name, dotdot, sizeof(WCHAR)))
+ found[26]++;
+ else if (name_len == 2 && !memcmp(name, dotdot, sizeof(dotdot)))
+ found[27]++;
+ else if (name_len == sizeof(testsuffix) / sizeof(WCHAR) + 1
+ && name[0] >= 'a' && name[0] <= 'z' && !memcmp(name + 1, testsuffix, sizeof(testsuffix)))
+ found[name[0] - 'a']++;
+ else
+ ok(0, "Found unexpected file %s (name_len %u, data_size %u, data_len %u, data_pos %u).\n",
+ wine_dbgstr_wn(name, name_len), name_len, data_size, data_len, data_pos);
+
+ if (!dir_info->NextEntryOffset)
+ {
+ pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
+ FileBothDirectoryInformation, FALSE, &mask, FALSE);
+ if (U(io).Status == STATUS_NO_MORE_FILES)
+ break;
+ if (U(io).Status == STATUS_BUFFER_OVERFLOW)
+ {
+ overflow = TRUE;
+ break;
+ }
+ ok(U(io).Status == STATUS_SUCCESS, "Failed to query directory; status %x.\n", U(io).Status);
+
+ data_len = io.Information;
+ ok(data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "Unexpected data_len %u.\n", data_len);
+ data_pos = 0;
+ }
+ else
+ {
+ data_pos += dir_info->NextEntryOffset;
+ }
+ }
+
+ if (!overflow)
+ {
+ for (i = 0; i < 28; i++)
+ /* Win7 somehow skips the ".." entry when data_size == 192. */
+ ok(found[i] == 1 || broken(data_size == 192 && i == 27),
+ "Found %u entries for file %u, data_size %u.\n", found[i], i, data_size);
+ }
+
+ data_size += sizeof(*dir_info);
+ if (data_size > sizeof(data))
+ break;
+ }
+
+ pNtClose(dirh);
+
+done:
+ tear_down_partial_test(testdir);
+ pRtlFreeUnicodeString(&ntdirname);
+}
+
static void test_redirection(void)
{
ULONG old, cur;
@@ -444,5 +612,6 @@ START_TEST(directory)
test_NtQueryDirectoryFile();
test_NtQueryDirectoryFile_case();
+ test_NtQueryDirectoryFile_partial();
test_redirection();
}
--
2.4.6
More information about the wine-patches
mailing list