Alexandre Julliard : ntdll: Add support for the FILE_OPEN_BY_FILE_ID flag in NtCreateFile.

Alexandre Julliard julliard at winehq.org
Thu Dec 3 10:29:50 CST 2009


Module: wine
Branch: master
Commit: 9c789f40250458bccf9f70b23c54089c24c799a1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9c789f40250458bccf9f70b23c54089c24c799a1

Author: Alexandre Julliard <julliard at 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 );
 




More information about the wine-cvs mailing list