[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