/* BSD-2-Clause license * * Copyright (c) 2018-2023 NST , sss . * */ #include #include #include "webrdp_module_api.h" #include "webrdp_core_api.h" #include "rdp_backend_api.h" #include "rdp_impl.h" #include "rdp_ft.h" #include "rdp_clipboard.h" static bool ft_api_handle_request( const wrdp_backend_ft_file_request *request, void *backend_internals) { rdp_internals *i = backend_internals; CLIPRDR_FILE_CONTENTS_REQUEST file_req; uint32_t chunk_len = 512000; size_t left = 0; if (i->context->ft_to_client->is_runing) { const char *msg = "rdp_module: clipboard: filetransfers: transfer " "already runing, cannot start new one"; i->core->api_utils->log_msg( (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0); return true; } memset(&file_req, 0, sizeof(CLIPRDR_FILE_CONTENTS_REQUEST)); i->context->ft_to_client->transfer_id = rand(); i->context->ft_to_client->file_size = request->req_size; i->context->ft_to_client->file_id = request->file_id; i->context->ft_to_client->transferred = request->file_offset; i->context->ft_to_client->is_runing = true; left = i->context->ft_to_client->file_size - i->context->ft_to_client->transferred; if (left < chunk_len) { chunk_len = left; } file_req.cbRequested = chunk_len; file_req.listIndex = request->file_id; file_req.streamId = i->context->ft_to_client->transfer_id; file_req.dwFlags = FILECONTENTS_RANGE; /* file_req.haveClipDataId = TRUE; file_req.clipDataId = i->context->ft_to_client->clipboard_data_id; */ /* TODO: check/change endianness */ memcpy(&(file_req.nPositionLow), &(i->context->ft_to_client->transferred), 4); memcpy(&(file_req.nPositionHigh), (((uint8_t *)&(i->context->ft_to_client->transferred)) + 4), 4); i->context->clipboard->clip_context->ClientFileContentsRequest( i->context->clipboard->clip_context, &file_req); return true; } static bool ft_api_handle_chunk(const wrdp_backend_ft_chunk *chunk, const uint8_t *data, void *backend_internals) { rdp_internals *i = backend_internals; CLIPRDR_FILE_CONTENTS_RESPONSE resp; memset(&resp, 0, sizeof(CLIPRDR_FILE_CONTENTS_RESPONSE)); resp.cbRequested = chunk->size; resp.streamId = i->context->ft_to_server->transfer_id; resp.common.msgFlags = CB_RESPONSE_OK; resp.common.msgType = CB_FILECONTENTS_RESPONSE; resp.requestedData = data; i->context->clipboard->clip_context->ClientFileContentsResponse( i->context->clipboard->clip_context, &resp); i->context->ft_to_server->transferred += chunk->size; if (i->context->ft_to_server->transferred == i->context->ft_to_server->file_size) { i->context->ft_to_server->is_runing = false; i->context->ft_to_server->transfer_id = 0; i->context->ft_to_server->file_id = 0; i->context->ft_to_server->file_size = 0; i->context->ft_to_server->transferred = 0; } return true; } static bool ft_api_handle_finish( const wrdp_backend_ft_status *status, void *backend_internals) { /* TODO: handle errors */ rdp_internals *i = backend_internals; if (status->status != ft_status_success) { /* TODO: test it */ CLIPRDR_FILE_CONTENTS_RESPONSE resp; memset(&resp, 0, sizeof(CLIPRDR_FILE_CONTENTS_RESPONSE)); const char *msg = "filetransfer finished with error"; i->core->api_utils->log_msg( (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0); resp.common.msgType = CB_FILECONTENTS_RESPONSE; resp.common.msgFlags = CB_RESPONSE_FAIL; resp.streamId = i->context->ft_to_server->transfer_id; resp.cbRequested = 0; resp.requestedData = 0; i->context->clipboard->clip_context->ClientFileContentsResponse( i->context->clipboard->clip_context, &resp); } i->context->ft_to_server->is_runing = false; i->context->ft_to_server->transfer_id = 0; i->context->ft_to_server->file_size = i->context->ft_to_server->transferred = 0; return true; } void register_ft(wrdp_backend_module *backend) { backend->callbacks_ft->chunk = ft_api_handle_chunk; backend->callbacks_ft->finish = ft_api_handle_finish; backend->callbacks_ft->request = ft_api_handle_request; }