server: Add support for setting file disposition information.

Based on a patch by Dmitry Timoshkov.
This commit is contained in:
Sebastian Lackner 2015-08-19 11:18:01 +02:00 committed by Alexandre Julliard
parent 9124cb28f9
commit 0fabfe7d6b
8 changed files with 101 additions and 13 deletions

View File

@ -4645,7 +4645,6 @@ todo_wine
dispinfo.DeleteFile = TRUE;
ret = pSetFileInformationByHandle(file, FileDispositionInfo, &dispinfo, sizeof(dispinfo));
todo_wine
ok(ret, "setting FileDispositionInfo failed, error %d\n", GetLastError());
CloseHandle(file);

View File

@ -2765,6 +2765,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_fd_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;

View File

@ -1473,7 +1473,6 @@ static void test_file_disposition_information(void)
ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %x\n", res );
fdi2 = 0x100;
res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@ -1488,7 +1487,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;
@ -1501,11 +1499,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 );
@ -1519,6 +1515,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 );
@ -1529,11 +1526,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;
@ -1546,7 +1541,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;
@ -1561,7 +1555,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;
@ -1576,11 +1569,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 );
@ -1593,7 +1584,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;
@ -1618,6 +1608,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 );
}

View File

@ -5080,6 +5080,20 @@ struct add_fd_completion_reply
struct set_fd_info_request
{
struct request_header __header;
obj_handle_t handle;
int unlink;
char __pad_20[4];
};
struct set_fd_info_reply
{
struct reply_header __header;
};
struct get_window_layered_info_request
{
struct request_header __header;
@ -5552,6 +5566,7 @@ enum request
REQ_query_completion,
REQ_set_completion_info,
REQ_add_fd_completion,
REQ_set_fd_info,
REQ_get_window_layered_info,
REQ_set_window_layered_info,
REQ_alloc_user_handle,
@ -5826,6 +5841,7 @@ union generic_request
struct query_completion_request query_completion_request;
struct set_completion_info_request set_completion_info_request;
struct add_fd_completion_request add_fd_completion_request;
struct set_fd_info_request set_fd_info_request;
struct get_window_layered_info_request get_window_layered_info_request;
struct set_window_layered_info_request set_window_layered_info_request;
struct alloc_user_handle_request alloc_user_handle_request;
@ -6098,6 +6114,7 @@ union generic_reply
struct query_completion_reply query_completion_reply;
struct set_completion_info_reply set_completion_info_reply;
struct add_fd_completion_reply add_fd_completion_reply;
struct set_fd_info_reply set_fd_info_reply;
struct get_window_layered_info_reply get_window_layered_info_reply;
struct set_window_layered_info_reply set_window_layered_info_reply;
struct alloc_user_handle_reply alloc_user_handle_reply;
@ -6114,6 +6131,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 484
#define SERVER_PROTOCOL_VERSION 485
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -2214,6 +2214,39 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
return fd;
}
/* set disposition for the fd */
static void set_fd_disposition( struct fd *fd, int unlink )
{
struct stat st;
if (!fd->inode)
{
set_error( STATUS_OBJECT_TYPE_MISMATCH );
return;
}
if (fd->unix_fd == -1)
{
set_error( fd->no_fd_status );
return;
}
if (fstat( fd->unix_fd, &st ) == -1)
{
file_set_error();
return;
}
/* can't unlink special files */
if (unlink && !S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
fd->closed->unlink = unlink || (fd->options & FILE_DELETE_ON_CLOSE);
}
struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key )
{
*p_key = fd->comp_key;
@ -2409,3 +2442,14 @@ DECL_HANDLER(add_fd_completion)
release_object( fd );
}
}
/* set fd information */
DECL_HANDLER(set_fd_info)
{
struct fd *fd = get_handle_fd_obj( current->process, req->handle, DELETE );
if (fd)
{
set_fd_disposition( fd, req->unlink );
release_object( fd );
}
}

View File

@ -3525,6 +3525,13 @@ enum coords_relative
@END
/* set fd information */
@REQ(set_fd_info)
obj_handle_t handle; /* handle to a file or directory */
int unlink; /* whether to unlink file on close */
@END
/* Retrieve layered info for a window */
@REQ(get_window_layered_info)
user_handle_t handle; /* handle to the window */

View File

@ -359,6 +359,7 @@ DECL_HANDLER(remove_completion);
DECL_HANDLER(query_completion);
DECL_HANDLER(set_completion_info);
DECL_HANDLER(add_fd_completion);
DECL_HANDLER(set_fd_info);
DECL_HANDLER(get_window_layered_info);
DECL_HANDLER(set_window_layered_info);
DECL_HANDLER(alloc_user_handle);
@ -632,6 +633,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_query_completion,
(req_handler)req_set_completion_info,
(req_handler)req_add_fd_completion,
(req_handler)req_set_fd_info,
(req_handler)req_get_window_layered_info,
(req_handler)req_set_window_layered_info,
(req_handler)req_alloc_user_handle,
@ -2221,6 +2223,9 @@ C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, cvalue) == 16 );
C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, information) == 24 );
C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, status) == 32 );
C_ASSERT( sizeof(struct add_fd_completion_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct set_fd_info_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_fd_info_request, unlink) == 16 );
C_ASSERT( sizeof(struct set_fd_info_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_window_layered_info_request, handle) == 12 );
C_ASSERT( sizeof(struct get_window_layered_info_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_window_layered_info_reply, color_key) == 8 );

View File

@ -4136,6 +4136,12 @@ static void dump_add_fd_completion_request( const struct add_fd_completion_reque
fprintf( stderr, ", status=%08x", req->status );
}
static void dump_set_fd_info_request( const struct set_fd_info_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
fprintf( stderr, ", unlink=%d", req->unlink );
}
static void dump_get_window_layered_info_request( const struct get_window_layered_info_request *req )
{
fprintf( stderr, " handle=%08x", req->handle );
@ -4509,6 +4515,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_query_completion_request,
(dump_func)dump_set_completion_info_request,
(dump_func)dump_add_fd_completion_request,
(dump_func)dump_set_fd_info_request,
(dump_func)dump_get_window_layered_info_request,
(dump_func)dump_set_window_layered_info_request,
(dump_func)dump_alloc_user_handle_request,
@ -4779,6 +4786,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_query_completion_reply,
NULL,
NULL,
NULL,
(dump_func)dump_get_window_layered_info_reply,
NULL,
(dump_func)dump_alloc_user_handle_reply,
@ -5049,6 +5057,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"query_completion",
"set_completion_info",
"add_fd_completion",
"set_fd_info",
"get_window_layered_info",
"set_window_layered_info",
"alloc_user_handle",