From d0a16b7dc99a4040e4e804c04d71a24b3a9d829e Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 9 Jul 2020 09:57:57 +0200 Subject: [PATCH] ntdll: Return a char pointer instead of an ANSI_STRING in nt_to_unix_file_name(). Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/file.c | 124 ++++++++++++++++++--------------- dlls/ntdll/unix/loader.c | 8 +-- dlls/ntdll/unix/process.c | 6 +- dlls/ntdll/unix/unix_private.h | 3 +- 4 files changed, 76 insertions(+), 65 deletions(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index dff246f5e74..0862b94921d 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -2806,7 +2806,7 @@ void init_files(void) * * Get the Unix path of a DOS device. */ -static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *unix_name_ret ) +static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, char **unix_name_ret ) { struct stat st; char *unix_name, *new_name, *dev; @@ -2841,9 +2841,7 @@ static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *u if (!stat( unix_name, &st )) { TRACE( "%s -> %s\n", debugstr_wn(name,name_len), debugstr_a(unix_name) ); - unix_name_ret->Buffer = unix_name; - unix_name_ret->Length = strlen(unix_name); - unix_name_ret->MaximumLength = unix_len; + *unix_name_ret = unix_name; return STATUS_SUCCESS; } if (!dev) break; @@ -2993,37 +2991,36 @@ static NTSTATUS find_drive_rootA( LPCSTR *ppath, unsigned int len, int *drive_re * * Recursively search directories from the dir queue for a given inode. */ -static NTSTATUS find_file_id( ANSI_STRING *unix_name, ULONGLONG file_id, dev_t dev ) +static NTSTATUS find_file_id( char **unix_name, ULONG *len, ULONGLONG file_id, dev_t dev ) { unsigned int pos; DIR *dir; struct dirent *de; NTSTATUS status; struct stat st; + char *name = *unix_name; - while (!(status = next_dir_in_queue( unix_name->Buffer ))) + while (!(status = next_dir_in_queue( name ))) { - if (!(dir = opendir( unix_name->Buffer ))) continue; - TRACE( "searching %s for %s\n", unix_name->Buffer, wine_dbgstr_longlong(file_id) ); - pos = strlen( unix_name->Buffer ); - if (pos + MAX_DIR_ENTRY_LEN >= unix_name->MaximumLength/sizeof(WCHAR)) + if (!(dir = opendir( name ))) continue; + TRACE( "searching %s for %s\n", debugstr_a(name), wine_dbgstr_longlong(file_id) ); + pos = strlen( name ); + if (pos + MAX_DIR_ENTRY_LEN >= *len / sizeof(WCHAR)) { - char *new = RtlReAllocateHeap( GetProcessHeap(), 0, unix_name->Buffer, - unix_name->MaximumLength * 2 ); - if (!new) + if (!(name = RtlReAllocateHeap( GetProcessHeap(), 0, name, *len * 2 ))) { closedir( dir ); return STATUS_NO_MEMORY; } - unix_name->MaximumLength *= 2; - unix_name->Buffer = new; + *len *= 2; + *unix_name = name; } - unix_name->Buffer[pos++] = '/'; + name[pos++] = '/'; while ((de = readdir( dir ))) { if (!strcmp( de->d_name, "." ) || !strcmp( de->d_name, ".." )) continue; - strcpy( unix_name->Buffer + pos, de->d_name ); - if (lstat( unix_name->Buffer, &st ) == -1) continue; + strcpy( name + pos, de->d_name ); + if (lstat( name, &st ) == -1) continue; if (st.st_dev != dev) continue; if (st.st_ino == file_id) { @@ -3031,7 +3028,7 @@ static NTSTATUS find_file_id( ANSI_STRING *unix_name, ULONGLONG file_id, dev_t d return STATUS_SUCCESS; } if (!S_ISDIR( st.st_mode )) continue; - if ((status = add_dir_to_queue( unix_name->Buffer )) != STATUS_SUCCESS) + if ((status = add_dir_to_queue( name )) != STATUS_SUCCESS) { closedir( dir ); return status; @@ -3048,10 +3045,12 @@ static NTSTATUS find_file_id( ANSI_STRING *unix_name, ULONGLONG file_id, dev_t d * * Lookup a file from its file id instead of its name. */ -static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *unix_name ) +static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **unix_name_ret ) { enum server_fd_type type; int old_cwd, root_fd, needs_close; + char *unix_name; + ULONG len; NTSTATUS status; ULONGLONG file_id; struct stat st, root_st; @@ -3060,10 +3059,9 @@ static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_S if (!attr->RootDirectory) return STATUS_INVALID_PARAMETER; memcpy( &file_id, attr->ObjectName->Buffer, sizeof(file_id) ); - unix_name->MaximumLength = 2 * MAX_DIR_ENTRY_LEN + 4; - if (!(unix_name->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, unix_name->MaximumLength ))) - return STATUS_NO_MEMORY; - strcpy( unix_name->Buffer, "." ); + len = 2 * MAX_DIR_ENTRY_LEN + 4; + if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY; + strcpy( unix_name, "." ); if ((status = server_get_unix_fd( attr->RootDirectory, 0, &root_fd, &needs_close, &type, NULL ))) goto done; @@ -3087,16 +3085,16 @@ static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_S /* shortcut for ".." */ if (!stat( "..", &st ) && st.st_dev == root_st.st_dev && st.st_ino == file_id) { - strcpy( unix_name->Buffer, ".." ); + strcpy( unix_name, ".." ); status = STATUS_SUCCESS; } else { status = add_dir_to_queue( "." ); if (!status) - status = find_file_id( unix_name, file_id, root_st.st_dev ); + status = find_file_id( &unix_name, &len, file_id, root_st.st_dev ); if (!status) /* get rid of "./" prefix */ - memmove( unix_name->Buffer, unix_name->Buffer + 2, strlen(unix_name->Buffer) - 1 ); + memmove( unix_name, unix_name + 2, strlen(unix_name) - 1 ); flush_dir_queue(); } if (fchdir( old_cwd ) == -1) chdir( "/" ); @@ -3108,13 +3106,13 @@ static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_S done: if (status == STATUS_SUCCESS) { - TRACE( "%s -> %s\n", wine_dbgstr_longlong(file_id), debugstr_a(unix_name->Buffer) ); - unix_name->Length = strlen( unix_name->Buffer ); + TRACE( "%s -> %s\n", wine_dbgstr_longlong(file_id), debugstr_a(unix_name) ); + *unix_name_ret = unix_name; } else { TRACE( "%s not found in dir %p\n", wine_dbgstr_longlong(file_id), attr->RootDirectory ); - RtlFreeHeap( GetProcessHeap(), 0, unix_name->Buffer ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); } if (needs_close) close( root_fd ); return status; @@ -3238,7 +3236,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer /****************************************************************************** * nt_to_unix_file_name_attr */ -static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *unix_name_ret, +static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition ) { static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 }; @@ -3250,7 +3248,7 @@ static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S NTSTATUS status; if (!attr->RootDirectory) /* without root dir fall back to normal lookup */ - return nt_to_unix_file_name( attr->ObjectName, unix_name_ret, disposition ); + return nt_to_unix_file_name( attr->ObjectName, name_ret, disposition ); name = attr->ObjectName->Buffer; name_len = attr->ObjectName->Length / sizeof(WCHAR); @@ -3293,9 +3291,7 @@ static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE) { TRACE( "%s -> %s\n", debugstr_us(attr->ObjectName), debugstr_a(unix_name) ); - unix_name_ret->Buffer = unix_name; - unix_name_ret->Length = strlen(unix_name); - unix_name_ret->MaximumLength = unix_len; + *name_ret = unix_name; } else { @@ -3315,8 +3311,7 @@ static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S * element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is * returned, but the unix name is still filled in properly. */ -NTSTATUS CDECL nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret, - UINT disposition ) +NTSTATUS nt_to_unix_file_name( const UNICODE_STRING *nameW, char **unix_name_ret, UINT disposition ) { static const WCHAR unixW[] = {'u','n','i','x'}; static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 }; @@ -3412,9 +3407,7 @@ NTSTATUS CDECL nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *u if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE) { TRACE( "%s -> %s\n", debugstr_us(nameW), debugstr_a(unix_name) ); - unix_name_ret->Buffer = unix_name; - unix_name_ret->Length = strlen(unix_name); - unix_name_ret->MaximumLength = unix_len; + *unix_name_ret = unix_name; } else { @@ -3425,6 +3418,25 @@ NTSTATUS CDECL nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *u } +/****************************************************************************** + * wine_nt_to_unix_file_name + * + * Convert a file name from NT namespace to Unix namespace. + * + * If disposition is not FILE_OPEN or FILE_OVERWRITE, the last path + * element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is + * returned, but the unix name is still filled in properly. + */ +NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret, + UINT disposition ) +{ + char *buffer = NULL; + NTSTATUS status = nt_to_unix_file_name( nameW, &buffer, disposition ); + if (buffer) RtlInitAnsiString( unix_name_ret, buffer ); + return status; +} + + /****************************************************************** * unix_to_nt_file_name */ @@ -3528,7 +3540,7 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU ULONG attributes, ULONG sharing, ULONG disposition, ULONG options, void *ea_buffer, ULONG ea_length ) { - ANSI_STRING unix_name; + char *unix_name; BOOL created = FALSE; TRACE( "handle=%p access=%08x name=%s objattr=%08x root=%p sec=%p io=%p alloc_size=%p " @@ -3580,7 +3592,7 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU unix_attr.ObjectName = &empty_string; /* we send the unix name instead */ if ((io->u.Status = alloc_object_attributes( &unix_attr, &objattr, &len ))) { - RtlFreeAnsiString( &unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); return io->u.Status; } SERVER_START_REQ( create_file ) @@ -3591,13 +3603,13 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU req->options = options; req->attrs = attributes; wine_server_add_data( req, objattr, len ); - wine_server_add_data( req, unix_name.Buffer, unix_name.Length ); + wine_server_add_data( req, unix_name, strlen(unix_name) ); io->u.Status = wine_server_call( req ); *handle = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; free( objattr ); - RtlFreeAnsiString( &unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); } else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status ); @@ -3747,7 +3759,7 @@ NTSTATUS WINAPI NtDeleteFile( OBJECT_ATTRIBUTES *attr ) NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_NETWORK_OPEN_INFORMATION *info ) { - ANSI_STRING unix_name; + char *unix_name; NTSTATUS status; if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN ))) @@ -3755,7 +3767,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr, ULONG attributes; struct stat st; - if (get_file_info( unix_name.Buffer, &st, &attributes ) == -1) + if (get_file_info( unix_name, &st, &attributes ) == -1) status = errno_to_status( errno ); else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) status = STATUS_INVALID_INFO_CLASS; @@ -3776,7 +3788,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr, info->FileAttributes = basic.FileAttributes; if (is_hidden_file( attr->ObjectName )) info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; } - RtlFreeAnsiString( &unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); } else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status ); return status; @@ -3788,7 +3800,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr, */ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info ) { - ANSI_STRING unix_name; + char *unix_name; NTSTATUS status; if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN ))) @@ -3796,7 +3808,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC ULONG attributes; struct stat st; - if (get_file_info( unix_name.Buffer, &st, &attributes ) == -1) + if (get_file_info( unix_name, &st, &attributes ) == -1) status = errno_to_status( errno ); else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) status = STATUS_INVALID_INFO_CLASS; @@ -3805,7 +3817,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC status = fill_file_info( &st, attributes, info, FileBasicInformation ); if (is_hidden_file( attr->ObjectName )) info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; } - RtlFreeAnsiString( &unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); } else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status ); return status; @@ -4345,7 +4357,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, FILE_RENAME_INFORMATION *info = ptr; UNICODE_STRING name_str; OBJECT_ATTRIBUTES attr; - ANSI_STRING unix_name; + char *unix_name; name_str.Buffer = info->FileName; name_str.Length = info->FileNameLength; @@ -4366,12 +4378,12 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, req->rootdir = wine_server_obj_handle( attr.RootDirectory ); req->link = FALSE; req->replace = info->ReplaceIfExists; - wine_server_add_data( req, unix_name.Buffer, unix_name.Length ); + wine_server_add_data( req, unix_name, strlen(unix_name) ); io->u.Status = wine_server_call( req ); } SERVER_END_REQ; - RtlFreeAnsiString( &unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); } else io->u.Status = STATUS_INVALID_PARAMETER_3; break; @@ -4382,7 +4394,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, FILE_LINK_INFORMATION *info = ptr; UNICODE_STRING name_str; OBJECT_ATTRIBUTES attr; - ANSI_STRING unix_name; + char *unix_name; name_str.Buffer = info->FileName; name_str.Length = info->FileNameLength; @@ -4403,12 +4415,12 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, req->rootdir = wine_server_obj_handle( attr.RootDirectory ); req->link = TRUE; req->replace = info->ReplaceIfExists; - wine_server_add_data( req, unix_name.Buffer, unix_name.Length ); + wine_server_add_data( req, unix_name, strlen(unix_name) ); io->u.Status = wine_server_call( req ); } SERVER_END_REQ; - RtlFreeAnsiString( &unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); } else io->u.Status = STATUS_INVALID_PARAMETER_3; break; diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index b19b41fcba4..461b325d213 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -927,7 +927,7 @@ already_loaded: static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module ) { static const WCHAR soW[] = {'.','s','o',0}; - ANSI_STRING unix_name; + char *unix_name; NTSTATUS status; DWORD len; @@ -937,8 +937,8 @@ static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module ) len = nt_name->Length / sizeof(WCHAR); if (len > 3 && !wcsicmp( nt_name->Buffer + len - 3, soW )) nt_name->Length -= 3 * sizeof(WCHAR); - status = dlopen_dll( unix_name.Buffer, module ); - RtlFreeAnsiString( &unix_name ); + status = dlopen_dll( unix_name, module ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); return status; } @@ -1533,7 +1533,7 @@ static struct unix_funcs unix_funcs = server_handle_to_fd, server_release_fd, server_init_process_done, - nt_to_unix_file_name, + wine_nt_to_unix_file_name, unix_to_nt_file_name, set_show_dot_files, load_so_dll, diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 7061d8864db..1e31fee326a 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -662,7 +662,7 @@ static NTSTATUS fork_and_exec( UNICODE_STRING *path, int unixdir, pid_t pid; int fd[2], stdin_fd = -1, stdout_fd = -1; char **argv, **envp; - ANSI_STRING unix_name; + char *unix_name; NTSTATUS status; status = nt_to_unix_file_name( path, &unix_name, FILE_OPEN ); @@ -712,7 +712,7 @@ static NTSTATUS fork_and_exec( UNICODE_STRING *path, int unixdir, fchdir( unixdir ); close( unixdir ); } - execve( unix_name.Buffer, argv, envp ); + execve( unix_name, argv, envp ); } if (pid <= 0) /* grandchild if exec failed or child if fork failed */ @@ -750,7 +750,7 @@ static NTSTATUS fork_and_exec( UNICODE_STRING *path, int unixdir, if (stdin_fd != -1) close( stdin_fd ); if (stdout_fd != -1) close( stdout_fd ); done: - RtlFreeAnsiString( &unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); return status; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 82806463e53..d03e74b68b0 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -124,8 +124,6 @@ extern NTSTATUS CDECL exec_process( UNICODE_STRING *path, UNICODE_STRING *cmdlin extern NTSTATUS CDECL unwind_builtin_dll( ULONG type, struct _DISPATCHER_CONTEXT *dispatch, CONTEXT *context ) DECLSPEC_HIDDEN; -extern NTSTATUS CDECL nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret, - UINT disposition ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRING *nt ) DECLSPEC_HIDDEN; extern void CDECL set_show_dot_files( BOOL enable ) DECLSPEC_HIDDEN; @@ -237,6 +235,7 @@ extern NTSTATUS tape_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTI ULONG in_size, void *out_buffer, ULONG out_size ) DECLSPEC_HIDDEN; extern NTSTATUS errno_to_status( int err ) DECLSPEC_HIDDEN; +extern NTSTATUS nt_to_unix_file_name( const UNICODE_STRING *nameW, char **name_ret, UINT disposition ) DECLSPEC_HIDDEN; extern void init_files(void) DECLSPEC_HIDDEN; extern void init_cpu_info(void) DECLSPEC_HIDDEN;