[PATCH v4 1/1] ntdll: Do not open directory file when setting the same directory path.

Paul Gofman wine at gitlab.winehq.org
Wed Jun 29 15:11:57 CDT 2022


From: Paul Gofman <pgofman at codeweavers.com>

Signed-off-by: Paul Gofman <pgofman at 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 */
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/256



More information about the wine-devel mailing list