Commit 4bb759e8 authored by Alexandre Julliard's avatar Alexandre Julliard

Properly set IO_STATUS_BLOCK.Information in NtCreateFile.

parent 69f2e04f
......@@ -650,7 +650,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event,
* 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,
int is_last, int check_last, int check_case )
int check_case )
{
WCHAR buffer[MAX_DIR_ENTRY_LEN];
UNICODE_STRING str;
......@@ -771,19 +771,8 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
goto not_found; /* avoid warning */
not_found:
if (is_last && !check_last) /* return the name anyway */
{
int used_default;
ret = ntdll_wcstoumbs( 0, name, length, unix_name + pos,
MAX_DIR_ENTRY_LEN, NULL, &used_default );
if (ret > 0 && !used_default)
{
unix_name[pos + ret] = 0;
return STATUS_SUCCESS;
}
}
unix_name[pos - 1] = 0;
return is_last ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_OBJECT_PATH_NOT_FOUND;
return STATUS_OBJECT_PATH_NOT_FOUND;
}
......@@ -809,6 +798,10 @@ static inline int get_dos_prefix_len( const UNICODE_STRING *name )
* DIR_nt_to_unix
*
* Convert a file name from NT namespace to Unix namespace.
*
* If check_last is 0, the last path element doesn't have to exist;
* in that case STATUS_OBJECT_NAME_NOT_FOUND is returned, but the
* unix name is still filled in properly.
*/
NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret,
int check_last, int check_case )
......@@ -816,7 +809,7 @@ NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret
static const WCHAR uncW[] = {'U','N','C','\\'};
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 };
NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
NTSTATUS status = STATUS_SUCCESS;
const char *config_dir = wine_get_config_dir();
const WCHAR *name, *p;
struct stat st;
......@@ -908,6 +901,7 @@ NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret
while (end < name + name_len && !IS_SEPARATOR(*end)) end++;
next = end;
while (next < name + name_len && IS_SEPARATOR(*next)) next++;
name_len -= next - name;
/* grow the buffer if needed */
......@@ -923,8 +917,25 @@ NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret
unix_name = new_name;
}
status = find_file_in_dir( unix_name, pos, name, end - name,
(next - name == name_len), check_last, check_case );
status = find_file_in_dir( unix_name, pos, name, end - name, check_case );
/* if this is the last element, not finding it is not necessarily fatal */
if (!name_len && status == STATUS_OBJECT_PATH_NOT_FOUND)
{
status = STATUS_OBJECT_NAME_NOT_FOUND;
if (!check_last)
{
ret = ntdll_wcstoumbs( 0, name, end - name, unix_name + pos + 1,
MAX_DIR_ENTRY_LEN, NULL, &used_default );
if (ret > 0 && !used_default)
{
unix_name[pos] = '/';
unix_name[pos + 1 + ret] = 0;
break;
}
}
}
if (status != STATUS_SUCCESS)
{
/* couldn't find it at all, fail */
......@@ -934,7 +945,6 @@ NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret
}
pos += strlen( unix_name + pos );
name_len -= next - name;
name = next;
}
......@@ -946,7 +956,7 @@ done:
unix_name_ret->Buffer = unix_name;
unix_name_ret->Length = strlen(unix_name);
unix_name_ret->MaximumLength = unix_len;
return STATUS_SUCCESS;
return status;
}
......@@ -965,7 +975,7 @@ char *wine_get_unix_file_name( LPCWSTR dosW )
if (!RtlDosPathNameToNtPathName_U( dosW, &nt_name, NULL, NULL )) return NULL;
status = DIR_nt_to_unix( &nt_name, &unix_name, FALSE, FALSE );
RtlFreeUnicodeString( &nt_name );
if (status) return NULL;
if (status && status != STATUS_OBJECT_NAME_NOT_FOUND) return NULL;
return unix_name.Buffer;
}
......
......@@ -131,6 +131,7 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
ULONG options, PVOID ea_buffer, ULONG ea_length )
{
ANSI_STRING unix_name;
int check_last, created = FALSE;
TRACE("handle=%p access=%08lx name=%s objattr=%08lx root=%p sec=%p io=%p alloc_size=%p\n"
"attr=%08lx sharing=%08lx disp=%ld options=%08lx ea=%p.0x%08lx\n",
......@@ -145,9 +146,18 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
}
if (alloc_size) FIXME( "alloc_size not supported\n" );
if (!(io->u.Status = DIR_nt_to_unix( attr->ObjectName, &unix_name,
(disposition == FILE_OPEN || disposition == FILE_OVERWRITE),
!(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
check_last = (disposition == FILE_OPEN || disposition == FILE_OVERWRITE);
io->u.Status = DIR_nt_to_unix( attr->ObjectName, &unix_name, check_last,
!(attr->Attributes & OBJ_CASE_INSENSITIVE) );
if (!check_last && io->u.Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
created = TRUE;
io->u.Status = STATUS_SUCCESS;
}
if (io->u.Status == STATUS_SUCCESS)
{
SERVER_START_REQ( create_file )
{
......@@ -165,6 +175,29 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
RtlFreeAnsiString( &unix_name );
}
else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), io->u.Status );
if (io->u.Status == STATUS_SUCCESS)
{
if (created) io->Information = FILE_CREATED;
else switch(disposition)
{
case FILE_SUPERSEDE:
io->Information = FILE_SUPERSEDED;
break;
case FILE_CREATE:
io->Information = FILE_CREATED;
break;
case FILE_OPEN:
case FILE_OPEN_IF:
io->Information = FILE_OPENED;
break;
case FILE_OVERWRITE:
case FILE_OVERWRITE_IF:
io->Information = FILE_OVERWRITTEN;
break;
}
}
return io->u.Status;
}
......
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