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

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-07-09 10:03:15 +02:00
parent 5ebdeaaa37
commit 6f862a1ad8
6 changed files with 51 additions and 36 deletions

View File

@ -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;
}
/*************************************************************************

View File

@ -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)

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 );
/***********************************************************************