win_fix_multi_tab: refactor clipboard on windows, mid commit

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-10-25 18:46:38 +08:00
parent 6da1d37100
commit 2faa5cfd18
4 changed files with 110 additions and 91 deletions

View File

@ -239,8 +239,6 @@ pub type CLIPRDR_FORMAT = _CLIPRDR_FORMAT;
pub struct _CLIPRDR_FORMAT_LIST { pub struct _CLIPRDR_FORMAT_LIST {
pub connID: UINT32, pub connID: UINT32,
pub msgType: UINT16, pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub numFormats: UINT32, pub numFormats: UINT32,
pub formats: *mut CLIPRDR_FORMAT, pub formats: *mut CLIPRDR_FORMAT,
} }

View File

@ -1,6 +1,6 @@
use cliprdr::*; use cliprdr::*;
use hbb_common::{ use hbb_common::{
log, allow_err, log,
tokio::sync::{ tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex, Mutex as TokioMutex,
@ -12,7 +12,7 @@ use std::{
boxed::Box, boxed::Box,
collections::HashMap, collections::HashMap,
ffi::{CStr, CString}, ffi::{CStr, CString},
sync::Mutex, sync::{Arc, Mutex, RwLock},
}; };
pub mod cliprdr; pub mod cliprdr;
@ -20,25 +20,20 @@ pub mod cliprdr;
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "t", content = "c")] #[serde(tag = "t", content = "c")]
pub enum ClipbaordFile { pub enum ClipbaordFile {
ServerFormatList { FormatList {
conn_id: i32,
format_list: Vec<(i32, String)>, format_list: Vec<(i32, String)>,
}, },
ServerFormatListResponse { FormatListResponse {
conn_id: i32,
msg_flags: i32, msg_flags: i32,
}, },
ServerFormatDataRequest { FormatDataRequest {
conn_id: i32,
requested_format_id: i32, requested_format_id: i32,
}, },
ServerFormatDataResponse { FormatDataResponse {
conn_id: i32,
msg_flags: i32, msg_flags: i32,
format_data: Vec<u8>, format_data: Vec<u8>,
}, },
FileContentsRequest { FileContentsRequest {
conn_id: i32,
stream_id: i32, stream_id: i32,
list_index: i32, list_index: i32,
dw_flags: i32, dw_flags: i32,
@ -49,7 +44,6 @@ pub enum ClipbaordFile {
clip_data_id: i32, clip_data_id: i32,
}, },
FileContentsResponse { FileContentsResponse {
conn_id: i32,
msg_flags: i32, msg_flags: i32,
stream_id: i32, stream_id: i32,
requested_data: Vec<u8>, requested_data: Vec<u8>,
@ -61,18 +55,76 @@ struct ConnEnabled {
conn_enabled: HashMap<i32, bool>, conn_enabled: HashMap<i32, bool>,
} }
lazy_static::lazy_static! { struct MsgChannel {
static ref MSG_CHANNEL_CLIENT: (UnboundedSender<(i32, ClipbaordFile)>, TokioMutex<UnboundedReceiver<(i32, ClipbaordFile)>>) = { peer_id: String,
let (tx, rx) = unbounded_channel(); conn_id: i32,
(tx, TokioMutex::new(rx)) sender: UnboundedSender<ClipbaordFile>,
}; receiver: Arc<TokioMutex<UnboundedReceiver<ClipbaordFile>>>,
}
lazy_static::lazy_static! {
static ref VEC_MSG_CHANNEL: RwLock<Vec<MsgChannel>> = Default::default();
static ref CLIP_CONN_ENABLED: Mutex<ConnEnabled> = Mutex::new(ConnEnabled::default()); static ref CLIP_CONN_ENABLED: Mutex<ConnEnabled> = Mutex::new(ConnEnabled::default());
} }
#[inline(always)] #[inline]
pub fn get_rx_clip_client<'a>() -> &'a TokioMutex<UnboundedReceiver<(i32, ClipbaordFile)>> { pub async fn get_rx_cliprdr_client<'a>(
&MSG_CHANNEL_CLIENT.1 peer_id: &str,
) -> (i32, Arc<TokioMutex<UnboundedReceiver<ClipbaordFile>>>) {
let mut lock = VEC_MSG_CHANNEL.write().unwrap();
match lock.iter().find(|x| x.peer_id == peer_id.to_owned()) {
Some(msg_channel) => (msg_channel.conn_id, msg_channel.receiver.clone()),
None => {
let (sender, receiver) = unbounded_channel();
let receiver = Arc::new(TokioMutex::new(receiver));
let receiver2 = receiver.clone();
let conn_id = lock.len() as i32 + 1;
let msg_channel = MsgChannel {
peer_id: peer_id.to_owned(),
conn_id,
sender,
receiver,
};
lock.push(msg_channel);
(conn_id, receiver2)
}
}
}
#[inline]
pub async fn get_rx_cliprdr_server<'a>(
conn_id: i32,
) -> Arc<TokioMutex<UnboundedReceiver<ClipbaordFile>>> {
let mut lock = VEC_MSG_CHANNEL.write().unwrap();
match lock.iter().find(|x| x.conn_id == conn_id) {
Some(msg_channel) => msg_channel.receiver.clone(),
None => {
let (sender, receiver) = unbounded_channel();
let receiver = Arc::new(TokioMutex::new(receiver));
let receiver2 = receiver.clone();
let msg_channel = MsgChannel {
peer_id: "".to_owned(),
conn_id,
sender,
receiver,
};
lock.push(msg_channel);
receiver2
}
}
}
#[inline]
fn send_data(conn_id: i32, data: ClipbaordFile) {
// no need to handle result here
if let Some(msg_channel) = VEC_MSG_CHANNEL
.read()
.unwrap()
.iter()
.find(|x| x.conn_id == conn_id)
{
allow_err!(msg_channel.sender.send(data));
}
} }
pub fn set_conn_enabled(conn_id: i32, enabled: bool) { pub fn set_conn_enabled(conn_id: i32, enabled: bool) {
@ -88,61 +140,40 @@ pub fn empty_clipboard(context: &mut Box<CliprdrClientContext>, conn_id: i32) ->
pub fn server_clip_file( pub fn server_clip_file(
context: &mut Box<CliprdrClientContext>, context: &mut Box<CliprdrClientContext>,
s_conn_id: i32, conn_id: i32,
msg: ClipbaordFile, msg: ClipbaordFile,
) -> u32 { ) -> u32 {
match msg { match msg {
ClipbaordFile::ServerFormatList { ClipbaordFile::FormatList { format_list } => {
mut conn_id,
format_list,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("server_format_list called"); log::debug!("server_format_list called");
let ret = server_format_list(context, conn_id, format_list); let ret = server_format_list(context, conn_id, format_list);
log::debug!("server_format_list called, return {}", ret); log::debug!("server_format_list called, return {}", ret);
ret ret
} }
ClipbaordFile::ServerFormatListResponse { ClipbaordFile::FormatListResponse { msg_flags } => {
mut conn_id,
msg_flags,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_list_response called"); log::debug!("format_list_response called");
let ret = server_format_list_response(context, conn_id, msg_flags); let ret = server_format_list_response(context, conn_id, msg_flags);
log::debug!("server_format_list_response called, return {}", ret); log::debug!("server_format_list_response called, return {}", ret);
ret ret
} }
ClipbaordFile::ServerFormatDataRequest { ClipbaordFile::FormatDataRequest {
mut conn_id,
requested_format_id, requested_format_id,
} => { } => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_data_request called"); log::debug!("format_data_request called");
let ret = server_format_data_request(context, conn_id, requested_format_id); let ret = server_format_data_request(context, conn_id, requested_format_id);
log::debug!("server_format_data_request called, return {}", ret); log::debug!("server_format_data_request called, return {}", ret);
ret ret
} }
ClipbaordFile::ServerFormatDataResponse { ClipbaordFile::FormatDataResponse {
mut conn_id,
msg_flags, msg_flags,
format_data, format_data,
} => { } => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_data_response called"); log::debug!("format_data_response called");
let ret = server_format_data_response(context, conn_id, msg_flags, format_data); let ret = server_format_data_response(context, conn_id, msg_flags, format_data);
log::debug!("server_format_data_response called, return {}", ret); log::debug!("server_format_data_response called, return {}", ret);
ret ret
} }
ClipbaordFile::FileContentsRequest { ClipbaordFile::FileContentsRequest {
mut conn_id,
stream_id, stream_id,
list_index, list_index,
dw_flags, dw_flags,
@ -152,9 +183,6 @@ pub fn server_clip_file(
have_clip_data_id, have_clip_data_id,
clip_data_id, clip_data_id,
} => { } => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("file_contents_request called"); log::debug!("file_contents_request called");
let ret = server_file_contents_request( let ret = server_file_contents_request(
context, context,
@ -172,14 +200,10 @@ pub fn server_clip_file(
ret ret
} }
ClipbaordFile::FileContentsResponse { ClipbaordFile::FileContentsResponse {
mut conn_id,
msg_flags, msg_flags,
stream_id, stream_id,
requested_data, requested_data,
} => { } => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("file_contents_response called"); log::debug!("file_contents_response called");
let ret = server_file_contents_response( let ret = server_file_contents_response(
context, context,
@ -225,8 +249,6 @@ pub fn server_format_list(
let format_list = CLIPRDR_FORMAT_LIST { let format_list = CLIPRDR_FORMAT_LIST {
connID: conn_id as UINT32, connID: conn_id as UINT32,
msgType: 0 as UINT16, msgType: 0 as UINT16,
msgFlags: 0 as UINT16,
dataLen: 0 as UINT32,
numFormats: num_formats, numFormats: num_formats,
formats: formats.as_mut_ptr(), formats: formats.as_mut_ptr(),
}; };
@ -243,6 +265,7 @@ pub fn server_format_list(
ret as u32 ret as u32
} }
} }
pub fn server_format_list_response( pub fn server_format_list_response(
context: &mut Box<CliprdrClientContext>, context: &mut Box<CliprdrClientContext>,
conn_id: i32, conn_id: i32,
@ -262,6 +285,7 @@ pub fn server_format_list_response(
ret as u32 ret as u32
} }
} }
pub fn server_format_data_request( pub fn server_format_data_request(
context: &mut Box<CliprdrClientContext>, context: &mut Box<CliprdrClientContext>,
conn_id: i32, conn_id: i32,
@ -280,6 +304,7 @@ pub fn server_format_data_request(
ret as u32 ret as u32
} }
} }
pub fn server_format_data_response( pub fn server_format_data_response(
context: &mut Box<CliprdrClientContext>, context: &mut Box<CliprdrClientContext>,
conn_id: i32, conn_id: i32,
@ -301,6 +326,7 @@ pub fn server_format_data_response(
ret as u32 ret as u32
} }
} }
pub fn server_file_contents_request( pub fn server_file_contents_request(
context: &mut Box<CliprdrClientContext>, context: &mut Box<CliprdrClientContext>,
conn_id: i32, conn_id: i32,
@ -335,6 +361,7 @@ pub fn server_file_contents_request(
ret as u32 ret as u32
} }
} }
pub fn server_file_contents_response( pub fn server_file_contents_response(
context: &mut Box<CliprdrClientContext>, context: &mut Box<CliprdrClientContext>,
conn_id: i32, conn_id: i32,
@ -398,7 +425,7 @@ extern "C" fn client_format_list(
) -> UINT { ) -> UINT {
log::debug!("client_format_list called"); log::debug!("client_format_list called");
let conn_id; // let conn_id;
let mut format_list: Vec<(i32, String)> = Vec::new(); let mut format_list: Vec<(i32, String)> = Vec::new();
unsafe { unsafe {
let mut i = 0u32; let mut i = 0u32;
@ -420,14 +447,15 @@ extern "C" fn client_format_list(
// log::debug!("format list item {}: format id: {}, format name: {}", i, format_data.formatId, &format_name); // log::debug!("format list item {}: format id: {}, format name: {}", i, format_data.formatId, &format_name);
i += 1; i += 1;
} }
conn_id = (*clip_format_list).connID as i32; // conn_id = (*clip_format_list).connID as i32;
} }
let data = ClipbaordFile::ServerFormatList { let data = ClipbaordFile::FormatList { format_list };
conn_id,
format_list,
};
// no need to handle result here // no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); VEC_MSG_CHANNEL
.read()
.unwrap()
.iter()
.for_each(|msg_channel| allow_err!(msg_channel.sender.send(data.clone())));
0 0
} }
@ -444,9 +472,8 @@ extern "C" fn client_format_list_response(
conn_id = (*format_list_response).connID as i32; conn_id = (*format_list_response).connID as i32;
msg_flags = (*format_list_response).msgFlags as i32; msg_flags = (*format_list_response).msgFlags as i32;
} }
let data = ClipbaordFile::ServerFormatListResponse { conn_id, msg_flags }; let data = ClipbaordFile::FormatListResponse { msg_flags };
// no need to handle result here send_data(conn_id, data);
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0 0
} }
@ -463,12 +490,11 @@ extern "C" fn client_format_data_request(
conn_id = (*format_data_request).connID as i32; conn_id = (*format_data_request).connID as i32;
requested_format_id = (*format_data_request).requestedFormatId as i32; requested_format_id = (*format_data_request).requestedFormatId as i32;
} }
let data = ClipbaordFile::ServerFormatDataRequest { let data = ClipbaordFile::FormatDataRequest {
conn_id,
requested_format_id, requested_format_id,
}; };
// no need to handle result here // no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); send_data(conn_id, data);
0 0
} }
@ -495,13 +521,11 @@ extern "C" fn client_format_data_response(
.to_vec(); .to_vec();
} }
} }
let data = ClipbaordFile::ServerFormatDataResponse { let data = ClipbaordFile::FormatDataResponse {
conn_id,
msg_flags, msg_flags,
format_data, format_data,
}; };
// no need to handle result here send_data(conn_id, data);
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0 0
} }
@ -544,7 +568,6 @@ extern "C" fn client_file_contents_request(
} }
let data = ClipbaordFile::FileContentsRequest { let data = ClipbaordFile::FileContentsRequest {
conn_id,
stream_id, stream_id,
list_index, list_index,
dw_flags, dw_flags,
@ -554,8 +577,7 @@ extern "C" fn client_file_contents_request(
have_clip_data_id, have_clip_data_id,
clip_data_id, clip_data_id,
}; };
// no need to handle result here send_data(conn_id, data);
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0 0
} }
@ -585,13 +607,11 @@ extern "C" fn client_file_contents_response(
} }
} }
let data = ClipbaordFile::FileContentsResponse { let data = ClipbaordFile::FileContentsResponse {
conn_id,
msg_flags, msg_flags,
stream_id, stream_id,
requested_data, requested_data,
}; };
// no need to handle result here send_data(conn_id, data);
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0 0
} }

View File

@ -193,6 +193,7 @@ struct _CliprdrDataObject
ULONG m_nStreams; ULONG m_nStreams;
IStream **m_pStream; IStream **m_pStream;
void *m_pData; void *m_pData;
DWORD m_processID;
UINT32 m_connID; UINT32 m_connID;
}; };
typedef struct _CliprdrDataObject CliprdrDataObject; typedef struct _CliprdrDataObject CliprdrDataObject;
@ -246,7 +247,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr);
BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr); BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr);
BOOL wf_do_empty_cliprdr(wfClipboard *clipboard); BOOL wf_do_empty_cliprdr(wfClipboard *clipboard);
static BOOL wf_create_file_obj(UINT32 connID, wfClipboard *cliprdrrdr, IDataObject **ppDataObject); static BOOL wf_create_file_obj(UINT32 *connID, wfClipboard *clipboard, IDataObject **ppDataObject);
static void wf_destroy_file_obj(IDataObject *instance); static void wf_destroy_file_obj(IDataObject *instance);
static UINT32 get_remote_format_id(wfClipboard *clipboard, UINT32 local_format); static UINT32 get_remote_format_id(wfClipboard *clipboard, UINT32 local_format);
static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UINT32 format); static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UINT32 format);
@ -673,6 +674,12 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
if (!pFormatEtc || !pMedium || !instance) if (!pFormatEtc || !pMedium || !instance)
return E_INVALIDARG; return E_INVALIDARG;
// Not the same process id
if (instance->m_processID != GetCurrentProcessId())
{
return E_INVALIDARG;
}
clipboard = (wfClipboard *)instance->m_pData; clipboard = (wfClipboard *)instance->m_pData;
if (!clipboard->context->CheckEnabled(instance->m_connID)) if (!clipboard->context->CheckEnabled(instance->m_connID))
{ {
@ -892,6 +899,7 @@ static CliprdrDataObject *CliprdrDataObject_New(UINT32 connID, FORMATETC *fmtetc
instance->m_pData = data; instance->m_pData = data;
instance->m_nStreams = 0; instance->m_nStreams = 0;
instance->m_pStream = NULL; instance->m_pStream = NULL;
instance->m_processID = GetCurrentProcessId();
instance->m_connID = connID; instance->m_connID = connID;
if (count > 0) if (count > 0)
@ -966,7 +974,7 @@ static BOOL wf_create_file_obj(UINT32 *connID, wfClipboard *clipboard, IDataObje
stgmeds[1].tymed = TYMED_ISTREAM; stgmeds[1].tymed = TYMED_ISTREAM;
stgmeds[1].pstm = NULL; stgmeds[1].pstm = NULL;
stgmeds[1].pUnkForRelease = NULL; stgmeds[1].pUnkForRelease = NULL;
*ppDataObject = (IDataObject *)CliprdrDataObject_New(*connID, fmtetc, stgmeds, 2, clipboard); *ppDataObject = (IDataObject *)CliprdrDataObject_New(*connID, *(connID + 1), fmtetc, stgmeds, 2, clipboard);
return (*ppDataObject) ? TRUE : FALSE; return (*ppDataObject) ? TRUE : FALSE;
} }
@ -1669,7 +1677,8 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
DEBUG_CLIPRDR("info: WM_RENDERFORMAT"); DEBUG_CLIPRDR("info: WM_RENDERFORMAT");
// https://docs.microsoft.com/en-us/windows/win32/dataxchg/wm-renderformat?redirectedfrom=MSDN // https://docs.microsoft.com/en-us/windows/win32/dataxchg/wm-renderformat?redirectedfrom=MSDN
if (cliprdr_send_data_request(0, 0, clipboard, (UINT32)wParam) != 0) // to-do: ensure usage of 0
if (cliprdr_send_data_request(0, clipboard, (UINT32)wParam) != 0)
{ {
DEBUG_CLIPRDR("error: cliprdr_send_data_request failed."); DEBUG_CLIPRDR("error: cliprdr_send_data_request failed.");
break; break;

View File

@ -360,38 +360,31 @@ message FileDirCreate {
// main logic from freeRDP // main logic from freeRDP
message CliprdrMonitorReady { message CliprdrMonitorReady {
int32 conn_id = 1;
} }
message CliprdrFormat { message CliprdrFormat {
int32 conn_id = 1;
int32 id = 2; int32 id = 2;
string format = 3; string format = 3;
} }
message CliprdrServerFormatList { message CliprdrServerFormatList {
int32 conn_id = 1;
repeated CliprdrFormat formats = 2; repeated CliprdrFormat formats = 2;
} }
message CliprdrServerFormatListResponse { message CliprdrServerFormatListResponse {
int32 conn_id = 1;
int32 msg_flags = 2; int32 msg_flags = 2;
} }
message CliprdrServerFormatDataRequest { message CliprdrServerFormatDataRequest {
int32 conn_id = 1;
int32 requested_format_id = 2; int32 requested_format_id = 2;
} }
message CliprdrServerFormatDataResponse { message CliprdrServerFormatDataResponse {
int32 conn_id = 1;
int32 msg_flags = 2; int32 msg_flags = 2;
bytes format_data = 3; bytes format_data = 3;
} }
message CliprdrFileContentsRequest { message CliprdrFileContentsRequest {
int32 conn_id = 1;
int32 stream_id = 2; int32 stream_id = 2;
int32 list_index = 3; int32 list_index = 3;
int32 dw_flags = 4; int32 dw_flags = 4;
@ -403,7 +396,6 @@ message CliprdrFileContentsRequest {
} }
message CliprdrFileContentsResponse { message CliprdrFileContentsResponse {
int32 conn_id = 1;
int32 msg_flags = 3; int32 msg_flags = 3;
int32 stream_id = 4; int32 stream_id = 4;
bytes requested_data = 5; bytes requested_data = 5;