server: Add support for setting file disposition information.
Based on a patch by Dmitry Timoshkov.
This commit is contained in:
parent
9124cb28f9
commit
0fabfe7d6b
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
44
server/fd.c
44
server/fd.c
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue