From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/path.c | 18 ++++++++++++++---- dlls/ntdll/path.c | 22 +++++++++++++++++----- 2 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c index 3c57e81f4c6..eb2c551dcca 100644 --- a/dlls/kernel32/tests/path.c +++ b/dlls/kernel32/tests/path.c @@ -450,6 +450,8 @@ static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir) CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH]; char *buffer; DWORD len,len1; + HANDLE handle; + BOOL ret; /* Save the original directory, so that we can return to it at the end of the test */ @@ -505,10 +507,18 @@ static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir) sprintf(tmpstr,"%s\",newdir); test_setdir(origdir,tmpstr,newdir,1,"check 1"); test_setdir(origdir,newdir,NULL,1,"check 2"); -/* Set the directory to the working area. We just tested that this works, - so why check it again. -*/ - SetCurrentDirectoryA(newdir); + +/* Check that SetCurrentDirectory doesn't reopen directory file when setting the same directory. */ + handle = NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle; + ret = SetCurrentDirectoryA(newdir); + ok(ret, "SetCurrentDirectoryA failed.\n"); + ok(handle != NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle, "got same handle.\n"); + handle = NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle; + + ret = SetCurrentDirectoryA(newdir); + ok(ret, "SetCurrentDirectoryA failed.\n"); + ok(handle == NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle, "got different handle.\n"); + /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */ sprintf(tmpstr,"%s\%s\%s",newdir,SHORTDIR,NONDIR_SHORT); test_setdir(newdir,tmpstr,NULL,0,"check 3"); diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index cccd000a6c6..889d020bd8e 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -905,13 +905,13 @@ ULONG WINAPI RtlGetCurrentDirectory_U(ULONG buflen, LPWSTR buf) NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir) { FILE_FS_DEVICE_INFORMATION device_info; + ULONG size, compare_size; OBJECT_ATTRIBUTES attr; UNICODE_STRING newdir; IO_STATUS_BLOCK io; CURDIR *curdir; HANDLE handle; NTSTATUS nts; - ULONG size; PWSTR ptr;
newdir.Buffer = NULL; @@ -929,6 +929,22 @@ NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir) goto out; }
+ size = newdir.Length / sizeof(WCHAR); + ptr = newdir.Buffer; + ptr += 4; /* skip ??\ prefix */ + size -= 4; + + if (size && ptr[size - 1] == '\') compare_size = size - 1; + else compare_size = size; + + if (curdir->DosPath.Length == (compare_size + 1) * sizeof(WCHAR) + && !wcsnicmp( curdir->DosPath.Buffer, ptr, compare_size )) + { + TRACE( "dir %s is the same as current.\n", debugstr_us(dir) ); + nts = STATUS_SUCCESS; + goto out; + } + attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.Attributes = OBJ_CASE_INSENSITIVE; @@ -953,10 +969,6 @@ NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir) curdir->Handle = handle;
/* append trailing \ if missing */ - size = newdir.Length / sizeof(WCHAR); - ptr = newdir.Buffer; - ptr += 4; /* skip ??\ prefix */ - size -= 4; if (size && ptr[size - 1] != '\') ptr[size++] = '\';
/* convert ??\UNC\ path to \ prefix */