diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c index f958610dbdd..5377c2302bc 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 d80a80cf390..bd41da37af4 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 fb85942ecae..5f2d379071a 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 760fb4c2497..9356fb03f44 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 ca708e45c2c..f39dd2d6d8f 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 ea2a23f3b6d..10d109fede1 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 ); /***********************************************************************