Alexandre Julliard : ntdll: Move the directory lookup part of wine_nt_to_unix_file_name to a separate helper .
Alexandre Julliard
julliard at winehq.org
Wed Dec 2 10:22:10 CST 2009
Module: wine
Branch: master
Commit: a420a207e3d800a110531eab9d4276ebe5be9d5c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a420a207e3d800a110531eab9d4276ebe5be9d5c
Author: Alexandre Julliard <julliard at 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;
}
More information about the wine-cvs
mailing list