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
|
* 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;
|
startup_info_t *info;
|
||||||
|
UNICODE_STRING dos_image = *nt_image;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
void *ptr;
|
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 = sizeof(*info);
|
||||||
size += params->CurrentDirectory.DosPath.Length;
|
size += params->CurrentDirectory.DosPath.Length;
|
||||||
size += params->DllPath.Length;
|
size += params->DllPath.Length;
|
||||||
size += params->ImagePathName.Length;
|
size += dos_image.Length;
|
||||||
size += params->CommandLine.Length;
|
size += params->CommandLine.Length;
|
||||||
size += params->WindowTitle.Length;
|
size += params->WindowTitle.Length;
|
||||||
size += params->Desktop.Length;
|
size += params->Desktop.Length;
|
||||||
|
@ -2172,7 +2177,7 @@ void *create_startup_info( const RTL_USER_PROCESS_PARAMETERS *params, DWORD *inf
|
||||||
ptr = info + 1;
|
ptr = info + 1;
|
||||||
info->curdir_len = append_string( &ptr, params, ¶ms->CurrentDirectory.DosPath );
|
info->curdir_len = append_string( &ptr, params, ¶ms->CurrentDirectory.DosPath );
|
||||||
info->dllpath_len = append_string( &ptr, params, ¶ms->DllPath );
|
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->cmdline_len = append_string( &ptr, params, ¶ms->CommandLine );
|
||||||
info->title_len = append_string( &ptr, params, ¶ms->WindowTitle );
|
info->title_len = append_string( &ptr, params, ¶ms->WindowTitle );
|
||||||
info->desktop_len = append_string( &ptr, params, ¶ms->Desktop );
|
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 */
|
/* at some point we may want to allow Winelib apps to set this */
|
||||||
static const BOOL is_case_sensitive = FALSE;
|
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 dir_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_mutex_t mnt_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.
|
* 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,
|
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];
|
WCHAR buffer[MAX_DIR_ENTRY_LEN];
|
||||||
BOOLEAN is_name_8_dot_3;
|
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)
|
if (ret >= 0 && ret <= MAX_DIR_ENTRY_LEN)
|
||||||
{
|
{
|
||||||
unix_name[pos + ret] = 0;
|
unix_name[pos + ret] = 0;
|
||||||
if (!stat( unix_name, &st ))
|
if (!stat( unix_name, &st )) return STATUS_SUCCESS;
|
||||||
{
|
|
||||||
if (is_win_dir) *is_win_dir = is_same_file( &windir, &st );
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (check_case) goto not_found; /* we want an exact match */
|
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 );
|
strcpy( unix_name + pos, kde[1].d_name );
|
||||||
close( fd );
|
close( fd );
|
||||||
goto success;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = ntdll_umbstowcs( kde[0].d_name, strlen(kde[0].d_name),
|
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,
|
strcpy( unix_name + pos,
|
||||||
kde[1].d_name[0] ? kde[1].d_name : kde[0].d_name );
|
kde[1].d_name[0] ? kde[1].d_name : kde[0].d_name );
|
||||||
close( fd );
|
close( fd );
|
||||||
goto success;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)kde ) == -1)
|
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 );
|
strcpy( unix_name + pos, de->d_name );
|
||||||
closedir( dir );
|
closedir( dir );
|
||||||
goto success;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_name_8_dot_3) continue;
|
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 );
|
strcpy( unix_name + pos, de->d_name );
|
||||||
closedir( dir );
|
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:
|
not_found:
|
||||||
unix_name[pos - 1] = 0;
|
unix_name[pos - 1] = 0;
|
||||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
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 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 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 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 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 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;
|
catrootW,
|
||||||
const char *unix_target;
|
catroot2W,
|
||||||
} redirects[] =
|
driversstoreW,
|
||||||
{
|
driversetcW,
|
||||||
{ catrootW, NULL },
|
logfilesW,
|
||||||
{ catroot2W, NULL },
|
spoolW
|
||||||
{ driversstoreW, NULL },
|
|
||||||
{ driversetcW, NULL },
|
|
||||||
{ logfilesW, NULL },
|
|
||||||
{ spoolW, NULL },
|
|
||||||
{ system32W, "syswow64" },
|
|
||||||
{ sysnativeW, "system32" },
|
|
||||||
{ regeditW, "syswow64/regedit.exe" }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
* init_redirects
|
||||||
*/
|
*/
|
||||||
static void init_redirects(void)
|
static void init_redirects(void)
|
||||||
{
|
{
|
||||||
static const char windows_dir[] = "/dosdevices/c:/windows";
|
static const char system_dir[] = "/dosdevices/c:/windows/system32";
|
||||||
char *dir;
|
char *dir;
|
||||||
struct stat st;
|
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 );
|
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 ))
|
if (!stat( dir, &st ))
|
||||||
{
|
{
|
||||||
windir.dev = st.st_dev;
|
windir.dev = st.st_dev;
|
||||||
windir.ino = st.st_ino;
|
windir.ino = st.st_ino;
|
||||||
nb_redirects = ARRAY_SIZE( redirects );
|
|
||||||
}
|
}
|
||||||
else ERR( "%s: %s\n", dir, strerror(errno) );
|
else ERR( "%s: %s\n", dir, strerror(errno) );
|
||||||
free( dir );
|
free( dir );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* match_redirect
|
* get_redirect
|
||||||
*
|
|
||||||
* Check if path matches a redirect name. If yes, return matched length.
|
|
||||||
*/
|
*/
|
||||||
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;
|
prefix_len = wcslen( windirW );
|
||||||
while (i < len && !IS_SEPARATOR(path[i])) i++;
|
if (len < prefix_len || wcsnicmp( name, windirW, prefix_len )) return FALSE;
|
||||||
if (check_case)
|
|
||||||
{
|
|
||||||
if (wcsncmp( path + start, redir, i - start )) return 0;
|
|
||||||
}
|
|
||||||
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;
|
else
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* 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 ((len = match_redirect( name, length, redirects[i].source, check_case )))
|
int fd, needs_close;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
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 (!redirects[i].unix_target) break;
|
if (!is_same_file( &sysdir, &st )) return FALSE;
|
||||||
unix_name[pos++] = '/';
|
if (NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR]) return FALSE;
|
||||||
strcpy( unix_name + pos, redirects[i].unix_target );
|
if (name[0] == '\\') return FALSE;
|
||||||
return len;
|
|
||||||
|
/* 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 */
|
#else /* _WIN64 */
|
||||||
|
|
||||||
/* there are no redirects on 64-bit */
|
/* 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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
|
#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;
|
ULONGLONG file_id;
|
||||||
struct stat st, root_st;
|
struct stat st, root_st;
|
||||||
|
|
||||||
|
nt_name->Buffer = NULL;
|
||||||
if (attr->ObjectName->Length != sizeof(ULONGLONG)) return STATUS_OBJECT_PATH_SYNTAX_BAD;
|
if (attr->ObjectName->Length != sizeof(ULONGLONG)) return STATUS_OBJECT_PATH_SYNTAX_BAD;
|
||||||
if (!attr->RootDirectory) return STATUS_INVALID_PARAMETER;
|
if (!attr->RootDirectory) return STATUS_INVALID_PARAMETER;
|
||||||
memcpy( &file_id, attr->ObjectName->Buffer, sizeof(file_id) );
|
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 };
|
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, '/', 0 };
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
int ret, len;
|
int ret;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *unix_name = *buffer;
|
char *unix_name = *buffer;
|
||||||
const WCHAR *ptr, *end;
|
const WCHAR *ptr, *end;
|
||||||
const BOOL redirect = NtCurrentTeb64() && !NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR];
|
|
||||||
|
|
||||||
/* check syntax of individual components */
|
/* check syntax of individual components */
|
||||||
|
|
||||||
|
@ -3132,20 +3170,16 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
||||||
char *p;
|
char *p;
|
||||||
unix_name[pos + 1 + ret] = 0;
|
unix_name[pos + 1 + ret] = 0;
|
||||||
for (p = unix_name + pos ; *p; p++) if (*p == '\\') *p = '/';
|
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 (!stat( unix_name, &st ))
|
if (disposition == FILE_CREATE) return STATUS_OBJECT_NAME_COLLISION;
|
||||||
{
|
return STATUS_SUCCESS;
|
||||||
if (disposition == FILE_CREATE)
|
|
||||||
return STATUS_OBJECT_NAME_COLLISION;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name_len) /* empty name -> drive root doesn't exist */
|
if (!name_len) /* empty name -> drive root doesn't exist */
|
||||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
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;
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
/* now do it component by component */
|
/* 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)
|
while (name_len)
|
||||||
{
|
{
|
||||||
const WCHAR *end, *next;
|
const WCHAR *end, *next;
|
||||||
BOOLEAN is_win_dir = FALSE;
|
|
||||||
|
|
||||||
end = name;
|
end = name;
|
||||||
while (end < name + name_len && *end != '\\') end++;
|
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;
|
unix_name = *buffer = new_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = find_file_in_dir( unix_name, pos, name, end - name,
|
status = find_file_in_dir( unix_name, pos, name, end - name, is_unix );
|
||||||
is_unix, redirect ? &is_win_dir : NULL );
|
|
||||||
|
|
||||||
/* if this is the last element, not finding it is not necessarily fatal */
|
/* if this is the last element, not finding it is not necessarily fatal */
|
||||||
if (!name_len)
|
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 );
|
pos += strlen( unix_name + pos );
|
||||||
name = next;
|
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;
|
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
|
* nt_to_unix_file_name_no_root
|
||||||
*/
|
*/
|
||||||
static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char **unix_name_ret,
|
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 unixW[] = {'u','n','i','x'};
|
||||||
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 };
|
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) );
|
TRACE( "%s -> %s\n", debugstr_us(nameW), debugstr_a(unix_name) );
|
||||||
*unix_name_ret = unix_name;
|
*unix_name_ret = unix_name;
|
||||||
if (nt_name) rebuild_nt_name( nameW, name - nameW->Buffer, unix_name + pos, nt_name );
|
|
||||||
}
|
}
|
||||||
else
|
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
|
* element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is
|
||||||
* returned, but the unix name is still filled in properly.
|
* returned, but the unix name is still filled in properly.
|
||||||
*/
|
*/
|
||||||
NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret,
|
NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition )
|
||||||
UNICODE_STRING *nt_name, UINT disposition )
|
|
||||||
{
|
{
|
||||||
enum server_fd_type type;
|
enum server_fd_type type;
|
||||||
int old_cwd, root_fd, needs_close;
|
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;
|
NTSTATUS status;
|
||||||
|
|
||||||
if (!attr->RootDirectory) /* without root dir fall back to normal lookup */
|
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 = attr->ObjectName->Buffer;
|
||||||
name_len = attr->ObjectName->Length / sizeof(WCHAR);
|
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) );
|
TRACE( "%s -> %s\n", debugstr_us(attr->ObjectName), debugstr_a(unix_name) );
|
||||||
*name_ret = unix_name;
|
*name_ret = unix_name;
|
||||||
if (nt_name) rebuild_nt_name( attr->ObjectName, 0, unix_name, nt_name );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3407,10 +3428,12 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, char *nam
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
UNICODE_STRING redir;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
|
||||||
InitializeObjectAttributes( &attr, (UNICODE_STRING *)nameW, OBJ_CASE_INSENSITIVE, 0, NULL );
|
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)
|
if (buffer)
|
||||||
{
|
{
|
||||||
|
@ -3419,6 +3442,7 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, char *nam
|
||||||
*size = strlen(buffer) + 1;
|
*size = strlen(buffer) + 1;
|
||||||
free( buffer );
|
free( buffer );
|
||||||
}
|
}
|
||||||
|
free( redir.Buffer );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3703,7 +3727,8 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
|
||||||
ULONG attributes, ULONG sharing, ULONG disposition,
|
ULONG attributes, ULONG sharing, ULONG disposition,
|
||||||
ULONG options, void *ea_buffer, ULONG ea_length )
|
ULONG options, void *ea_buffer, ULONG ea_length )
|
||||||
{
|
{
|
||||||
UNICODE_STRING nt_name = { 0 };
|
OBJECT_ATTRIBUTES new_attr;
|
||||||
|
UNICODE_STRING nt_name;
|
||||||
char *unix_name;
|
char *unix_name;
|
||||||
BOOL created = FALSE;
|
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" );
|
if (alloc_size) FIXME( "alloc_size not supported\n" );
|
||||||
|
|
||||||
|
new_attr = *attr;
|
||||||
if (options & FILE_OPEN_BY_FILE_ID)
|
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
|
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)
|
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->rootdir = wine_server_obj_handle( attr->RootDirectory );
|
||||||
req->sharing = sharing;
|
req->sharing = sharing;
|
||||||
req->options = options;
|
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 );
|
io->u.Status = wine_server_call( req );
|
||||||
*handle = wine_server_ptr_handle( reply->handle );
|
*handle = wine_server_ptr_handle( reply->handle );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
|
if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
|
||||||
|
free( nt_name.Buffer );
|
||||||
return io->u.Status;
|
return io->u.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3748,12 +3781,8 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
|
||||||
|
|
||||||
if (io->u.Status == STATUS_SUCCESS)
|
if (io->u.Status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES nt_attr = *attr;
|
io->u.Status = open_unix_file( handle, unix_name, access, &new_attr, attributes,
|
||||||
|
|
||||||
if (nt_name.Buffer) nt_attr.ObjectName = &nt_name;
|
|
||||||
io->u.Status = open_unix_file( handle, unix_name, access, &nt_attr, attributes,
|
|
||||||
sharing, disposition, options, ea_buffer, ea_length );
|
sharing, disposition, options, ea_buffer, ea_length );
|
||||||
free( nt_name.Buffer );
|
|
||||||
free( unix_name );
|
free( unix_name );
|
||||||
}
|
}
|
||||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
|
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" );
|
if (!once++) ERR_(winediag)( "Too many open files, ulimit -n probably needs to be increased\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free( nt_name.Buffer );
|
||||||
return io->u.Status;
|
return io->u.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3906,8 +3936,11 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
||||||
{
|
{
|
||||||
char *unix_name;
|
char *unix_name;
|
||||||
NTSTATUS status;
|
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;
|
ULONG attributes;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -3936,6 +3969,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
||||||
free( unix_name );
|
free( unix_name );
|
||||||
}
|
}
|
||||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||||
|
free( redir.Buffer );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3947,8 +3981,11 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
||||||
{
|
{
|
||||||
char *unix_name;
|
char *unix_name;
|
||||||
NTSTATUS status;
|
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;
|
ULONG attributes;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -3965,6 +4002,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
||||||
free( unix_name );
|
free( unix_name );
|
||||||
}
|
}
|
||||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||||
|
free( redir.Buffer );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4497,38 +4535,35 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||||
if (len >= sizeof(FILE_RENAME_INFORMATION))
|
if (len >= sizeof(FILE_RENAME_INFORMATION))
|
||||||
{
|
{
|
||||||
FILE_RENAME_INFORMATION *info = ptr;
|
FILE_RENAME_INFORMATION *info = ptr;
|
||||||
UNICODE_STRING name_str, nt_name = { 0 };
|
UNICODE_STRING name_str, redir;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
char *unix_name;
|
char *unix_name;
|
||||||
|
|
||||||
name_str.Buffer = info->FileName;
|
name_str.Buffer = info->FileName;
|
||||||
name_str.Length = info->FileNameLength;
|
name_str.Length = info->FileNameLength;
|
||||||
name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
|
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);
|
io->u.Status = nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN_IF );
|
||||||
attr.ObjectName = &name_str;
|
if (io->u.Status == STATUS_SUCCESS || io->u.Status == STATUS_NO_SUCH_FILE)
|
||||||
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;
|
|
||||||
|
|
||||||
SERVER_START_REQ( set_fd_name_info )
|
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
SERVER_START_REQ( set_fd_name_info )
|
||||||
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
{
|
||||||
req->namelen = nt_name.Length;
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->link = FALSE;
|
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
||||||
req->replace = info->ReplaceIfExists;
|
req->namelen = attr.ObjectName->Length;
|
||||||
wine_server_add_data( req, nt_name.Buffer, nt_name.Length );
|
req->link = FALSE;
|
||||||
wine_server_add_data( req, unix_name, strlen(unix_name) );
|
req->replace = info->ReplaceIfExists;
|
||||||
io->u.Status = wine_server_call( req );
|
wine_server_add_data( req, attr.ObjectName->Buffer, attr.ObjectName->Length );
|
||||||
}
|
wine_server_add_data( req, unix_name, strlen(unix_name) );
|
||||||
SERVER_END_REQ;
|
io->u.Status = wine_server_call( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
free( unix_name );
|
free( unix_name );
|
||||||
free( nt_name.Buffer );
|
}
|
||||||
|
free( redir.Buffer );
|
||||||
}
|
}
|
||||||
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||||
break;
|
break;
|
||||||
|
@ -4537,38 +4572,35 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||||
if (len >= sizeof(FILE_LINK_INFORMATION))
|
if (len >= sizeof(FILE_LINK_INFORMATION))
|
||||||
{
|
{
|
||||||
FILE_LINK_INFORMATION *info = ptr;
|
FILE_LINK_INFORMATION *info = ptr;
|
||||||
UNICODE_STRING name_str, nt_name = { 0 };
|
UNICODE_STRING name_str, redir;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
char *unix_name;
|
char *unix_name;
|
||||||
|
|
||||||
name_str.Buffer = info->FileName;
|
name_str.Buffer = info->FileName;
|
||||||
name_str.Length = info->FileNameLength;
|
name_str.Length = info->FileNameLength;
|
||||||
name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
|
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);
|
io->u.Status = nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN_IF );
|
||||||
attr.ObjectName = &name_str;
|
if (io->u.Status == STATUS_SUCCESS || io->u.Status == STATUS_NO_SUCH_FILE)
|
||||||
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;
|
|
||||||
|
|
||||||
SERVER_START_REQ( set_fd_name_info )
|
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
SERVER_START_REQ( set_fd_name_info )
|
||||||
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
{
|
||||||
req->namelen = nt_name.Length;
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->link = TRUE;
|
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
||||||
req->replace = info->ReplaceIfExists;
|
req->namelen = attr.ObjectName->Length;
|
||||||
wine_server_add_data( req, nt_name.Buffer, nt_name.Length );
|
req->link = TRUE;
|
||||||
wine_server_add_data( req, unix_name, strlen(unix_name) );
|
req->replace = info->ReplaceIfExists;
|
||||||
io->u.Status = wine_server_call( req );
|
wine_server_add_data( req, attr.ObjectName->Buffer, attr.ObjectName->Length );
|
||||||
}
|
wine_server_add_data( req, unix_name, strlen(unix_name) );
|
||||||
SERVER_END_REQ;
|
io->u.Status = wine_server_call( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
free( unix_name );
|
free( unix_name );
|
||||||
free( nt_name.Buffer );
|
}
|
||||||
|
free( redir.Buffer );
|
||||||
}
|
}
|
||||||
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1105,6 +1105,7 @@ static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module )
|
||||||
{
|
{
|
||||||
static const WCHAR soW[] = {'.','s','o',0};
|
static const WCHAR soW[] = {'.','s','o',0};
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
UNICODE_STRING redir;
|
||||||
pe_image_info_t info;
|
pe_image_info_t info;
|
||||||
char *unix_name;
|
char *unix_name;
|
||||||
NTSTATUS status;
|
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;
|
if (get_load_order( nt_name ) == LO_DISABLED) return STATUS_DLL_NOT_FOUND;
|
||||||
InitializeObjectAttributes( &attr, nt_name, OBJ_CASE_INSENSITIVE, 0, 0 );
|
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 */
|
/* remove .so extension from Windows name */
|
||||||
len = nt_name->Length / sizeof(WCHAR);
|
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 );
|
status = dlopen_dll( unix_name, nt_name, module, &info, FALSE );
|
||||||
free( unix_name );
|
free( unix_name );
|
||||||
|
free( redir.Buffer );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,8 +1406,7 @@ BOOL is_builtin_path( const UNICODE_STRING *path, WORD *machine )
|
||||||
if (path->Length > wcslen(system_dir) * sizeof(WCHAR) &&
|
if (path->Length > wcslen(system_dir) * sizeof(WCHAR) &&
|
||||||
!wcsnicmp( path->Buffer, system_dir, wcslen(system_dir) ))
|
!wcsnicmp( path->Buffer, system_dir, wcslen(system_dir) ))
|
||||||
{
|
{
|
||||||
if (NtCurrentTeb64() && NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR])
|
if (is_wow64) *machine = IMAGE_FILE_MACHINE_AMD64;
|
||||||
*machine = IMAGE_FILE_MACHINE_AMD64;
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
if ((is_win64 || is_wow64) && path->Length > sizeof(wow64W) &&
|
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 );
|
init_unicode_string( &nt_name, image );
|
||||||
InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
|
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 );
|
status = open_dll_file( unix_name, &attr, &mapping );
|
||||||
if (!status)
|
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','\\',
|
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};
|
'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;
|
UNICODE_STRING nt_name;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
SIZE_T size;
|
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 );
|
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, current_machine, FALSE );
|
||||||
if (status)
|
if (status)
|
||||||
{
|
{
|
||||||
|
|
|
@ -267,12 +267,18 @@ static NTSTATUS get_pe_file_info( OBJECT_ATTRIBUTES *attr, HANDLE *handle, pe_im
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
HANDLE mapping;
|
HANDLE mapping;
|
||||||
IO_STATUS_BLOCK io;
|
char *unix_name;
|
||||||
|
|
||||||
*handle = 0;
|
*handle = 0;
|
||||||
memset( info, 0, sizeof(*info) );
|
memset( info, 0, sizeof(*info) );
|
||||||
if ((status = NtOpenFile( handle, GENERIC_READ, attr, &io,
|
if (!(status = nt_to_unix_file_name( attr, &unix_name, FILE_OPEN )))
|
||||||
FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT )))
|
{
|
||||||
|
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 ))
|
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;
|
char *unix_name;
|
||||||
NTSTATUS status;
|
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;
|
if (status) return status;
|
||||||
|
|
||||||
#ifdef HAVE_PIPE2
|
#ifdef HAVE_PIPE2
|
||||||
|
@ -613,7 +619,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
|
||||||
pe_image_info_t pe_info;
|
pe_image_info_t pe_info;
|
||||||
CLIENT_ID id;
|
CLIENT_ID id;
|
||||||
HANDLE parent = 0, debug = 0, token = 0;
|
HANDLE parent = 0, debug = 0, token = 0;
|
||||||
UNICODE_STRING path = {0};
|
UNICODE_STRING redir, path = {0};
|
||||||
OBJECT_ATTRIBUTES attr, empty_attr = { sizeof(empty_attr) };
|
OBJECT_ATTRIBUTES attr, empty_attr = { sizeof(empty_attr) };
|
||||||
SIZE_T i, attr_count = (ps_attr->TotalLength - sizeof(ps_attr->TotalLength)) / sizeof(PS_ATTRIBUTE);
|
SIZE_T i, attr_count = (ps_attr->TotalLength - sizeof(ps_attr->TotalLength)) / sizeof(PS_ATTRIBUTE);
|
||||||
const PS_ATTRIBUTE *handles_attr = NULL;
|
const PS_ATTRIBUTE *handles_attr = NULL;
|
||||||
|
@ -655,16 +661,19 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
|
||||||
unixdir = get_unix_curdir( params );
|
unixdir = get_unix_curdir( params );
|
||||||
|
|
||||||
InitializeObjectAttributes( &attr, &path, OBJ_CASE_INSENSITIVE, 0, 0 );
|
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 = get_pe_file_info( &attr, &file_handle, &pe_info )))
|
||||||
{
|
{
|
||||||
if (status == STATUS_INVALID_IMAGE_NOT_MZ && !fork_and_exec( &attr, unixdir, params ))
|
if (status == STATUS_INVALID_IMAGE_NOT_MZ && !fork_and_exec( &attr, unixdir, params ))
|
||||||
{
|
{
|
||||||
memset( info, 0, sizeof(*info) );
|
memset( info, 0, sizeof(*info) );
|
||||||
|
free( redir.Buffer );
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
goto done;
|
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 );
|
env_size = get_env_size( params, &winedebug );
|
||||||
|
|
||||||
if ((status = alloc_object_attributes( process_attr, &objattr, &attr_len ))) goto done;
|
if ((status = alloc_object_attributes( process_attr, &objattr, &attr_len ))) goto done;
|
||||||
|
@ -830,6 +839,7 @@ done:
|
||||||
if (unixdir != -1) close( unixdir );
|
if (unixdir != -1) close( unixdir );
|
||||||
free( startup_info );
|
free( startup_info );
|
||||||
free( winedebug );
|
free( winedebug );
|
||||||
|
free( redir.Buffer );
|
||||||
return status;
|
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_environment( int argc, char *argv[], char *envp[] ) DECLSPEC_HIDDEN;
|
||||||
extern void init_startup_info(void) 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 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 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;
|
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;
|
ULONG in_size, void *out_buffer, ULONG out_size ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern NTSTATUS errno_to_status( int err ) 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,
|
extern BOOL get_redirect( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *redir ) DECLSPEC_HIDDEN;
|
||||||
UNICODE_STRING *nt_name, UINT disposition ) 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 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 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,
|
extern NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MASK access,
|
||||||
|
|
Loading…
Reference in New Issue