Module: wine Branch: master Commit: a420a207e3d800a110531eab9d4276ebe5be9d5c URL: http://source.winehq.org/git/wine.git/?a=commit;h=a420a207e3d800a110531eab9d...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Dec 1 16:30:52 2009 +0100
ntdll: Move the directory lookup part of wine_nt_to_unix_file_name to a separate helper.
---
dlls/ntdll/directory.c | 238 ++++++++++++++++++++++++----------------------- 1 files changed, 122 insertions(+), 116 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 40cc455..7833809 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -2212,6 +2212,120 @@ static inline int get_dos_prefix_len( const UNICODE_STRING *name )
/****************************************************************************** + * lookup_unix_name + * + * Helper for nt_to_unix_file_name + */ +static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer, int unix_len, int pos, + UINT disposition, BOOLEAN check_case ) +{ + NTSTATUS status; + int ret, used_default, len; + struct stat st; + char *unix_name = *buffer; + const BOOL redirect = nb_redirects && ntdll_get_thread_data()->wow64_redir; + + /* try a shortcut first */ + + ret = ntdll_wcstoumbs( 0, name, name_len, unix_name + pos, unix_len - pos - 1, + NULL, &used_default ); + + while (name_len && IS_SEPARATOR(*name)) + { + name++; + name_len--; + } + + if (ret > 0 && !used_default) /* if we used the default char the name didn't convert properly */ + { + char *p; + unix_name[pos + ret] = 0; + for (p = unix_name + pos ; *p; p++) if (*p == '\') *p = '/'; + if ((!redirect || !strstr( unix_name, "/windows/")) && !stat( unix_name, &st )) + { + /* creation fails with STATUS_ACCESS_DENIED for the root of the drive */ + if (disposition == FILE_CREATE) + return name_len ? STATUS_OBJECT_NAME_COLLISION : STATUS_ACCESS_DENIED; + return STATUS_SUCCESS; + } + } + + if (!name_len) /* empty name -> drive root doesn't exist */ + return STATUS_OBJECT_PATH_NOT_FOUND; + if (check_case && !redirect && (disposition == FILE_OPEN || disposition == FILE_OVERWRITE)) + return STATUS_OBJECT_NAME_NOT_FOUND; + + /* now do it component by component */ + + while (name_len) + { + const WCHAR *end, *next; + int is_win_dir = 0; + + end = name; + while (end < name + name_len && !IS_SEPARATOR(*end)) end++; + next = end; + while (next < name + name_len && IS_SEPARATOR(*next)) next++; + name_len -= next - name; + + /* grow the buffer if needed */ + + if (unix_len - pos < MAX_DIR_ENTRY_LEN + 2) + { + char *new_name; + unix_len += 2 * MAX_DIR_ENTRY_LEN; + if (!(new_name = RtlReAllocateHeap( GetProcessHeap(), 0, unix_name, unix_len ))) + return STATUS_NO_MEMORY; + unix_name = *buffer = new_name; + } + + status = find_file_in_dir( unix_name, pos, name, end - name, + check_case, redirect ? &is_win_dir : NULL ); + + /* if this is the last element, not finding it is not necessarily fatal */ + if (!name_len) + { + if (status == STATUS_OBJECT_PATH_NOT_FOUND) + { + status = STATUS_OBJECT_NAME_NOT_FOUND; + if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE) + { + ret = ntdll_wcstoumbs( 0, name, end - name, unix_name + pos + 1, + MAX_DIR_ENTRY_LEN, NULL, &used_default ); + if (ret > 0 && !used_default) + { + unix_name[pos] = '/'; + unix_name[pos + 1 + ret] = 0; + status = STATUS_NO_SUCH_FILE; + break; + } + } + } + else if (status == STATUS_SUCCESS && disposition == FILE_CREATE) + { + status = STATUS_OBJECT_NAME_COLLISION; + } + } + + if (status != STATUS_SUCCESS) break; + + pos += strlen( unix_name + pos ); + name = next; + + if (is_win_dir && (len = get_redirect_path( unix_name, pos, name, name_len, check_case ))) + { + name += len; + name_len -= len; + pos += strlen( unix_name + pos ); + TRACE( "redirecting -> %s + %s\n", debugstr_a(unix_name), debugstr_w(name) ); + } + } + + return status; +} + + +/****************************************************************************** * wine_nt_to_unix_file_name (NTDLL.@) Not a Windows API * * Convert a file name from NT namespace to Unix namespace. @@ -2234,7 +2348,6 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI int pos, ret, name_len, unix_len, prefix_len, used_default; WCHAR prefix[MAX_DIR_ENTRY_LEN]; BOOLEAN is_unix = FALSE; - const BOOL redirect = nb_redirects && ntdll_get_thread_data()->wow64_redir;
name = nameW->Buffer; name_len = nameW->Length / sizeof(WCHAR); @@ -2315,126 +2428,19 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI } }
- /* try a shortcut first */ - - ret = ntdll_wcstoumbs( 0, name, name_len, unix_name + pos, unix_len - pos - 1, - NULL, &used_default ); - - while (name_len && IS_SEPARATOR(*name)) - { - name++; - name_len--; - } - - if (ret > 0 && !used_default) /* if we used the default char the name didn't convert properly */ + status = lookup_unix_name( name, name_len, &unix_name, unix_len, pos, disposition, check_case ); + if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE) { - char *p; - unix_name[pos + ret] = 0; - for (p = unix_name + pos ; *p; p++) if (*p == '\') *p = '/'; - if ((!redirect || !strstr( unix_name, "/windows/")) && !stat( unix_name, &st )) - { - /* creation fails with STATUS_ACCESS_DENIED for the root of the drive */ - if (disposition == FILE_CREATE) - { - RtlFreeHeap( GetProcessHeap(), 0, unix_name ); - return name_len ? STATUS_OBJECT_NAME_COLLISION : STATUS_ACCESS_DENIED; - } - goto done; - } + 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; } - - if (!name_len) /* empty name -> drive root doesn't exist */ - { - RtlFreeHeap( GetProcessHeap(), 0, unix_name ); - return STATUS_OBJECT_PATH_NOT_FOUND; - } - if (check_case && !redirect && (disposition == FILE_OPEN || disposition == FILE_OVERWRITE)) + else { + TRACE( "%s not found in %s\n", debugstr_w(name), unix_name ); RtlFreeHeap( GetProcessHeap(), 0, unix_name ); - return STATUS_OBJECT_NAME_NOT_FOUND; - } - - /* now do it component by component */ - - while (name_len) - { - const WCHAR *end, *next; - int is_win_dir = 0; - - end = name; - while (end < name + name_len && !IS_SEPARATOR(*end)) end++; - next = end; - while (next < name + name_len && IS_SEPARATOR(*next)) next++; - name_len -= next - name; - - /* grow the buffer if needed */ - - if (unix_len - pos < MAX_DIR_ENTRY_LEN + 2) - { - char *new_name; - unix_len += 2 * MAX_DIR_ENTRY_LEN; - if (!(new_name = RtlReAllocateHeap( GetProcessHeap(), 0, unix_name, unix_len ))) - { - RtlFreeHeap( GetProcessHeap(), 0, unix_name ); - return STATUS_NO_MEMORY; - } - unix_name = new_name; - } - - status = find_file_in_dir( unix_name, pos, name, end - name, - check_case, redirect ? &is_win_dir : NULL ); - - /* if this is the last element, not finding it is not necessarily fatal */ - if (!name_len) - { - if (status == STATUS_OBJECT_PATH_NOT_FOUND) - { - status = STATUS_OBJECT_NAME_NOT_FOUND; - if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE) - { - ret = ntdll_wcstoumbs( 0, name, end - name, unix_name + pos + 1, - MAX_DIR_ENTRY_LEN, NULL, &used_default ); - if (ret > 0 && !used_default) - { - unix_name[pos] = '/'; - unix_name[pos + 1 + ret] = 0; - status = STATUS_NO_SUCH_FILE; - break; - } - } - } - else if (status == STATUS_SUCCESS && disposition == FILE_CREATE) - { - status = STATUS_OBJECT_NAME_COLLISION; - } - } - - if (status != STATUS_SUCCESS) - { - /* couldn't find it at all, fail */ - TRACE( "%s not found in %s\n", debugstr_w(name), unix_name ); - RtlFreeHeap( GetProcessHeap(), 0, unix_name ); - return status; - } - - pos += strlen( unix_name + pos ); - name = next; - - if (is_win_dir && (prefix_len = get_redirect_path( unix_name, pos, name, name_len, check_case ))) - { - name += prefix_len; - name_len -= prefix_len; - pos += strlen( unix_name + pos ); - TRACE( "redirecting %s -> %s + %s\n", - debugstr_us(nameW), debugstr_a(unix_name), debugstr_w(name) ); - } } - -done: - 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; return status; }