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