From adecc0a88655710360130ba8e2c7f61d855e9d8b Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
Date: Fri, 17 Apr 2015 18:39:59 +0800
Subject: server: Do not allow to set disposition on file which has a file
 mapping.

---
 dlls/ntdll/tests/file.c |  2 --
 server/fd.c             | 12 ++++++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 740e44a..99aaa37 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -2279,7 +2279,6 @@ static void test_file_disposition_information(void)
     ok( mapping != NULL, "failed to create file mapping\n");
     fdi.DoDeleteFile = TRUE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     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;
@@ -2313,7 +2312,6 @@ static void test_file_disposition_information(void)
     CloseHandle( mapping );
     fdi.DoDeleteFile = TRUE;
     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
-    todo_wine
     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;
diff --git a/server/fd.c b/server/fd.c
index 5130b44..04891e7 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2218,6 +2218,7 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
 static void set_fd_disposition( struct fd *fd, int unlink )
 {
     struct stat st;
+    struct list *ptr;
 
     if (!fd->inode)
     {
@@ -2251,6 +2252,17 @@ static void set_fd_disposition( struct fd *fd, int unlink )
         return;
     }
 
+    /* can't unlink files which are mapped to memory */
+    LIST_FOR_EACH( ptr, &fd->inode->open )
+    {
+        struct fd *fd_ptr = LIST_ENTRY( ptr, struct fd, inode_entry );
+        if (fd_ptr != fd && (fd_ptr->access & FILE_MAPPING_ACCESS))
+        {
+            set_error( STATUS_CANNOT_DELETE );
+            return;
+        }
+    }
+
     fd->closed->unlink = unlink || (fd->options & FILE_DELETE_ON_CLOSE);
 }
 
-- 
2.5.0

