ntdll: Reimplement file system redirection using NT pathname comparisons.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8e7c6422e5
commit
7ef35b3393
|
@ -2133,16 +2133,21 @@ void init_startup_info(void)
|
|||
/***********************************************************************
|
||||
* create_startup_info
|
||||
*/
|
||||
void *create_startup_info( const RTL_USER_PROCESS_PARAMETERS *params, DWORD *info_size )
|
||||
void *create_startup_info( const UNICODE_STRING *nt_image, const RTL_USER_PROCESS_PARAMETERS *params,
|
||||
DWORD *info_size )
|
||||
{
|
||||
startup_info_t *info;
|
||||
UNICODE_STRING dos_image = *nt_image;
|
||||
DWORD size;
|
||||
void *ptr;
|
||||
|
||||
dos_image.Buffer = get_dos_path( nt_image->Buffer );
|
||||
dos_image.Length = nt_image->Length - (dos_image.Buffer - nt_image->Buffer) * sizeof(WCHAR);
|
||||
|
||||
size = sizeof(*info);
|
||||
size += params->CurrentDirectory.DosPath.Length;
|
||||
size += params->DllPath.Length;
|
||||
size += params->ImagePathName.Length;
|
||||
size += dos_image.Length;
|
||||
size += params->CommandLine.Length;
|
||||
size += params->WindowTitle.Length;
|
||||
size += params->Desktop.Length;
|
||||
|
@ -2172,7 +2177,7 @@ void *create_startup_info( const RTL_USER_PROCESS_PARAMETERS *params, DWORD *inf
|
|||
ptr = info + 1;
|
||||
info->curdir_len = append_string( &ptr, params, ¶ms->CurrentDirectory.DosPath );
|
||||
info->dllpath_len = append_string( &ptr, params, ¶ms->DllPath );
|
||||
info->imagepath_len = append_string( &ptr, params, ¶ms->ImagePathName );
|
||||
info->imagepath_len = append_string( &ptr, params, &dos_image );
|
||||
info->cmdline_len = append_string( &ptr, params, ¶ms->CommandLine );
|
||||
info->title_len = append_string( &ptr, params, ¶ms->WindowTitle );
|
||||
info->desktop_len = append_string( &ptr, params, ¶ms->Desktop );
|
||||
|
|
|
@ -241,8 +241,6 @@ static mode_t start_umask;
|
|||
/* at some point we may want to allow Winelib apps to set this */
|
||||
static const BOOL is_case_sensitive = FALSE;
|
||||
|
||||
static struct file_identity windir;
|
||||
|
||||
static pthread_mutex_t dir_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t mnt_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
@ -2477,7 +2475,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, PIO_APC_ROUTI
|
|||
* There must be at least MAX_DIR_ENTRY_LEN+2 chars available at pos.
|
||||
*/
|
||||
static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, int length,
|
||||
BOOLEAN check_case, BOOLEAN *is_win_dir )
|
||||
BOOLEAN check_case )
|
||||
{
|
||||
WCHAR buffer[MAX_DIR_ENTRY_LEN];
|
||||
BOOLEAN is_name_8_dot_3;
|
||||
|
@ -2493,11 +2491,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
|||
if (ret >= 0 && ret <= MAX_DIR_ENTRY_LEN)
|
||||
{
|
||||
unix_name[pos + ret] = 0;
|
||||
if (!stat( unix_name, &st ))
|
||||
{
|
||||
if (is_win_dir) *is_win_dir = is_same_file( &windir, &st );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if (!stat( unix_name, &st )) return STATUS_SUCCESS;
|
||||
}
|
||||
if (check_case) goto not_found; /* we want an exact match */
|
||||
|
||||
|
@ -2536,7 +2530,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
|||
{
|
||||
strcpy( unix_name + pos, kde[1].d_name );
|
||||
close( fd );
|
||||
goto success;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
ret = ntdll_umbstowcs( kde[0].d_name, strlen(kde[0].d_name),
|
||||
|
@ -2546,7 +2540,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
|||
strcpy( unix_name + pos,
|
||||
kde[1].d_name[0] ? kde[1].d_name : kde[0].d_name );
|
||||
close( fd );
|
||||
goto success;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)kde ) == -1)
|
||||
{
|
||||
|
@ -2573,7 +2567,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
|||
{
|
||||
strcpy( unix_name + pos, de->d_name );
|
||||
closedir( dir );
|
||||
goto success;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!is_name_8_dot_3) continue;
|
||||
|
@ -2586,7 +2580,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
|||
{
|
||||
strcpy( unix_name + pos, de->d_name );
|
||||
closedir( dir );
|
||||
goto success;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2595,10 +2589,6 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
|||
not_found:
|
||||
unix_name[pos - 1] = 0;
|
||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
|
||||
success:
|
||||
if (is_win_dir && !stat( unix_name, &st )) *is_win_dir = is_same_file( &windir, &st );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2611,116 +2601,164 @@ static const WCHAR driversetcW[] = {'s','y','s','t','e','m','3','2','\\','d','r'
|
|||
static const WCHAR logfilesW[] = {'s','y','s','t','e','m','3','2','\\','l','o','g','f','i','l','e','s',0};
|
||||
static const WCHAR spoolW[] = {'s','y','s','t','e','m','3','2','\\','s','p','o','o','l',0};
|
||||
static const WCHAR system32W[] = {'s','y','s','t','e','m','3','2',0};
|
||||
static const WCHAR syswow64W[] = {'s','y','s','w','o','w','6','4',0};
|
||||
static const WCHAR sysnativeW[] = {'s','y','s','n','a','t','i','v','e',0};
|
||||
static const WCHAR regeditW[] = {'r','e','g','e','d','i','t','.','e','x','e',0};
|
||||
static const WCHAR syswow64_regeditW[] = {'s','y','s','w','o','w','6','4','\\','r','e','g','e','d','i','t','.','e','x','e',0};
|
||||
static const WCHAR windirW[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\',0};
|
||||
static const WCHAR syswow64dirW[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','w','o','w','6','4','\\'};
|
||||
|
||||
static struct
|
||||
static const WCHAR * const no_redirect[] =
|
||||
{
|
||||
const WCHAR *source;
|
||||
const char *unix_target;
|
||||
} redirects[] =
|
||||
{
|
||||
{ catrootW, NULL },
|
||||
{ catroot2W, NULL },
|
||||
{ driversstoreW, NULL },
|
||||
{ driversetcW, NULL },
|
||||
{ logfilesW, NULL },
|
||||
{ spoolW, NULL },
|
||||
{ system32W, "syswow64" },
|
||||
{ sysnativeW, "system32" },
|
||||
{ regeditW, "syswow64/regedit.exe" }
|
||||
catrootW,
|
||||
catroot2W,
|
||||
driversstoreW,
|
||||
driversetcW,
|
||||
logfilesW,
|
||||
spoolW
|
||||
};
|
||||
|
||||
static unsigned int nb_redirects;
|
||||
static struct file_identity windir, sysdir;
|
||||
|
||||
static inline ULONG starts_with_path( const WCHAR *name, ULONG name_len, const WCHAR *prefix )
|
||||
{
|
||||
ULONG len = wcslen( prefix );
|
||||
|
||||
if (name_len < len) return 0;
|
||||
if (wcsnicmp( name, prefix, len )) return 0;
|
||||
if (name_len > len && name[len] != '\\') return 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
static BOOL replace_path( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *str, ULONG prefix_len,
|
||||
const WCHAR *match, const WCHAR *replace )
|
||||
{
|
||||
const WCHAR *name = attr->ObjectName->Buffer;
|
||||
ULONG match_len, replace_len, len = attr->ObjectName->Length / sizeof(WCHAR);
|
||||
WCHAR *p;
|
||||
|
||||
if (!starts_with_path( name + prefix_len, len - prefix_len, match )) return FALSE;
|
||||
|
||||
match_len = wcslen( match );
|
||||
replace_len = wcslen( replace );
|
||||
str->Length = (len + replace_len - match_len) * sizeof(WCHAR);
|
||||
str->MaximumLength = str->Length + sizeof(WCHAR);
|
||||
if (!(p = str->Buffer = malloc( str->MaximumLength ))) return FALSE;
|
||||
|
||||
memcpy( p, name, prefix_len * sizeof(WCHAR) );
|
||||
p += prefix_len;
|
||||
memcpy( p, replace, replace_len * sizeof(WCHAR) );
|
||||
p += replace_len;
|
||||
name += prefix_len + match_len;
|
||||
len -= prefix_len + match_len;
|
||||
memcpy( p, name, len * sizeof(WCHAR) );
|
||||
p[len] = 0;
|
||||
attr->ObjectName = str;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* init_redirects
|
||||
*/
|
||||
static void init_redirects(void)
|
||||
{
|
||||
static const char windows_dir[] = "/dosdevices/c:/windows";
|
||||
static const char system_dir[] = "/dosdevices/c:/windows/system32";
|
||||
char *dir;
|
||||
struct stat st;
|
||||
|
||||
if (!(dir = malloc( strlen(config_dir) + sizeof(windows_dir) ))) return;
|
||||
if (!(dir = malloc( strlen(config_dir) + sizeof(system_dir) ))) return;
|
||||
strcpy( dir, config_dir );
|
||||
strcat( dir, windows_dir );
|
||||
strcat( dir, system_dir );
|
||||
if (!stat( dir, &st ))
|
||||
{
|
||||
sysdir.dev = st.st_dev;
|
||||
sysdir.ino = st.st_ino;
|
||||
}
|
||||
*strrchr( dir, '/' ) = 0;
|
||||
if (!stat( dir, &st ))
|
||||
{
|
||||
windir.dev = st.st_dev;
|
||||
windir.ino = st.st_ino;
|
||||
nb_redirects = ARRAY_SIZE( redirects );
|
||||
}
|
||||
else ERR( "%s: %s\n", dir, strerror(errno) );
|
||||
free( dir );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* match_redirect
|
||||
*
|
||||
* Check if path matches a redirect name. If yes, return matched length.
|
||||
* get_redirect
|
||||
*/
|
||||
static int match_redirect( const WCHAR *path, int len, const WCHAR *redir, BOOLEAN check_case )
|
||||
BOOL get_redirect( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *redir )
|
||||
{
|
||||
int i = 0;
|
||||
const WCHAR *name = attr->ObjectName->Buffer;
|
||||
unsigned int i, prefix_len = 0, len = attr->ObjectName->Length / sizeof(WCHAR);
|
||||
|
||||
while (i < len)
|
||||
redir->Buffer = NULL;
|
||||
if (!NtCurrentTeb64()) return FALSE;
|
||||
if (!len) return FALSE;
|
||||
|
||||
if (!attr->RootDirectory)
|
||||
{
|
||||
int start = i;
|
||||
while (i < len && !IS_SEPARATOR(path[i])) i++;
|
||||
if (check_case)
|
||||
{
|
||||
if (wcsncmp( path + start, redir, i - start )) return 0;
|
||||
prefix_len = wcslen( windirW );
|
||||
if (len < prefix_len || wcsnicmp( name, windirW, prefix_len )) return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wcsnicmp( path + start, redir, i - start )) return 0;
|
||||
}
|
||||
redir += i - start;
|
||||
while (i < len && IS_SEPARATOR(path[i])) i++;
|
||||
if (!*redir) return i;
|
||||
if (*redir++ != '\\') return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int fd, needs_close;
|
||||
struct stat st;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_redirect_path
|
||||
*
|
||||
* Retrieve the Unix path corresponding to a redirected path if any.
|
||||
*/
|
||||
static int get_redirect_path( char *unix_name, int pos, const WCHAR *name, int length, BOOLEAN check_case )
|
||||
{
|
||||
unsigned int i;
|
||||
int len;
|
||||
|
||||
for (i = 0; i < nb_redirects; i++)
|
||||
if (server_get_unix_fd( attr->RootDirectory, 0, &fd, &needs_close, NULL, NULL )) return FALSE;
|
||||
fstat( fd, &st );
|
||||
if (needs_close) close( fd );
|
||||
if (!is_same_file( &windir, &st ))
|
||||
{
|
||||
if ((len = match_redirect( name, length, redirects[i].source, check_case )))
|
||||
{
|
||||
if (!redirects[i].unix_target) break;
|
||||
unix_name[pos++] = '/';
|
||||
strcpy( unix_name + pos, redirects[i].unix_target );
|
||||
return len;
|
||||
if (!is_same_file( &sysdir, &st )) return FALSE;
|
||||
if (NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR]) return FALSE;
|
||||
if (name[0] == '\\') return FALSE;
|
||||
|
||||
/* only check for paths that should NOT be redirected */
|
||||
for (i = 0; i < ARRAY_SIZE( no_redirect ); i++)
|
||||
if (starts_with_path( name, len, no_redirect[i] + 9 /* "system32\\" */)) return FALSE;
|
||||
|
||||
/* redirect everything else */
|
||||
redir->Length = sizeof(syswow64dirW) + len * sizeof(WCHAR);
|
||||
redir->MaximumLength = redir->Length + sizeof(WCHAR);
|
||||
if (!(redir->Buffer = malloc( redir->MaximumLength ))) return FALSE;
|
||||
memcpy( redir->Buffer, syswow64dirW, sizeof(syswow64dirW) );
|
||||
memcpy( redir->Buffer + ARRAY_SIZE(syswow64dirW), name, len * sizeof(WCHAR) );
|
||||
redir->Buffer[redir->Length / sizeof(WCHAR)] = 0;
|
||||
attr->RootDirectory = 0;
|
||||
attr->ObjectName = redir;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* sysnative is redirected even when redirection is disabled */
|
||||
|
||||
if (replace_path( attr, redir, prefix_len, sysnativeW, system32W )) return TRUE;
|
||||
|
||||
if (NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR]) return FALSE;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE( no_redirect ); i++)
|
||||
if (starts_with_path( name + prefix_len, len - prefix_len, no_redirect[i] )) return FALSE;
|
||||
|
||||
if (replace_path( attr, redir, prefix_len, system32W, syswow64W )) return TRUE;
|
||||
if (replace_path( attr, redir, prefix_len, regeditW, syswow64_regeditW )) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#else /* _WIN64 */
|
||||
|
||||
/* there are no redirects on 64-bit */
|
||||
static int get_redirect_path( char *unix_name, int pos, const WCHAR *name, int length, BOOLEAN check_case )
|
||||
BOOL get_redirect( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *redir )
|
||||
{
|
||||
return 0;
|
||||
redir->Buffer = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -3018,6 +3056,7 @@ static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char *
|
|||
ULONGLONG file_id;
|
||||
struct stat st, root_st;
|
||||
|
||||
nt_name->Buffer = NULL;
|
||||
if (attr->ObjectName->Length != sizeof(ULONGLONG)) return STATUS_OBJECT_PATH_SYNTAX_BAD;
|
||||
if (!attr->RootDirectory) return STATUS_INVALID_PARAMETER;
|
||||
memcpy( &file_id, attr->ObjectName->Buffer, sizeof(file_id) );
|
||||
|
@ -3093,11 +3132,10 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
|||
{
|
||||
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, '/', 0 };
|
||||
NTSTATUS status;
|
||||
int ret, len;
|
||||
int ret;
|
||||
struct stat st;
|
||||
char *unix_name = *buffer;
|
||||
const WCHAR *ptr, *end;
|
||||
const BOOL redirect = NtCurrentTeb64() && !NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR];
|
||||
|
||||
/* check syntax of individual components */
|
||||
|
||||
|
@ -3132,20 +3170,16 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
|||
char *p;
|
||||
unix_name[pos + 1 + ret] = 0;
|
||||
for (p = unix_name + pos ; *p; p++) if (*p == '\\') *p = '/';
|
||||
if (!name_len || !redirect || (!strstr( unix_name, "/windows/") && strncmp( unix_name, "windows/", 8 )))
|
||||
{
|
||||
if (!stat( unix_name, &st ))
|
||||
{
|
||||
if (disposition == FILE_CREATE)
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
if (disposition == FILE_CREATE) return STATUS_OBJECT_NAME_COLLISION;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!name_len) /* empty name -> drive root doesn't exist */
|
||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
if (is_unix && !redirect && (disposition == FILE_OPEN || disposition == FILE_OVERWRITE))
|
||||
if (is_unix && (disposition == FILE_OPEN || disposition == FILE_OVERWRITE))
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
|
||||
/* now do it component by component */
|
||||
|
@ -3153,7 +3187,6 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
|||
while (name_len)
|
||||
{
|
||||
const WCHAR *end, *next;
|
||||
BOOLEAN is_win_dir = FALSE;
|
||||
|
||||
end = name;
|
||||
while (end < name + name_len && *end != '\\') end++;
|
||||
|
@ -3171,8 +3204,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
|||
unix_name = *buffer = new_name;
|
||||
}
|
||||
|
||||
status = find_file_in_dir( unix_name, pos, name, end - name,
|
||||
is_unix, redirect ? &is_win_dir : NULL );
|
||||
status = find_file_in_dir( unix_name, pos, name, end - name, is_unix );
|
||||
|
||||
/* if this is the last element, not finding it is not necessarily fatal */
|
||||
if (!name_len)
|
||||
|
@ -3202,14 +3234,6 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
|||
|
||||
pos += strlen( unix_name + pos );
|
||||
name = next;
|
||||
|
||||
if (is_win_dir && (len = get_redirect_path( unix_name, pos, name, name_len, is_unix )))
|
||||
{
|
||||
name += len;
|
||||
name_len -= len;
|
||||
pos += strlen( unix_name + pos );
|
||||
TRACE( "redirecting -> %s + %s\n", debugstr_a(unix_name), debugstr_w(name) );
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -3220,7 +3244,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
|||
* nt_to_unix_file_name_no_root
|
||||
*/
|
||||
static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char **unix_name_ret,
|
||||
UNICODE_STRING *nt_name, UINT disposition )
|
||||
UINT disposition )
|
||||
{
|
||||
static const WCHAR unixW[] = {'u','n','i','x'};
|
||||
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 };
|
||||
|
@ -3313,7 +3337,6 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char
|
|||
{
|
||||
TRACE( "%s -> %s\n", debugstr_us(nameW), debugstr_a(unix_name) );
|
||||
*unix_name_ret = unix_name;
|
||||
if (nt_name) rebuild_nt_name( nameW, name - nameW->Buffer, unix_name + pos, nt_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3333,8 +3356,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char
|
|||
* 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 nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret,
|
||||
UNICODE_STRING *nt_name, UINT disposition )
|
||||
NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition )
|
||||
{
|
||||
enum server_fd_type type;
|
||||
int old_cwd, root_fd, needs_close;
|
||||
|
@ -3344,7 +3366,7 @@ NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret,
|
|||
NTSTATUS status;
|
||||
|
||||
if (!attr->RootDirectory) /* without root dir fall back to normal lookup */
|
||||
return nt_to_unix_file_name_no_root( attr->ObjectName, name_ret, nt_name, disposition );
|
||||
return nt_to_unix_file_name_no_root( attr->ObjectName, name_ret, disposition );
|
||||
|
||||
name = attr->ObjectName->Buffer;
|
||||
name_len = attr->ObjectName->Length / sizeof(WCHAR);
|
||||
|
@ -3382,7 +3404,6 @@ NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret,
|
|||
{
|
||||
TRACE( "%s -> %s\n", debugstr_us(attr->ObjectName), debugstr_a(unix_name) );
|
||||
*name_ret = unix_name;
|
||||
if (nt_name) rebuild_nt_name( attr->ObjectName, 0, unix_name, nt_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3407,10 +3428,12 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, char *nam
|
|||
{
|
||||
char *buffer = NULL;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING redir;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
|
||||
InitializeObjectAttributes( &attr, (UNICODE_STRING *)nameW, OBJ_CASE_INSENSITIVE, 0, NULL );
|
||||
status = nt_to_unix_file_name( &attr, &buffer, NULL, disposition );
|
||||
get_redirect( &attr, &redir );
|
||||
status = nt_to_unix_file_name( &attr, &buffer, disposition );
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
|
@ -3419,6 +3442,7 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, char *nam
|
|||
*size = strlen(buffer) + 1;
|
||||
free( buffer );
|
||||
}
|
||||
free( redir.Buffer );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -3703,7 +3727,8 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
|
|||
ULONG attributes, ULONG sharing, ULONG disposition,
|
||||
ULONG options, void *ea_buffer, ULONG ea_length )
|
||||
{
|
||||
UNICODE_STRING nt_name = { 0 };
|
||||
OBJECT_ATTRIBUTES new_attr;
|
||||
UNICODE_STRING nt_name;
|
||||
char *unix_name;
|
||||
BOOL created = FALSE;
|
||||
|
||||
|
@ -3717,10 +3742,17 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
|
|||
|
||||
if (alloc_size) FIXME( "alloc_size not supported\n" );
|
||||
|
||||
new_attr = *attr;
|
||||
if (options & FILE_OPEN_BY_FILE_ID)
|
||||
io->u.Status = file_id_to_unix_file_name( attr, &unix_name, &nt_name );
|
||||
{
|
||||
io->u.Status = file_id_to_unix_file_name( &new_attr, &unix_name, &nt_name );
|
||||
if (!io->u.Status) new_attr.ObjectName = &nt_name;
|
||||
}
|
||||
else
|
||||
io->u.Status = nt_to_unix_file_name( attr, &unix_name, &nt_name, disposition );
|
||||
{
|
||||
get_redirect( &new_attr, &nt_name );
|
||||
io->u.Status = nt_to_unix_file_name( &new_attr, &unix_name, disposition );
|
||||
}
|
||||
|
||||
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
|
||||
{
|
||||
|
@ -3731,12 +3763,13 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
|
|||
req->rootdir = wine_server_obj_handle( attr->RootDirectory );
|
||||
req->sharing = sharing;
|
||||
req->options = options;
|
||||
wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
|
||||
wine_server_add_data( req, new_attr.ObjectName->Buffer, new_attr.ObjectName->Length );
|
||||
io->u.Status = wine_server_call( req );
|
||||
*handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
|
||||
free( nt_name.Buffer );
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
|
@ -3748,12 +3781,8 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
|
|||
|
||||
if (io->u.Status == STATUS_SUCCESS)
|
||||
{
|
||||
OBJECT_ATTRIBUTES nt_attr = *attr;
|
||||
|
||||
if (nt_name.Buffer) nt_attr.ObjectName = &nt_name;
|
||||
io->u.Status = open_unix_file( handle, unix_name, access, &nt_attr, attributes,
|
||||
io->u.Status = open_unix_file( handle, unix_name, access, &new_attr, attributes,
|
||||
sharing, disposition, options, ea_buffer, ea_length );
|
||||
free( nt_name.Buffer );
|
||||
free( unix_name );
|
||||
}
|
||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
|
||||
|
@ -3785,6 +3814,7 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
|
|||
if (!once++) ERR_(winediag)( "Too many open files, ulimit -n probably needs to be increased\n" );
|
||||
}
|
||||
|
||||
free( nt_name.Buffer );
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
|
@ -3906,8 +3936,11 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
|||
{
|
||||
char *unix_name;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING redir;
|
||||
OBJECT_ATTRIBUTES new_attr = *attr;
|
||||
|
||||
if (!(status = nt_to_unix_file_name( attr, &unix_name, NULL, FILE_OPEN )))
|
||||
get_redirect( &new_attr, &redir );
|
||||
if (!(status = nt_to_unix_file_name( &new_attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
ULONG attributes;
|
||||
struct stat st;
|
||||
|
@ -3936,6 +3969,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
|||
free( unix_name );
|
||||
}
|
||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||
free( redir.Buffer );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -3947,8 +3981,11 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
|||
{
|
||||
char *unix_name;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING redir;
|
||||
OBJECT_ATTRIBUTES new_attr = *attr;
|
||||
|
||||
if (!(status = nt_to_unix_file_name( attr, &unix_name, NULL, FILE_OPEN )))
|
||||
get_redirect( &new_attr, &redir );
|
||||
if (!(status = nt_to_unix_file_name( &new_attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
ULONG attributes;
|
||||
struct stat st;
|
||||
|
@ -3965,6 +4002,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
|||
free( unix_name );
|
||||
}
|
||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||
free( redir.Buffer );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -4497,38 +4535,35 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
|||
if (len >= sizeof(FILE_RENAME_INFORMATION))
|
||||
{
|
||||
FILE_RENAME_INFORMATION *info = ptr;
|
||||
UNICODE_STRING name_str, nt_name = { 0 };
|
||||
UNICODE_STRING name_str, redir;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
char *unix_name;
|
||||
|
||||
name_str.Buffer = info->FileName;
|
||||
name_str.Length = info->FileNameLength;
|
||||
name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
|
||||
InitializeObjectAttributes( &attr, &name_str, OBJ_CASE_INSENSITIVE, info->RootDirectory, NULL );
|
||||
get_redirect( &attr, &redir );
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.ObjectName = &name_str;
|
||||
attr.RootDirectory = info->RootDirectory;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
|
||||
io->u.Status = nt_to_unix_file_name( &attr, &unix_name, &nt_name, FILE_OPEN_IF );
|
||||
if (io->u.Status != STATUS_SUCCESS && io->u.Status != STATUS_NO_SUCH_FILE)
|
||||
break;
|
||||
|
||||
io->u.Status = nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN_IF );
|
||||
if (io->u.Status == STATUS_SUCCESS || io->u.Status == STATUS_NO_SUCH_FILE)
|
||||
{
|
||||
SERVER_START_REQ( set_fd_name_info )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
||||
req->namelen = nt_name.Length;
|
||||
req->namelen = attr.ObjectName->Length;
|
||||
req->link = FALSE;
|
||||
req->replace = info->ReplaceIfExists;
|
||||
wine_server_add_data( req, nt_name.Buffer, nt_name.Length );
|
||||
wine_server_add_data( req, attr.ObjectName->Buffer, attr.ObjectName->Length );
|
||||
wine_server_add_data( req, unix_name, strlen(unix_name) );
|
||||
io->u.Status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
free( unix_name );
|
||||
free( nt_name.Buffer );
|
||||
}
|
||||
free( redir.Buffer );
|
||||
}
|
||||
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
break;
|
||||
|
@ -4537,38 +4572,35 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
|||
if (len >= sizeof(FILE_LINK_INFORMATION))
|
||||
{
|
||||
FILE_LINK_INFORMATION *info = ptr;
|
||||
UNICODE_STRING name_str, nt_name = { 0 };
|
||||
UNICODE_STRING name_str, redir;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
char *unix_name;
|
||||
|
||||
name_str.Buffer = info->FileName;
|
||||
name_str.Length = info->FileNameLength;
|
||||
name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
|
||||
InitializeObjectAttributes( &attr, &name_str, OBJ_CASE_INSENSITIVE, info->RootDirectory, NULL );
|
||||
get_redirect( &attr, &redir );
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.ObjectName = &name_str;
|
||||
attr.RootDirectory = info->RootDirectory;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
|
||||
io->u.Status = nt_to_unix_file_name( &attr, &unix_name, &nt_name, FILE_OPEN_IF );
|
||||
if (io->u.Status != STATUS_SUCCESS && io->u.Status != STATUS_NO_SUCH_FILE)
|
||||
break;
|
||||
|
||||
io->u.Status = nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN_IF );
|
||||
if (io->u.Status == STATUS_SUCCESS || io->u.Status == STATUS_NO_SUCH_FILE)
|
||||
{
|
||||
SERVER_START_REQ( set_fd_name_info )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
||||
req->namelen = nt_name.Length;
|
||||
req->namelen = attr.ObjectName->Length;
|
||||
req->link = TRUE;
|
||||
req->replace = info->ReplaceIfExists;
|
||||
wine_server_add_data( req, nt_name.Buffer, nt_name.Length );
|
||||
wine_server_add_data( req, attr.ObjectName->Buffer, attr.ObjectName->Length );
|
||||
wine_server_add_data( req, unix_name, strlen(unix_name) );
|
||||
io->u.Status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
free( unix_name );
|
||||
free( nt_name.Buffer );
|
||||
}
|
||||
free( redir.Buffer );
|
||||
}
|
||||
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
break;
|
||||
|
|
|
@ -1105,6 +1105,7 @@ static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module )
|
|||
{
|
||||
static const WCHAR soW[] = {'.','s','o',0};
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING redir;
|
||||
pe_image_info_t info;
|
||||
char *unix_name;
|
||||
NTSTATUS status;
|
||||
|
@ -1112,7 +1113,13 @@ static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module )
|
|||
|
||||
if (get_load_order( nt_name ) == LO_DISABLED) return STATUS_DLL_NOT_FOUND;
|
||||
InitializeObjectAttributes( &attr, nt_name, OBJ_CASE_INSENSITIVE, 0, 0 );
|
||||
if (nt_to_unix_file_name( &attr, &unix_name, NULL, FILE_OPEN )) return STATUS_DLL_NOT_FOUND;
|
||||
get_redirect( &attr, &redir );
|
||||
|
||||
if (nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN ))
|
||||
{
|
||||
free( redir.Buffer );
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* remove .so extension from Windows name */
|
||||
len = nt_name->Length / sizeof(WCHAR);
|
||||
|
@ -1120,6 +1127,7 @@ static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module )
|
|||
|
||||
status = dlopen_dll( unix_name, nt_name, module, &info, FALSE );
|
||||
free( unix_name );
|
||||
free( redir.Buffer );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1398,8 +1406,7 @@ BOOL is_builtin_path( const UNICODE_STRING *path, WORD *machine )
|
|||
if (path->Length > wcslen(system_dir) * sizeof(WCHAR) &&
|
||||
!wcsnicmp( path->Buffer, system_dir, wcslen(system_dir) ))
|
||||
{
|
||||
if (NtCurrentTeb64() && NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR])
|
||||
*machine = IMAGE_FILE_MACHINE_AMD64;
|
||||
if (is_wow64) *machine = IMAGE_FILE_MACHINE_AMD64;
|
||||
goto found;
|
||||
}
|
||||
if ((is_win64 || is_wow64) && path->Length > sizeof(wow64W) &&
|
||||
|
@ -1439,7 +1446,7 @@ static NTSTATUS open_main_image( WCHAR *image, void **module, SECTION_IMAGE_INFO
|
|||
|
||||
init_unicode_string( &nt_name, image );
|
||||
InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
|
||||
if (nt_to_unix_file_name( &attr, &unix_name, NULL, FILE_OPEN )) return STATUS_DLL_NOT_FOUND;
|
||||
if (nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN )) return STATUS_DLL_NOT_FOUND;
|
||||
|
||||
status = open_dll_file( unix_name, &attr, &mapping );
|
||||
if (!status)
|
||||
|
@ -1536,11 +1543,13 @@ NTSTATUS load_start_exe( WCHAR **image, void **module )
|
|||
{
|
||||
static const WCHAR startW[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\',
|
||||
's','y','s','t','e','m','3','2','\\','s','t','a','r','t','.','e','x','e',0};
|
||||
static const WCHAR startwow64W[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\',
|
||||
's','y','s','w','o','w','6','4','\\','s','t','a','r','t','.','e','x','e',0};
|
||||
UNICODE_STRING nt_name;
|
||||
NTSTATUS status;
|
||||
SIZE_T size;
|
||||
|
||||
init_unicode_string( &nt_name, startW );
|
||||
init_unicode_string( &nt_name, is_wow64 ? startwow64W : startW );
|
||||
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, current_machine, FALSE );
|
||||
if (status)
|
||||
{
|
||||
|
|
|
@ -267,12 +267,18 @@ static NTSTATUS get_pe_file_info( OBJECT_ATTRIBUTES *attr, HANDLE *handle, pe_im
|
|||
{
|
||||
NTSTATUS status;
|
||||
HANDLE mapping;
|
||||
IO_STATUS_BLOCK io;
|
||||
char *unix_name;
|
||||
|
||||
*handle = 0;
|
||||
memset( info, 0, sizeof(*info) );
|
||||
if ((status = NtOpenFile( handle, GENERIC_READ, attr, &io,
|
||||
FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT )))
|
||||
if (!(status = nt_to_unix_file_name( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
status = open_unix_file( handle, unix_name, GENERIC_READ, attr, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
|
||||
free( unix_name );
|
||||
}
|
||||
if (status)
|
||||
{
|
||||
if (is_builtin_path( attr->ObjectName, &info->machine ))
|
||||
{
|
||||
|
@ -479,7 +485,7 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
|
|||
char *unix_name;
|
||||
NTSTATUS status;
|
||||
|
||||
status = nt_to_unix_file_name( attr, &unix_name, NULL, FILE_OPEN );
|
||||
status = nt_to_unix_file_name( attr, &unix_name, FILE_OPEN );
|
||||
if (status) return status;
|
||||
|
||||
#ifdef HAVE_PIPE2
|
||||
|
@ -613,7 +619,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
|
|||
pe_image_info_t pe_info;
|
||||
CLIENT_ID id;
|
||||
HANDLE parent = 0, debug = 0, token = 0;
|
||||
UNICODE_STRING path = {0};
|
||||
UNICODE_STRING redir, path = {0};
|
||||
OBJECT_ATTRIBUTES attr, empty_attr = { sizeof(empty_attr) };
|
||||
SIZE_T i, attr_count = (ps_attr->TotalLength - sizeof(ps_attr->TotalLength)) / sizeof(PS_ATTRIBUTE);
|
||||
const PS_ATTRIBUTE *handles_attr = NULL;
|
||||
|
@ -655,16 +661,19 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
|
|||
unixdir = get_unix_curdir( params );
|
||||
|
||||
InitializeObjectAttributes( &attr, &path, OBJ_CASE_INSENSITIVE, 0, 0 );
|
||||
get_redirect( &attr, &redir );
|
||||
|
||||
if ((status = get_pe_file_info( &attr, &file_handle, &pe_info )))
|
||||
{
|
||||
if (status == STATUS_INVALID_IMAGE_NOT_MZ && !fork_and_exec( &attr, unixdir, params ))
|
||||
{
|
||||
memset( info, 0, sizeof(*info) );
|
||||
free( redir.Buffer );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
if (!(startup_info = create_startup_info( params, &startup_info_size ))) goto done;
|
||||
if (!(startup_info = create_startup_info( attr.ObjectName, params, &startup_info_size ))) goto done;
|
||||
env_size = get_env_size( params, &winedebug );
|
||||
|
||||
if ((status = alloc_object_attributes( process_attr, &objattr, &attr_len ))) goto done;
|
||||
|
@ -830,6 +839,7 @@ done:
|
|||
if (unixdir != -1) close( unixdir );
|
||||
free( startup_info );
|
||||
free( winedebug );
|
||||
free( redir.Buffer );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,8 @@ extern struct ldt_copy __wine_ldt_copy DECLSPEC_HIDDEN;
|
|||
|
||||
extern void init_environment( int argc, char *argv[], char *envp[] ) DECLSPEC_HIDDEN;
|
||||
extern void init_startup_info(void) DECLSPEC_HIDDEN;
|
||||
extern void *create_startup_info( const RTL_USER_PROCESS_PARAMETERS *params, DWORD *info_size ) DECLSPEC_HIDDEN;
|
||||
extern void *create_startup_info( const UNICODE_STRING *nt_image, const RTL_USER_PROCESS_PARAMETERS *params,
|
||||
DWORD *info_size ) DECLSPEC_HIDDEN;
|
||||
extern DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen ) DECLSPEC_HIDDEN;
|
||||
extern int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict ) DECLSPEC_HIDDEN;
|
||||
extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN;
|
||||
|
@ -250,8 +251,8 @@ 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 OBJECT_ATTRIBUTES *attr, char **name_ret,
|
||||
UNICODE_STRING *nt_name, UINT disposition ) DECLSPEC_HIDDEN;
|
||||
extern BOOL get_redirect( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *redir ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS unix_to_nt_file_name( const char *name, WCHAR **nt ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS get_full_path( const WCHAR *name, const WCHAR *curdir, WCHAR **path ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MASK access,
|
||||
|
|
Loading…
Reference in New Issue