Alexandre Julliard : ntdll: Allocate the buffer in the caller for wine_unix_to_nt_file_name().

Alexandre Julliard julliard at winehq.org
Thu Jul 9 17:10:38 CDT 2020


Module: wine
Branch: master
Commit: 6f862a1ad803b1a7037797cedb3624445538afc1
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6f862a1ad803b1a7037797cedb3624445538afc1

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jul  9 10:03:15 2020 +0200

ntdll: Allocate the buffer in the caller for wine_unix_to_nt_file_name().

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/path.c   | 28 +++++++++++++++-------------
 dlls/ntdll/ntdll.spec  |  2 +-
 dlls/ntdll/path.c      | 35 +++++++++++++++++++----------------
 dlls/ntdll/unix/file.c | 16 +++++++++++++---
 dlls/ntdll/unixlib.h   |  4 ++--
 include/winternl.h     |  2 +-
 6 files changed, 51 insertions(+), 36 deletions(-)

diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index f958610dbd..5377c2302b 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -312,36 +312,38 @@ char * CDECL wine_get_unix_file_name( LPCWSTR dosW )
 WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
 {
     UNICODE_STRING nt_name;
-    ANSI_STRING unix_name;
     NTSTATUS status;
     WCHAR *buffer;
-    DWORD len;
+    SIZE_T len = strlen(str) + 1;
 
     if (str[0] != '/')  /* relative path name */
     {
-        len = strlen( str ) + 1;
         if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
         MultiByteToWideChar( CP_UNIXCP, 0, str, len, buffer, len );
         status = RtlDosPathNameToNtPathName_U_WithStatus( buffer, &nt_name, NULL, NULL );
         RtlFreeHeap( GetProcessHeap(), 0, buffer );
+        if (!set_ntstatus( status )) return NULL;
+        buffer = nt_name.Buffer;
+        len = nt_name.Length / sizeof(WCHAR) + 1;
     }
     else
     {
-        RtlInitAnsiString( &unix_name, str );
-        status = wine_unix_to_nt_file_name( &unix_name, &nt_name );
+        len += 8;  /* \??\unix prefix */
+        if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
+        if (!set_ntstatus( wine_unix_to_nt_file_name( str, buffer, &len )))
+        {
+            HeapFree( GetProcessHeap(), 0, buffer );
+            return NULL;
+        }
     }
-    if (!set_ntstatus( status )) return NULL;
-    if (nt_name.Buffer[5] == ':')
+    if (buffer[5] == ':')
     {
         /* get rid of the \??\ prefix */
         /* FIXME: should implement RtlNtPathNameToDosPathName and use that instead */
-        len = nt_name.Length - 4 * sizeof(WCHAR);
-        memmove( nt_name.Buffer, nt_name.Buffer + 4, len );
-        nt_name.Buffer[len / sizeof(WCHAR)] = 0;
+        memmove( buffer, buffer + 4, (len - 4) * sizeof(WCHAR) );
     }
-    else
-        nt_name.Buffer[1] = '\\';
-    return nt_name.Buffer;
+    else buffer[1] = '\\';
+    return buffer;
 }
 
 /*************************************************************************
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index d80a80cf39..bd41da37af 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1605,4 +1605,4 @@
 
 # Filesystem
 @ cdecl wine_nt_to_unix_file_name(ptr ptr ptr long)
-@ cdecl wine_unix_to_nt_file_name(ptr ptr)
+@ cdecl wine_unix_to_nt_file_name(str ptr ptr)
diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c
index fb85942eca..5f2d379071 100644
--- a/dlls/ntdll/path.c
+++ b/dlls/ntdll/path.c
@@ -545,26 +545,34 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size)
         if (name[0] == '/')  /* may be a Unix path */
         {
             char *unix_name;
-            ANSI_STRING unix_str;
-            UNICODE_STRING nt_str;
+            WCHAR *nt_str;
+            SIZE_T buflen;
+            NTSTATUS status;
 
             unix_name = RtlAllocateHeap( GetProcessHeap(), 0, 3 * wcslen(name) + 1 );
             ntdll_wcstoumbs( name, wcslen(name) + 1, unix_name, 3 * wcslen(name) + 1, FALSE );
-            RtlInitAnsiString( &unix_str, unix_name );
-            unix_funcs->unix_to_nt_file_name( &unix_str, &nt_str );
-            RtlFreeAnsiString( &unix_str );
-            if (nt_str.Length > 5 * sizeof(WCHAR) && nt_str.Buffer[5] == ':')
+            buflen = strlen(unix_name) + 10;
+            for (;;)
             {
-                reqsize = nt_str.Length - 3 * sizeof(WCHAR);
+                if (!(nt_str = RtlAllocateHeap( GetProcessHeap(), 0, buflen * sizeof(WCHAR) ))) break;
+                status = unix_funcs->unix_to_nt_file_name( unix_name, nt_str, &buflen );
+                if (status != STATUS_BUFFER_TOO_SMALL) break;
+                RtlFreeHeap( GetProcessHeap(), 0, nt_str );
+            }
+            RtlFreeHeap( GetProcessHeap(), 0, unix_name );
+            if (!status && buflen > 6 && nt_str[5] == ':')
+            {
+                reqsize = (buflen - 4) * sizeof(WCHAR);
                 if (reqsize <= size)
                 {
-                    memcpy( buffer, nt_str.Buffer + 4, reqsize );
+                    memcpy( buffer, nt_str + 4, reqsize );
                     collapse_path( buffer, 3 );
                     reqsize -= sizeof(WCHAR);
                 }
-                RtlFreeUnicodeString( &nt_str );
+                RtlFreeHeap( GetProcessHeap(), 0, nt_str );
                 goto done;
             }
+            RtlFreeHeap( GetProcessHeap(), 0, nt_str );
         }
         if (cd->Buffer[1] == ':')
         {
@@ -889,12 +897,7 @@ NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir)
 /******************************************************************
  *           wine_unix_to_nt_file_name  (NTDLL.@) Not a Windows API
  */
-NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRING *nt )
+NTSTATUS CDECL wine_unix_to_nt_file_name( const char *name, WCHAR *buffer, SIZE_T *size )
 {
-    unsigned int lenA = name->Length;
-    const char *path = name->Buffer;
-
-    if (!lenA) return STATUS_INVALID_PARAMETER;
-    if (path[0] != '/') return STATUS_INVALID_PARAMETER; /* relative path not supported */
-    return unix_funcs->unix_to_nt_file_name( name, nt );
+    return unix_funcs->unix_to_nt_file_name( name, buffer, size );
 }
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 760fb4c249..9356fb03f4 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -3482,11 +3482,21 @@ NTSTATUS unix_to_nt_file_name( const char *name, WCHAR **nt )
 /******************************************************************
  *           wine_unix_to_nt_file_name
  */
-NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRING *nt )
+NTSTATUS CDECL wine_unix_to_nt_file_name( const char *name, WCHAR *buffer, SIZE_T *size )
 {
     WCHAR *nt_name = NULL;
-    NTSTATUS status = unix_to_nt_file_name( name->Buffer, &nt_name );
-    if (nt_name) RtlInitUnicodeString( nt, nt_name );
+    NTSTATUS status;
+
+    if (name[0] != '/') return STATUS_INVALID_PARAMETER;  /* relative paths are not supported */
+
+    status = unix_to_nt_file_name( name, &nt_name );
+    if (nt_name)
+    {
+        if (*size > wcslen(nt_name)) wcscpy( buffer, nt_name );
+        else status = STATUS_BUFFER_TOO_SMALL;
+        *size = wcslen(nt_name) + 1;
+        RtlFreeHeap( GetProcessHeap(), 0, nt_name );
+    }
     return status;
 }
 
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
index ca708e45c2..f39dd2d6d8 100644
--- a/dlls/ntdll/unixlib.h
+++ b/dlls/ntdll/unixlib.h
@@ -28,7 +28,7 @@ struct msghdr;
 struct _DISPATCHER_CONTEXT;
 
 /* increment this when you change the function table */
-#define NTDLL_UNIXLIB_VERSION 73
+#define NTDLL_UNIXLIB_VERSION 74
 
 struct unix_funcs
 {
@@ -334,7 +334,7 @@ struct unix_funcs
     /* file functions */
     NTSTATUS      (CDECL *nt_to_unix_file_name)( const UNICODE_STRING *nameW, char *nameA, SIZE_T *size,
                                                  UINT disposition );
-    NTSTATUS      (CDECL *unix_to_nt_file_name)( const ANSI_STRING *name, UNICODE_STRING *nt );
+    NTSTATUS      (CDECL *unix_to_nt_file_name)( const char *name, WCHAR *buffer, SIZE_T *size );
     void          (CDECL *set_show_dot_files)( BOOL enable );
 
     /* loader functions */
diff --git a/include/winternl.h b/include/winternl.h
index ea2a23f3b6..10d109fede 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -3373,7 +3373,7 @@ NTSYSAPI void      WINAPI TpWaitForWork(TP_WORK *,BOOL);
 
 NTSYSAPI NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, char *nameA, SIZE_T *size,
                                                    UINT disposition );
-NTSYSAPI NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRING *nt );
+NTSYSAPI NTSTATUS CDECL wine_unix_to_nt_file_name( const char *name, WCHAR *buffer, SIZE_T *size );
 
 
 /***********************************************************************




More information about the wine-cvs mailing list