Module: wine Branch: stable Commit: 360c56a361fa93ee675fadc0a39368e51cf6ca02 URL: http://source.winehq.org/git/wine.git/?a=commit;h=360c56a361fa93ee675fadc0a3...
Author: Piotr Caban piotr@codeweavers.com Date: Mon Dec 21 18:42:04 2015 +0100
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 (cherry picked from commit a8ef26149308f577151f14a2d359868754c7ea20) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
dlls/ntdll/directory.c | 14 -------------- dlls/ntdll/tests/directory.c | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 4faafe9..23ebf48 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -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;
diff --git a/dlls/ntdll/tests/directory.c b/dlls/ntdll/tests/directory.c index 730b0f1..7b1002a 100644 --- a/dlls/ntdll/tests/directory.c +++ b/dlls/ntdll/tests/directory.c @@ -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);