ntdll: Fix NtQueryDirectoryFile behavior on short file names on case insensitive file systems.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2015-12-21 18:42:04 +01:00 committed by Alexandre Julliard
parent 0125ef6dd7
commit a8ef261493
2 changed files with 38 additions and 17 deletions

View File

@ -2120,15 +2120,6 @@ static int read_directory_stat( int fd, IO_STATUS_BLOCK *io, void *buffer, ULONG
}
else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
}
else if (!case_sensitive && ret && (errno == ENOENT || errno == ENOTDIR))
{
/* If the file does not exist, return that info.
* If the file DOES exist, return failure and fallback to the next
* read_directory_* function (we need to return the case-preserved
* filename stored on the filesystem). */
ret = 0;
io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
}
else
{
ret = -1;
@ -2214,11 +2205,6 @@ static int read_directory_getattrlist( int fd, IO_STATUS_BLOCK *io, void *buffer
}
else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
}
else if ((errno == ENOENT || errno == ENOTDIR) && !get_dir_case_sensitivity("."))
{
io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
ret = 0;
}
}
else ret = -1;

View File

@ -60,6 +60,7 @@ static struct testfile_s {
int nfound; /* How many were found (expect 1) */
WCHAR nameW[20]; /* unicode version of name (filled in later) */
} testfiles[] = {
{ 0, 0, FILE_ATTRIBUTE_NORMAL, "longfilename.tmp", NULL, "normal" },
{ 0, 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" },
{ 1, 0, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" },
{ 1, 0, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" },
@ -234,10 +235,17 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
static void test_NtQueryDirectoryFile(void)
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING ntdirname;
UNICODE_STRING ntdirname, mask;
char testdirA[MAX_PATH];
WCHAR testdirW[MAX_PATH];
int i;
IO_STATUS_BLOCK io;
WCHAR short_name[12];
UINT data_size;
BYTE data[8192];
FILE_BOTH_DIRECTORY_INFORMATION *fbdi = (FILE_BOTH_DIRECTORY_INFORMATION*)data;
DWORD status;
HANDLE dirh;
/* Clean up from prior aborted run, if any, then set up test files */
ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n");
@ -260,8 +268,6 @@ static void test_NtQueryDirectoryFile(void)
for (i = 0; testfiles[i].name; i++)
{
UNICODE_STRING mask;
if (testfiles[i].nameW[0] == '.') continue; /* . and .. as masks are broken on Windows */
mask.Buffer = testfiles[i].nameW;
mask.Length = mask.MaximumLength = lstrlenW(testfiles[i].nameW) * sizeof(WCHAR);
@ -271,6 +277,35 @@ static void test_NtQueryDirectoryFile(void)
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, FALSE);
}
/* short path passed as mask */
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'\n", testdirA);
if (status != STATUS_SUCCESS) {
skip("can't test if we can't open the directory\n");
return;
}
mask.Buffer = testfiles[0].nameW;
mask.Length = mask.MaximumLength = lstrlenW(testfiles[0].nameW) * sizeof(WCHAR);
data_size = offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[256]);
pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, &mask, FALSE);
ok(U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
ok(fbdi->ShortName[0], "ShortName is empty\n");
mask.Length = mask.MaximumLength = fbdi->ShortNameLength;
memcpy(short_name, fbdi->ShortName, mask.Length);
mask.Buffer = short_name;
pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, &mask, TRUE);
ok(U(io).Status == STATUS_SUCCESS, "failed to query directory status %x\n", U(io).Status);
ok(fbdi->FileNameLength == strlen(testfiles[0].name)*sizeof(WCHAR) &&
!memcmp(fbdi->FileName, testfiles[0].nameW, fbdi->FileNameLength),
"incorrect long file name: %s\n", wine_dbgstr_wn(fbdi->FileName,
fbdi->FileNameLength/sizeof(WCHAR)));
pNtClose(dirh);
done:
tear_down_attribute_test(testdirA);
pRtlFreeUnicodeString(&ntdirname);