mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Added patch to support setting file disposition information.
This commit is contained in:
parent
0ee71b2abe
commit
18b484d778
@ -35,6 +35,7 @@ Wine-Compholio contains fixes for the following Wine bugs:
|
||||
* Support for AllocateAndGetTcpExTableFromStack ([Wine Bug #34372](http://bugs.winehq.org/show_bug.cgi?id=34372 "Add missing function AllocateAndGetTcpExTableFromStack() to iphlpapi.dll"))
|
||||
* Support for GetSystemTimes ([Wine Bug #19813](http://bugs.winehq.org/show_bug.cgi?id=19813 "Voddler needs GetSystemTimes to run"))
|
||||
* Support for Junction Points ([Wine Bug #12401](http://bugs.winehq.org/show_bug.cgi?id=12401 "Support junction points, i.e. DeviceIoCtl(FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)"))
|
||||
* Support for NtSetInformationFile class FileDispositionInformation ([Wine Bug #30397](http://bugs.winehq.org/show_bug.cgi?id=30397 "Multiple applications need support for NtSetInformationFile class FileDispositionInformation (Cygwin installer, Stylizer 5.x Visual CSS editor, Spoon Studio 2011 (ex Xenocode) application sandboxing scheme)"))
|
||||
* Support for PulseAudio backend for audio ([Wine Bug #10495](http://bugs.winehq.org/show_bug.cgi?id=10495 "Wine should support PulseAudio"))
|
||||
* Support for TOOLTIPS_GetTipText edge cases ([Wine Bug #30648](http://bugs.winehq.org/show_bug.cgi?id=30648 "SEGA Genesis / Mega Drive Classic Collection (Steam) crashes on startup"))
|
||||
* Support for TransmitFile ([Wine Bug #5048](http://bugs.winehq.org/show_bug.cgi?id=5048 "Multiple applications and games need support for ws2_32 SIO_GET_EXTENSION_FUNCTION_POINTER TransmitFile (WSAID_TRANSMITFILE)"))
|
||||
|
3
debian/changelog
vendored
3
debian/changelog
vendored
@ -8,6 +8,7 @@ wine-compholio (1.7.24) UNRELEASED; urgency=low
|
||||
* Added patch to allow special characters in pipe names.
|
||||
* Added patch with stubs for [Get|Set]SystemFileCacheSize.
|
||||
* Added patch to implement AllocateAndGetTcpExTableFromStack.
|
||||
* Added patch to support setting file disposition information.
|
||||
* Added patch to fix ConnectNamedPort return value in overlapped mode.
|
||||
* Added patch to store IOCS data in a property instead of GWLP_USERDATA.
|
||||
* Added patch to return empty D3D hardware flags for HEL device enumeration.
|
||||
@ -21,7 +22,7 @@ wine-compholio (1.7.24) UNRELEASED; urgency=low
|
||||
* Removed patch to create Vista directories (accepted upstream).
|
||||
* Removed strmbase/quartz locking fix patches (accepted upstream).
|
||||
* Removed windowscodecs/PropertyBag patch (accepted upstream).
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Thu, 07 Aug 2014 17:31:56 -0600
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 08 Aug 2014 14:39:15 -0600
|
||||
|
||||
wine-compholio (1.7.23) unstable; urgency=low
|
||||
* Rewrite of patch system to simplify maintaining large patchsets.
|
||||
|
@ -20,6 +20,7 @@ PATCHLIST := Miscellaneous.ok \
|
||||
loader-Cmdline_Diagnostics.ok \
|
||||
ntdll-Dynamic_DST.ok \
|
||||
ntdll-FD_Cache.ok \
|
||||
ntdll-FileDispositionInformation.ok \
|
||||
ntdll-Junction_Points.ok \
|
||||
ntdll-Pipe_SpecialCharacters.ok \
|
||||
ntdll-loader_EntryPoint.ok \
|
||||
@ -348,6 +349,27 @@ ntdll-FD_Cache.ok:
|
||||
echo '+ { "ntdll-FD_Cache", "Sebastian Lackner", "Use lockfree implementation for get_cached_fd. [rev 4]" },'; \
|
||||
) > ntdll-FD_Cache.ok
|
||||
|
||||
# Patchset ntdll-FileDispositionInformation
|
||||
# |
|
||||
# | Included patches:
|
||||
# | * Add support for setting file disposition information. [by Dmitry Timoshkov / Erich E. Hoover]
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#30397] Multiple applications need support for NtSetInformationFile class FileDispositionInformation (Cygwin installer,
|
||||
# | Stylizer 5.x Visual CSS editor, Spoon Studio 2011 (ex Xenocode) application sandboxing scheme)
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/file.c, dlls/ntdll/tests/file.c, server/fd.c, server/file.c, server/file.h, server/protocol.def
|
||||
# |
|
||||
.INTERMEDIATE: ntdll-FileDispositionInformation.ok
|
||||
ntdll-FileDispositionInformation.ok:
|
||||
$(PATCH) < ntdll-FileDispositionInformation/0001-server-Keep-a-pointer-to-parent-s-fd-unix_name-in-th.patch
|
||||
$(PATCH) < ntdll-FileDispositionInformation/0002-server-Add-support-for-setting-file-disposition-info.patch
|
||||
$(PATCH) < ntdll-FileDispositionInformation/0003-server-Do-not-permit-FileDispositionInformation-to-d.patch
|
||||
@( \
|
||||
echo '+ { "ntdll-FileDispositionInformation", "Dmitry Timoshkov / Erich E. Hoover", "Add support for setting file disposition information." },'; \
|
||||
) > ntdll-FileDispositionInformation.ok
|
||||
|
||||
# Patchset ntdll-Junction_Points
|
||||
# |
|
||||
# | Included patches:
|
||||
|
@ -0,0 +1,168 @@
|
||||
From 35cc6b5ed224e27ef833bb84cea092bb65b8ab12 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Thu, 7 Aug 2014 18:31:33 -0600
|
||||
Subject: server: Keep a pointer to parent's fd unix_name in the closed_fd
|
||||
structure.
|
||||
|
||||
---
|
||||
server/fd.c | 38 +++++++++++++++++++++-----------------
|
||||
1 file changed, 21 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index e3b722c..b022a3c 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -164,7 +164,8 @@ struct closed_fd
|
||||
{
|
||||
struct list entry; /* entry in inode closed list */
|
||||
int unix_fd; /* the unix file descriptor */
|
||||
- char unlink[1]; /* name to unlink on close (if any) */
|
||||
+ int unlink; /* whether to unlink on close */
|
||||
+ char *unix_name; /* name to unlink on close, points to parent fd unix_name */
|
||||
};
|
||||
|
||||
struct fd
|
||||
@@ -1016,9 +1017,10 @@ static void inode_close_pending( struct inode *inode, int keep_unlinks )
|
||||
close( fd->unix_fd );
|
||||
fd->unix_fd = -1;
|
||||
}
|
||||
- if (!keep_unlinks || !fd->unlink[0]) /* get rid of it unless there's an unlink pending on that file */
|
||||
+ if (!keep_unlinks || !fd->unlink) /* get rid of it unless there's an unlink pending on that file */
|
||||
{
|
||||
list_remove( ptr );
|
||||
+ free( fd->unix_name );
|
||||
free( fd );
|
||||
}
|
||||
ptr = next;
|
||||
@@ -1048,16 +1050,17 @@ static void inode_destroy( struct object *obj )
|
||||
struct closed_fd *fd = LIST_ENTRY( ptr, struct closed_fd, entry );
|
||||
list_remove( ptr );
|
||||
if (fd->unix_fd != -1) close( fd->unix_fd );
|
||||
- if (fd->unlink[0])
|
||||
+ if (fd->unlink)
|
||||
{
|
||||
/* make sure it is still the same file */
|
||||
struct stat st;
|
||||
- if (!stat( fd->unlink, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino)
|
||||
+ if (!stat( fd->unix_name, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino)
|
||||
{
|
||||
- if (S_ISDIR(st.st_mode)) rmdir( fd->unlink );
|
||||
- else unlink( fd->unlink );
|
||||
+ if (S_ISDIR(st.st_mode)) rmdir( fd->unix_name );
|
||||
+ else unlink( fd->unix_name );
|
||||
}
|
||||
}
|
||||
+ free( fd->unix_name );
|
||||
free( fd );
|
||||
}
|
||||
release_object( inode->device );
|
||||
@@ -1103,7 +1106,7 @@ static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd )
|
||||
{
|
||||
list_add_head( &inode->closed, &fd->entry );
|
||||
}
|
||||
- else if (fd->unlink[0]) /* close the fd but keep the structure around for unlink */
|
||||
+ else if (fd->unlink) /* close the fd but keep the structure around for unlink */
|
||||
{
|
||||
if (fd->unix_fd != -1) close( fd->unix_fd );
|
||||
fd->unix_fd = -1;
|
||||
@@ -1112,6 +1115,7 @@ static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd )
|
||||
else /* no locks on this inode and no unlink, get rid of the fd */
|
||||
{
|
||||
if (fd->unix_fd != -1) close( fd->unix_fd );
|
||||
+ free( fd->unix_name );
|
||||
free( fd );
|
||||
}
|
||||
}
|
||||
@@ -1451,7 +1455,7 @@ static void fd_dump( struct object *obj, int verbose )
|
||||
{
|
||||
struct fd *fd = (struct fd *)obj;
|
||||
fprintf( stderr, "Fd unix_fd=%d user=%p options=%08x", fd->unix_fd, fd->user, fd->options );
|
||||
- if (fd->inode) fprintf( stderr, " inode=%p unlink='%s'", fd->inode, fd->closed->unlink );
|
||||
+ if (fd->inode) fprintf( stderr, " inode=%p unlink=%d", fd->inode, fd->closed->unlink );
|
||||
fprintf( stderr, "\n" );
|
||||
}
|
||||
|
||||
@@ -1465,7 +1469,6 @@ static void fd_destroy( struct object *obj )
|
||||
|
||||
if (fd->completion) release_object( fd->completion );
|
||||
remove_fd_locks( fd );
|
||||
- free( fd->unix_name );
|
||||
list_remove( &fd->inode_entry );
|
||||
if (fd->poll_index != -1) remove_poll_user( fd, fd->poll_index );
|
||||
if (fd->inode)
|
||||
@@ -1476,6 +1479,7 @@ static void fd_destroy( struct object *obj )
|
||||
else /* no inode, close it right away */
|
||||
{
|
||||
if (fd->unix_fd != -1) close( fd->unix_fd );
|
||||
+ free( fd->unix_name );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1563,7 +1567,7 @@ static inline void unmount_fd( struct fd *fd )
|
||||
fd->unix_fd = -1;
|
||||
fd->no_fd_status = STATUS_VOLUME_DISMOUNTED;
|
||||
fd->closed->unix_fd = -1;
|
||||
- fd->closed->unlink[0] = 0;
|
||||
+ fd->closed->unlink = 0;
|
||||
|
||||
/* stop using Unix locks on this fd (existing locks have been removed by close) */
|
||||
fd->fs_locks = 0;
|
||||
@@ -1662,7 +1666,8 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
|
||||
goto failed;
|
||||
}
|
||||
closed->unix_fd = fd->unix_fd;
|
||||
- closed->unlink[0] = 0;
|
||||
+ closed->unlink = 0;
|
||||
+ closed->unix_name = fd->unix_name;
|
||||
fd->closed = closed;
|
||||
fd->inode = (struct inode *)grab_object( orig->inode );
|
||||
list_add_head( &fd->inode->open, &fd->inode_entry );
|
||||
@@ -1738,7 +1743,6 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
struct stat st;
|
||||
struct closed_fd *closed_fd;
|
||||
struct fd *fd;
|
||||
- const char *unlink_name = "";
|
||||
int root_fd = -1;
|
||||
int rw_mode;
|
||||
|
||||
@@ -1752,8 +1756,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
if (!(fd = alloc_fd_object())) return NULL;
|
||||
|
||||
fd->options = options;
|
||||
- if (options & FILE_DELETE_ON_CLOSE) unlink_name = name;
|
||||
- if (!(closed_fd = mem_alloc( sizeof(*closed_fd) + strlen(unlink_name) )))
|
||||
+ if (!(closed_fd = mem_alloc( sizeof(*closed_fd) )))
|
||||
{
|
||||
release_object( fd );
|
||||
return NULL;
|
||||
@@ -1810,7 +1813,8 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
}
|
||||
|
||||
closed_fd->unix_fd = fd->unix_fd;
|
||||
- closed_fd->unlink[0] = 0;
|
||||
+ closed_fd->unlink = 0;
|
||||
+ closed_fd->unix_name = fd->unix_name;
|
||||
fstat( fd->unix_fd, &st );
|
||||
*mode = st.st_mode;
|
||||
|
||||
@@ -1851,7 +1855,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
set_error( err );
|
||||
return NULL;
|
||||
}
|
||||
- strcpy( closed_fd->unlink, unlink_name );
|
||||
+ closed_fd->unlink = (options & FILE_DELETE_ON_CLOSE) != 0;
|
||||
if (flags & O_TRUNC)
|
||||
{
|
||||
if (S_ISDIR(st.st_mode))
|
||||
@@ -1870,7 +1874,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
set_error( STATUS_NOT_A_DIRECTORY );
|
||||
goto error;
|
||||
}
|
||||
- if (unlink_name[0]) /* we can't unlink special files */
|
||||
+ if (options & FILE_DELETE_ON_CLOSE) /* we can't unlink special files */
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
goto error;
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,233 @@
|
||||
From 723aef38c2549d8767bb185906cc3fc8d865b695 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Thu, 7 Aug 2014 20:32:19 -0600
|
||||
Subject: server: Add support for setting file disposition information.
|
||||
|
||||
---
|
||||
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 d70ed6b..1606f83 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -1371,7 +1371,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;
|
||||
@@ -1384,11 +1383,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 );
|
||||
|
||||
@@ -1402,6 +1399,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 );
|
||||
@@ -1412,11 +1410,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;
|
||||
@@ -1429,7 +1425,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;
|
||||
@@ -1444,7 +1439,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;
|
||||
@@ -1459,11 +1453,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 );
|
||||
|
||||
@@ -1476,7 +1468,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;
|
||||
@@ -1501,6 +1492,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 b022a3c..7be3f4c 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -1921,6 +1921,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 a8c1fb9..85505c8 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -1178,6 +1178,12 @@ enum server_fd_type
|
||||
@END
|
||||
|
||||
|
||||
+/* Set file information */
|
||||
+@REQ(set_file_info)
|
||||
+ obj_handle_t handle; /* handle to the file */
|
||||
+ int unlink; /* whether to unlink file on close */
|
||||
+@END
|
||||
+
|
||||
/* Create a socket */
|
||||
@REQ(create_socket)
|
||||
unsigned int access; /* wanted access rights */
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,78 @@
|
||||
From ea378bcb8a0a6113178c2d42a3e8151b7f99dfb6 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 7 Aug 2014 21:14:25 -0600
|
||||
Subject: server: Do not permit FileDispositionInformation to delete a file
|
||||
without write access.
|
||||
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 28 ++++++++++++++++++++++++++++
|
||||
server/fd.c | 7 +++++++
|
||||
2 files changed, 35 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 1606f83..05ce517 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -1391,6 +1391,20 @@ static void test_file_disposition_information(void)
|
||||
|
||||
/* cannot set disposition on readonly file */
|
||||
GetTempFileNameA( tmp_path, "dis", 0, buffer );
|
||||
+ DeleteFileA( buffer );
|
||||
+ handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
+ fdi.DoDeleteFile = TRUE;
|
||||
+ res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
+ 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;
|
||||
+ ok( !fileDeleted, "File shouldn't have been deleted\n" );
|
||||
+ SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
|
||||
+ DeleteFileA( buffer );
|
||||
+
|
||||
+ /* cannot set disposition on readonly file */
|
||||
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
fdi.DoDeleteFile = TRUE;
|
||||
@@ -1404,6 +1418,20 @@ static void test_file_disposition_information(void)
|
||||
SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
|
||||
DeleteFileA( buffer );
|
||||
|
||||
+ /* cannot set disposition on readonly file */
|
||||
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
|
||||
+ DeleteFileA( buffer );
|
||||
+ handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
+ fdi.DoDeleteFile = TRUE;
|
||||
+ res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
+ 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;
|
||||
+ ok( !fileDeleted, "File shouldn't have been deleted\n" );
|
||||
+ SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
|
||||
+ DeleteFileA( buffer );
|
||||
+
|
||||
/* can set disposition on file and then reset it */
|
||||
GetTempFileNameA( tmp_path, "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 7be3f4c..37377d1 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -1945,6 +1945,13 @@ void set_fd_disposition( struct fd *fd, int unlink )
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (unlink && !(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
||||
+ {
|
||||
+ /* can't unlink files we don't have permission to access */
|
||||
+ set_error( STATUS_CANNOT_DELETE );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (unlink)
|
||||
fd->closed->unlink = 1;
|
||||
else if (!(fd->options & FILE_DELETE_ON_CLOSE))
|
||||
--
|
||||
1.7.9.5
|
||||
|
4
patches/ntdll-FileDispositionInformation/definition
Normal file
4
patches/ntdll-FileDispositionInformation/definition
Normal file
@ -0,0 +1,4 @@
|
||||
Author: Dmitry Timoshkov / Erich E. Hoover
|
||||
Subject: Add support for setting file disposition information.
|
||||
Revision: 1
|
||||
Fixes: [30397] Support for NtSetInformationFile class FileDispositionInformation
|
Loading…
Reference in New Issue
Block a user