[2/3] server: Add support for setting file disposition information.

Dmitry Timoshkov dmitry at baikal.ru
Mon Feb 10 03:46:59 CST 2014


---
 dlls/ntdll/file.c       | 16 ++++++++++++++++
 dlls/ntdll/tests/file.c | 12 ++----------
 server/fd.c             | 30 ++++++++++++++++++++++++++++++
 server/file.c           | 23 +++++++++++++++++++++++
 server/file.h           |  1 +
 server/protocol.def     |  6 ++++++
 6 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index d2efcc1..5d59470 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -2383,6 +2383,22 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
         else io->u.Status = STATUS_INVALID_PARAMETER_3;
         break;
 
+    case FileDispositionInformation:
+        if (len >= sizeof(FILE_DISPOSITION_INFORMATION))
+        {
+            FILE_DISPOSITION_INFORMATION *info = ptr;
+
+            SERVER_START_REQ( set_file_info )
+            {
+                req->handle   = wine_server_obj_handle( handle );
+                req->unlink   = info->DoDeleteFile;
+                io->u.Status = wine_server_call( req );
+            }
+            SERVER_END_REQ;
+        } else
+            io->u.Status = STATUS_INVALID_PARAMETER_3;
+        break;
+
     default:
         FIXME("Unsupported class (%d)\n", class);
         io->u.Status = STATUS_NOT_IMPLEMENTED;
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 695f034..986c25a 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1369,7 +1369,6 @@ static void test_file_disposition_information(void)
     ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
     fdi.DoDeleteFile = TRUE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1382,11 +1381,9 @@ static void test_file_disposition_information(void)
     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
     fdi.DoDeleteFile = TRUE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
-    todo_wine
     ok( fileDeleted, "File should have been deleted\n" );
     DeleteFileA( buffer );
 
@@ -1400,6 +1397,7 @@ static void test_file_disposition_information(void)
     ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    todo_wine
     ok( !fileDeleted, "File shouldn't have been deleted\n" );
     SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
     DeleteFileA( buffer );
@@ -1410,11 +1408,9 @@ static void test_file_disposition_information(void)
     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
     fdi.DoDeleteFile = TRUE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
     fdi.DoDeleteFile = FALSE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1427,7 +1423,6 @@ static void test_file_disposition_information(void)
     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
     fdi.DoDeleteFile = FALSE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1442,7 +1437,6 @@ static void test_file_disposition_information(void)
     CloseHandle( handle );
     fdi.DoDeleteFile = FALSE;
     res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
     CloseHandle( handle2 );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1457,11 +1451,9 @@ static void test_file_disposition_information(void)
     ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
     fdi.DoDeleteFile = TRUE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
-    todo_wine
     ok( fileDeleted, "Directory should have been deleted\n" );
     RemoveDirectoryA( buffer );
 
@@ -1474,7 +1466,6 @@ static void test_file_disposition_information(void)
     RemoveDirectoryA( buffer );
     fdi.DoDeleteFile = FALSE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1499,6 +1490,7 @@ static void test_file_disposition_information(void)
     buffer[dirpos] = '\0';
     CloseHandle( handle );
     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+    todo_wine
     ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
     RemoveDirectoryA( buffer );
 }
diff --git a/server/fd.c b/server/fd.c
index 9eadcf5..3d56e83 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1916,6 +1916,36 @@ unsigned int get_fd_options( struct fd *fd )
     return fd->options;
 }
 
+/* set disposition for the fd */
+void set_fd_disposition( struct fd *fd, int unlink )
+{
+    struct stat st;
+
+    if (fd->unix_fd == -1)
+    {
+        set_error( STATUS_INVALID_HANDLE );
+        return;
+    }
+
+    if (fstat( fd->unix_fd, &st ) == -1)
+    {
+        file_set_error();
+        return;
+    }
+
+    if (unlink && !S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
+    {
+        /* can't unlink special files */
+        set_error( STATUS_INVALID_PARAMETER );
+        return;
+    }
+
+    if (unlink)
+        fd->closed->unlink = 1;
+    else if (!(fd->options & FILE_DELETE_ON_CLOSE))
+        fd->closed->unlink = 0;
+}
+
 /* retrieve the unix fd for an object */
 int get_unix_fd( struct fd *fd )
 {
diff --git a/server/file.c b/server/file.c
index cceb8ad..0a7da00 100644
--- a/server/file.c
+++ b/server/file.c
@@ -728,3 +728,26 @@ DECL_HANDLER(unlock_file)
         release_object( file );
     }
 }
+
+/* set file information */
+DECL_HANDLER(set_file_info)
+{
+    struct file *file;
+
+    if ((file = get_file_obj( current->process, req->handle, DELETE )))
+    {
+        set_fd_disposition( file->fd, req->unlink );
+        release_object( file );
+        return;
+    }
+
+    if (get_error() == STATUS_OBJECT_TYPE_MISMATCH)
+    {
+        clear_error();
+        if ((file = (struct file *)get_dir_obj( current->process, req->handle, DELETE )))
+        {
+            set_fd_disposition( file->fd, req->unlink );
+            release_object( file );
+        }
+    }
+}
diff --git a/server/file.h b/server/file.h
index 493d30b..d689d29 100644
--- a/server/file.h
+++ b/server/file.h
@@ -65,6 +65,7 @@ extern struct fd *get_fd_object_for_mapping( struct fd *fd, unsigned int access,
 extern void *get_fd_user( struct fd *fd );
 extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
 extern unsigned int get_fd_options( struct fd *fd );
+extern void set_fd_disposition( struct fd *fd, int unlink );
 extern int get_unix_fd( struct fd *fd );
 extern int is_same_file_fd( struct fd *fd1, struct fd *fd2 );
 extern int is_fd_removable( struct fd *fd );
diff --git a/server/protocol.def b/server/protocol.def
index fec5e75..5b0c1cd 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1190,6 +1190,12 @@ enum server_fd_type
 @END
 
 
+/* Set file information */
+ at REQ(set_file_info)
+    obj_handle_t handle;        /* handle to the file */
+    int          unlink;        /* whether to unlink file on close */
+ at END
+
 /* Create a socket */
 @REQ(create_socket)
     unsigned int access;        /* wanted access rights */
-- 
1.8.5.3




More information about the wine-patches mailing list