Commit 76b32843 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Pass the NT name in the create_file request.

parent d7bdd5a5
......@@ -157,27 +157,28 @@ static NTSTATUS open_nls_data_file( ULONG type, ULONG id, HANDLE *file )
NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
IO_STATUS_BLOCK io;
OBJECT_ATTRIBUTES attr = { sizeof(attr) };
OBJECT_ATTRIBUTES attr;
UNICODE_STRING valueW;
WCHAR buffer[ARRAY_SIZE(sortdirW) + 16];
char *p, *path = get_nls_file_path( type, id );
if (!path) return STATUS_OBJECT_NAME_NOT_FOUND;
/* try to open file in system dir */
ntdll_wcscpy( buffer, type == NLS_SECTION_SORTKEYS ? sortdirW : systemdirW );
p = strrchr( path, '/' ) + 1;
ascii_to_unicode( buffer + ntdll_wcslen(buffer), p, strlen(p) + 1 );
valueW.Buffer = buffer;
valueW.Length = ntdll_wcslen( buffer ) * sizeof(WCHAR);
valueW.MaximumLength = sizeof( buffer );
InitializeObjectAttributes( &attr, &valueW, 0, 0, NULL );
status = open_unix_file( file, path, GENERIC_READ, &attr, 0, FILE_SHARE_READ,
FILE_OPEN, FILE_SYNCHRONOUS_IO_ALERT, NULL, 0 );
if (status == STATUS_NO_SUCH_FILE)
{
/* try to open file in system dir */
ntdll_wcscpy( buffer, type == NLS_SECTION_SORTKEYS ? sortdirW : systemdirW );
p = strrchr( path, '/' ) + 1;
ascii_to_unicode( buffer + ntdll_wcslen(buffer), p, strlen(p) + 1 );
valueW.Buffer = buffer;
valueW.Length = ntdll_wcslen( buffer ) * sizeof(WCHAR);
valueW.MaximumLength = sizeof( buffer );
InitializeObjectAttributes( &attr, &valueW, 0, 0, NULL );
status = NtOpenFile( file, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
}
free( path );
return status;
}
......
......@@ -2930,6 +2930,29 @@ static NTSTATUS find_drive_rootA( LPCSTR *ppath, unsigned int len, int *drive_re
/******************************************************************************
* rebuild_nt_name
*/
static void rebuild_nt_name( const UNICODE_STRING *nameW, DWORD prefix_len,
const char *unix_name, UNICODE_STRING *nt_name )
{
WCHAR *buf;
DWORD len;
while (*unix_name == '/') unix_name++;
nt_name->MaximumLength = (prefix_len + strlen(unix_name) + 2) * sizeof(WCHAR);
if (!(buf = malloc( nt_name->MaximumLength ))) return;
nt_name->Buffer = buf;
memcpy( buf, nameW->Buffer, prefix_len * sizeof(WCHAR) );
if (prefix_len && buf[prefix_len - 1] != '\\') buf[prefix_len++] = '\\';
buf += prefix_len;
len = ntdll_umbstowcs( unix_name, strlen(unix_name), buf, strlen(unix_name) );
for (; len; len--, buf++) if (*buf == '/') *buf = '\\';
*buf = 0;
nt_name->Length = (buf - nt_name->Buffer) * sizeof(WCHAR);
}
/******************************************************************************
* find_file_id
*
* Recursively search directories from the dir queue for a given inode.
......@@ -2988,7 +3011,8 @@ static NTSTATUS find_file_id( char **unix_name, ULONG *len, ULONGLONG file_id, d
*
* Lookup a file from its file id instead of its name.
*/
static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **unix_name_ret )
static NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **unix_name_ret,
UNICODE_STRING *nt_name )
{
enum server_fd_type type;
int old_cwd, root_fd, needs_close;
......@@ -3051,6 +3075,7 @@ done:
{
TRACE( "%s -> %s\n", wine_dbgstr_longlong(file_id), debugstr_a(unix_name) );
*unix_name_ret = unix_name;
if (nt_name) rebuild_nt_name( attr->ObjectName, 0, unix_name, nt_name );
}
else
{
......@@ -3183,7 +3208,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
* nt_to_unix_file_name_attr
*/
static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, char **name_ret,
UINT disposition )
UNICODE_STRING *nt_name, UINT disposition )
{
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 };
enum server_fd_type type;
......@@ -3194,7 +3219,7 @@ static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, char *
NTSTATUS status;
if (!attr->RootDirectory) /* without root dir fall back to normal lookup */
return nt_to_unix_file_name( attr->ObjectName, name_ret, disposition );
return nt_to_unix_file_name( attr->ObjectName, name_ret, nt_name, disposition );
name = attr->ObjectName->Buffer;
name_len = attr->ObjectName->Length / sizeof(WCHAR);
......@@ -3237,6 +3262,7 @@ static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, char *
{
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
{
......@@ -3256,7 +3282,8 @@ static NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, 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 UNICODE_STRING *nameW, char **unix_name_ret, UINT disposition )
NTSTATUS nt_to_unix_file_name( const UNICODE_STRING *nameW, char **unix_name_ret,
UNICODE_STRING *nt_name, UINT disposition )
{
static const WCHAR unixW[] = {'u','n','i','x'};
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 };
......@@ -3352,6 +3379,7 @@ NTSTATUS nt_to_unix_file_name( const UNICODE_STRING *nameW, char **unix_name_ret
{
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
{
......@@ -3375,7 +3403,7 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, char *nam
UINT disposition )
{
char *buffer = NULL;
NTSTATUS status = nt_to_unix_file_name( nameW, &buffer, disposition );
NTSTATUS status = nt_to_unix_file_name( nameW, &buffer, NULL, disposition );
if (buffer)
{
......@@ -3512,14 +3540,11 @@ NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MASK acce
OBJECT_ATTRIBUTES *attr, ULONG attributes, ULONG sharing, ULONG disposition,
ULONG options, void *ea_buffer, ULONG ea_length )
{
static UNICODE_STRING empty_string;
struct object_attributes *objattr;
OBJECT_ATTRIBUTES unix_attr = *attr;
NTSTATUS status;
data_size_t len;
unix_attr.ObjectName = &empty_string; /* we send the unix name instead */
if ((status = alloc_object_attributes( &unix_attr, &objattr, &len ))) return status;
if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status;
SERVER_START_REQ( create_file )
{
......@@ -3547,6 +3572,7 @@ 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 };
char *unix_name;
BOOL created = FALSE;
......@@ -3561,9 +3587,9 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
if (alloc_size) FIXME( "alloc_size not supported\n" );
if (options & FILE_OPEN_BY_FILE_ID)
io->u.Status = file_id_to_unix_file_name( attr, &unix_name );
io->u.Status = file_id_to_unix_file_name( attr, &unix_name, &nt_name );
else
io->u.Status = nt_to_unix_file_name_attr( attr, &unix_name, disposition );
io->u.Status = nt_to_unix_file_name_attr( attr, &unix_name, &nt_name, disposition );
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
{
......@@ -3591,8 +3617,12 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU
if (io->u.Status == STATUS_SUCCESS)
{
io->u.Status = open_unix_file( handle, unix_name, access, attr, attributes,
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,
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 );
......@@ -3746,7 +3776,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
char *unix_name;
NTSTATUS status;
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, NULL, FILE_OPEN )))
{
ULONG attributes;
struct stat st;
......@@ -3787,7 +3817,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
char *unix_name;
NTSTATUS status;
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, NULL, FILE_OPEN )))
{
ULONG attributes;
struct stat st;
......@@ -4336,7 +4366,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
if (len >= sizeof(FILE_RENAME_INFORMATION))
{
FILE_RENAME_INFORMATION *info = ptr;
UNICODE_STRING name_str;
UNICODE_STRING name_str, nt_name = { 0 };
OBJECT_ATTRIBUTES attr;
char *unix_name;
......@@ -4349,7 +4379,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
attr.RootDirectory = info->RootDirectory;
attr.Attributes = OBJ_CASE_INSENSITIVE;
io->u.Status = nt_to_unix_file_name_attr( &attr, &unix_name, FILE_OPEN_IF );
io->u.Status = nt_to_unix_file_name_attr( &attr, &unix_name, &nt_name, FILE_OPEN_IF );
if (io->u.Status != STATUS_SUCCESS && io->u.Status != STATUS_NO_SUCH_FILE)
break;
......@@ -4365,6 +4395,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
SERVER_END_REQ;
free( unix_name );
free( nt_name.Buffer );
}
else io->u.Status = STATUS_INVALID_PARAMETER_3;
break;
......@@ -4373,7 +4404,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
if (len >= sizeof(FILE_LINK_INFORMATION))
{
FILE_LINK_INFORMATION *info = ptr;
UNICODE_STRING name_str;
UNICODE_STRING name_str, nt_name = { 0 };
OBJECT_ATTRIBUTES attr;
char *unix_name;
......@@ -4386,7 +4417,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
attr.RootDirectory = info->RootDirectory;
attr.Attributes = OBJ_CASE_INSENSITIVE;
io->u.Status = nt_to_unix_file_name_attr( &attr, &unix_name, FILE_OPEN_IF );
io->u.Status = nt_to_unix_file_name_attr( &attr, &unix_name, &nt_name, FILE_OPEN_IF );
if (io->u.Status != STATUS_SUCCESS && io->u.Status != STATUS_NO_SUCH_FILE)
break;
......@@ -4402,6 +4433,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
SERVER_END_REQ;
free( unix_name );
free( nt_name.Buffer );
}
else io->u.Status = STATUS_INVALID_PARAMETER_3;
break;
......
......@@ -1101,7 +1101,7 @@ static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module )
NTSTATUS status;
DWORD len;
if (nt_to_unix_file_name( nt_name, &unix_name, FILE_OPEN )) return STATUS_DLL_NOT_FOUND;
if (nt_to_unix_file_name( nt_name, &unix_name, NULL, FILE_OPEN )) return STATUS_DLL_NOT_FOUND;
/* remove .so extension from Windows name */
len = nt_name->Length / sizeof(WCHAR);
......
......@@ -723,7 +723,7 @@ static NTSTATUS fork_and_exec( UNICODE_STRING *path, int unixdir,
char *unix_name;
NTSTATUS status;
status = nt_to_unix_file_name( path, &unix_name, FILE_OPEN );
status = nt_to_unix_file_name( path, &unix_name, NULL, FILE_OPEN );
if (status) return status;
#ifdef HAVE_PIPE2
......
......@@ -229,7 +229,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 UNICODE_STRING *nameW, char **name_ret, UINT disposition ) DECLSPEC_HIDDEN;
extern NTSTATUS nt_to_unix_file_name( const UNICODE_STRING *nameW, char **unix_name_ret,
UNICODE_STRING *nt_name, UINT disposition ) DECLSPEC_HIDDEN;
extern NTSTATUS unix_to_nt_file_name( const char *name, WCHAR **nt ) DECLSPEC_HIDDEN;
extern NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MASK access,
OBJECT_ATTRIBUTES *attr, ULONG attributes, ULONG sharing, ULONG disposition,
......
......@@ -685,21 +685,14 @@ DECL_HANDLER(create_file)
{
struct object *file;
struct fd *root_fd = NULL;
struct unicode_str unicode_name;
struct unicode_str nt_name;
const struct security_descriptor *sd;
const struct object_attributes *objattr = get_req_object_attributes( &sd, &unicode_name, NULL );
const struct object_attributes *objattr = get_req_object_attributes( &sd, &nt_name, NULL );
const char *name;
data_size_t name_len;
if (!objattr) return;
/* name is transferred in the unix codepage outside of the objattr structure */
if (unicode_name.len)
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
if (objattr->rootdir)
{
struct dir *root;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment