From f41db2526967d4e662fdcf8f602701af6e4e19f8 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
Date: Fri, 17 Apr 2015 18:39:59 +0800
Subject: [PATCH] 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 4f6c0d7f847..776de6d0cc8 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -3205,7 +3205,6 @@ todo_wine
     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;
@@ -3239,7 +3238,6 @@ todo_wine
     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 0a0683e5bce..2cbbdad6e62 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2487,6 +2487,7 @@ static int is_dir_empty( int fd )
 static void set_fd_disposition( struct fd *fd, int unlink )
 {
     struct stat st;
+    struct list *ptr;
 
     if (!fd->inode)
     {
@@ -2534,6 +2535,17 @@ static void set_fd_disposition( struct fd *fd, int unlink )
         }
     }
 
+    /* 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 ? 1 : 0;
     if (fd->options & FILE_DELETE_ON_CLOSE)
         fd->closed->unlink = -1;
-- 
2.26.2

