Module: wine Branch: master Commit: 9c789f40250458bccf9f70b23c54089c24c799a1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=9c789f40250458bccf9f70b23c...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Dec 2 17:35:43 2009 +0100
ntdll: Add support for the FILE_OPEN_BY_FILE_ID flag in NtCreateFile.
---
dlls/ntdll/directory.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/file.c | 7 +++- dlls/ntdll/ntdll_misc.h | 1 + 3 files changed, 87 insertions(+), 1 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index b01519e..82953c2 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -2218,6 +2218,86 @@ static inline int get_dos_prefix_len( const UNICODE_STRING *name )
/****************************************************************************** + * file_id_to_unix_file_name + * + * Lookup a file from its file id instead of its name. + */ +NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *unix_name_ret ) +{ + enum server_fd_type type; + int old_cwd, root_fd, needs_close; + char *unix_name; + int unix_len; + NTSTATUS status; + ULONGLONG file_id; + struct stat st, root_st; + DIR *dir; + struct dirent *de; + + 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) ); + + unix_len = MAX_DIR_ENTRY_LEN + 1; + if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len ))) + return STATUS_NO_MEMORY; + unix_name[0] = 0; + + if (!(status = server_get_unix_fd( attr->RootDirectory, FILE_READ_DATA, &root_fd, + &needs_close, &type, NULL ))) + { + if (type != FD_TYPE_DIR) + { + if (needs_close) close( root_fd ); + status = STATUS_OBJECT_TYPE_MISMATCH; + } + else + { + fstat( root_fd, &root_st ); + RtlEnterCriticalSection( &dir_section ); + if ((old_cwd = open( ".", O_RDONLY )) != -1 && fchdir( root_fd ) != -1) + { + if (!(dir = opendir( "." ))) status = FILE_GetNtStatus(); + else + { + while ((de = readdir( dir ))) + { + if (stat( de->d_name, &st ) == -1) continue; + if (st.st_dev == root_st.st_dev && st.st_ino == file_id) + { + strcpy( unix_name, de->d_name ); + break; + } + } + closedir( dir ); + if (!unix_name[0]) status = STATUS_OBJECT_NAME_NOT_FOUND; + } + if (fchdir( old_cwd ) == -1) chdir( "/" ); + } + else status = FILE_GetNtStatus(); + RtlLeaveCriticalSection( &dir_section ); + if (old_cwd != -1) close( old_cwd ); + if (needs_close) close( root_fd ); + } + } + + if (status == STATUS_SUCCESS) + { + TRACE( "%s -> %s\n", wine_dbgstr_longlong(file_id), debugstr_a(unix_name) ); + unix_name_ret->Buffer = unix_name; + unix_name_ret->Length = strlen(unix_name); + unix_name_ret->MaximumLength = unix_len; + } + else + { + TRACE( "%s not found in %s\n", wine_dbgstr_longlong(file_id), unix_name ); + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); + } + return status; +} + + +/****************************************************************************** * lookup_unix_name * * Helper for nt_to_unix_file_name diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 56c26c2..1af4116 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -115,7 +115,12 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
if (alloc_size) FIXME( "alloc_size not supported\n" );
- if ((io->u.Status = nt_to_unix_file_name_attr( attr, &unix_name, disposition )) == STATUS_BAD_DEVICE_TYPE) + if (options & FILE_OPEN_BY_FILE_ID) + io->u.Status = file_id_to_unix_file_name( attr, &unix_name ); + else + io->u.Status = nt_to_unix_file_name_attr( attr, &unix_name, disposition ); + + if (io->u.Status == STATUS_BAD_DEVICE_TYPE) { SERVER_START_REQ( open_file_object ) { diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index b1e976c..e1e67ea 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -147,6 +147,7 @@ extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name ); extern NTSTATUS DIR_unmount_device( HANDLE handle ); extern NTSTATUS DIR_get_unix_cwd( char **cwd ); extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ); +extern NTSTATUS file_id_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *unix_name_ret ); extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *unix_name_ret, UINT disposition );