mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge pull request #416 from fufesou/copy_paste
Move clipboard service to cm module
This commit is contained in:
commit
4fb8de9b68
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -395,6 +395,8 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"hbb_common",
|
"hbb_common",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"serde 1.0.135",
|
||||||
|
"serde_derive",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -12,4 +12,6 @@ cc = "1.0"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
hbb_common = { path = "../hbb_common" }
|
hbb_common = { path = "../hbb_common" }
|
||||||
|
|||||||
@ -192,6 +192,8 @@ extern "C"
|
|||||||
typedef UINT (*pcCliprdrServerFileContentsResponse)(
|
typedef UINT (*pcCliprdrServerFileContentsResponse)(
|
||||||
CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse);
|
CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse);
|
||||||
|
|
||||||
|
typedef BOOL (*pcCheckEnabled)(UINT32 server_conn_id, UINT32 remote_conn_id);
|
||||||
|
|
||||||
// TODO: hide more members of clipboard context
|
// TODO: hide more members of clipboard context
|
||||||
struct _cliprdr_client_context
|
struct _cliprdr_client_context
|
||||||
{
|
{
|
||||||
@ -199,6 +201,7 @@ extern "C"
|
|||||||
BOOL enableFiles;
|
BOOL enableFiles;
|
||||||
BOOL enableOthers;
|
BOOL enableOthers;
|
||||||
|
|
||||||
|
pcCheckEnabled CheckEnabled;
|
||||||
pcCliprdrServerCapabilities ServerCapabilities;
|
pcCliprdrServerCapabilities ServerCapabilities;
|
||||||
pcCliprdrClientCapabilities ClientCapabilities;
|
pcCliprdrClientCapabilities ClientCapabilities;
|
||||||
pcCliprdrMonitorReady MonitorReady;
|
pcCliprdrMonitorReady MonitorReady;
|
||||||
|
|||||||
@ -456,6 +456,9 @@ pub type pcCliprdrServerFileContentsResponse = ::std::option::Option<
|
|||||||
fileContentsResponse: *const CLIPRDR_FILE_CONTENTS_RESPONSE,
|
fileContentsResponse: *const CLIPRDR_FILE_CONTENTS_RESPONSE,
|
||||||
) -> UINT,
|
) -> UINT,
|
||||||
>;
|
>;
|
||||||
|
pub type pcCheckEnabled = ::std::option::Option<
|
||||||
|
unsafe extern "C" fn(server_conn_id: UINT32, remote_conn_id: UINT32) -> BOOL,
|
||||||
|
>;
|
||||||
|
|
||||||
// TODO: hide more members of clipboard context
|
// TODO: hide more members of clipboard context
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -464,6 +467,7 @@ pub struct _cliprdr_client_context {
|
|||||||
pub custom: *mut ::std::os::raw::c_void,
|
pub custom: *mut ::std::os::raw::c_void,
|
||||||
pub enableFiles: BOOL,
|
pub enableFiles: BOOL,
|
||||||
pub enableOthers: BOOL,
|
pub enableOthers: BOOL,
|
||||||
|
pub CheckEnabled: pcCheckEnabled,
|
||||||
pub ServerCapabilities: pcCliprdrServerCapabilities,
|
pub ServerCapabilities: pcCliprdrServerCapabilities,
|
||||||
pub ClientCapabilities: pcCliprdrClientCapabilities,
|
pub ClientCapabilities: pcCliprdrClientCapabilities,
|
||||||
pub MonitorReady: pcCliprdrMonitorReady,
|
pub MonitorReady: pcCliprdrMonitorReady,
|
||||||
@ -492,6 +496,11 @@ pub struct _cliprdr_client_context {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
pub(crate) fn init_cliprdr(context: *mut CliprdrClientContext) -> BOOL;
|
pub(crate) fn init_cliprdr(context: *mut CliprdrClientContext) -> BOOL;
|
||||||
pub(crate) fn uninit_cliprdr(context: *mut CliprdrClientContext) -> BOOL;
|
pub(crate) fn uninit_cliprdr(context: *mut CliprdrClientContext) -> BOOL;
|
||||||
|
pub(crate) fn empty_cliprdr(
|
||||||
|
context: *mut CliprdrClientContext,
|
||||||
|
server_conn_id: UINT32,
|
||||||
|
remote_conn_id: UINT32,
|
||||||
|
) -> BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
@ -508,6 +517,7 @@ impl CliprdrClientContext {
|
|||||||
pub fn create(
|
pub fn create(
|
||||||
enable_files: bool,
|
enable_files: bool,
|
||||||
enable_others: bool,
|
enable_others: bool,
|
||||||
|
check_enabled: pcCheckEnabled,
|
||||||
client_format_list: pcCliprdrClientFormatList,
|
client_format_list: pcCliprdrClientFormatList,
|
||||||
client_format_list_response: pcCliprdrClientFormatListResponse,
|
client_format_list_response: pcCliprdrClientFormatListResponse,
|
||||||
client_format_data_request: pcCliprdrClientFormatDataRequest,
|
client_format_data_request: pcCliprdrClientFormatDataRequest,
|
||||||
@ -519,6 +529,7 @@ impl CliprdrClientContext {
|
|||||||
custom: 0 as *mut _,
|
custom: 0 as *mut _,
|
||||||
enableFiles: if enable_files { TRUE } else { FALSE },
|
enableFiles: if enable_files { TRUE } else { FALSE },
|
||||||
enableOthers: if enable_others { TRUE } else { FALSE },
|
enableOthers: if enable_others { TRUE } else { FALSE },
|
||||||
|
CheckEnabled: check_enabled,
|
||||||
ServerCapabilities: None,
|
ServerCapabilities: None,
|
||||||
ClientCapabilities: None,
|
ClientCapabilities: None,
|
||||||
MonitorReady: None,
|
MonitorReady: None,
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
use cliprdr::*;
|
use cliprdr::*;
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
log,
|
log,
|
||||||
message_proto::cliprdr as msg_cliprdr,
|
|
||||||
message_proto::*,
|
|
||||||
tokio::sync::{
|
tokio::sync::{
|
||||||
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
||||||
Mutex as TokioMutex,
|
Mutex as TokioMutex,
|
||||||
},
|
},
|
||||||
ResultType,
|
ResultType,
|
||||||
};
|
};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
|
collections::HashMap,
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
|
sync::Mutex,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod cliprdr;
|
pub mod cliprdr;
|
||||||
@ -22,111 +23,273 @@ pub struct ConnID {
|
|||||||
pub remote_conn_id: u32,
|
pub remote_conn_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(tag = "t", content = "c")]
|
||||||
|
pub enum ClipbaordFile {
|
||||||
|
ServerFormatList {
|
||||||
|
server_conn_id: i32,
|
||||||
|
remote_conn_id: i32,
|
||||||
|
format_list: Vec<(i32, String)>,
|
||||||
|
},
|
||||||
|
ServerFormatListResponse {
|
||||||
|
server_conn_id: i32,
|
||||||
|
remote_conn_id: i32,
|
||||||
|
msg_flags: i32,
|
||||||
|
},
|
||||||
|
ServerFormatDataRequest {
|
||||||
|
server_conn_id: i32,
|
||||||
|
remote_conn_id: i32,
|
||||||
|
requested_format_id: i32,
|
||||||
|
},
|
||||||
|
ServerFormatDataResponse {
|
||||||
|
server_conn_id: i32,
|
||||||
|
remote_conn_id: i32,
|
||||||
|
msg_flags: i32,
|
||||||
|
format_data: Vec<u8>,
|
||||||
|
},
|
||||||
|
FileContentsRequest {
|
||||||
|
server_conn_id: i32,
|
||||||
|
remote_conn_id: i32,
|
||||||
|
stream_id: i32,
|
||||||
|
list_index: i32,
|
||||||
|
dw_flags: i32,
|
||||||
|
n_position_low: i32,
|
||||||
|
n_position_high: i32,
|
||||||
|
cb_requested: i32,
|
||||||
|
have_clip_data_id: bool,
|
||||||
|
clip_data_id: i32,
|
||||||
|
},
|
||||||
|
FileContentsResponse {
|
||||||
|
server_conn_id: i32,
|
||||||
|
remote_conn_id: i32,
|
||||||
|
msg_flags: i32,
|
||||||
|
stream_id: i32,
|
||||||
|
requested_data: Vec<u8>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct ConnEnabled {
|
||||||
|
server_conn_enabled: HashMap<i32, bool>,
|
||||||
|
remote_conn_enabled: HashMap<i32, bool>,
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref MSG_CHANNEL_CLIENT: (UnboundedSender<(ConnID, Message)>, TokioMutex<UnboundedReceiver<(ConnID, Message)>>) = {
|
static ref MSG_CHANNEL_CLIENT: (UnboundedSender<(ConnID, ClipbaordFile)>, TokioMutex<UnboundedReceiver<(ConnID, ClipbaordFile)>>) = {
|
||||||
let (tx, rx) = unbounded_channel();
|
let (tx, rx) = unbounded_channel();
|
||||||
(tx, TokioMutex::new(rx))
|
(tx, TokioMutex::new(rx))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ref CLIP_CONN_ENABLED: Mutex<ConnEnabled> = Mutex::new(ConnEnabled::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_rx_client_msg<'a>() -> &'a TokioMutex<UnboundedReceiver<(ConnID, Message)>> {
|
pub fn get_rx_clip_client<'a>() -> &'a TokioMutex<UnboundedReceiver<(ConnID, ClipbaordFile)>> {
|
||||||
&MSG_CHANNEL_CLIENT.1
|
&MSG_CHANNEL_CLIENT.1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn server_msg(context: &mut Box<CliprdrClientContext>, conn_id: ConnID, msg: Cliprdr) -> u32 {
|
pub fn set_conn_enabled(server_conn_id: i32, remote_conn_id: i32, enabled: bool) {
|
||||||
match msg.union {
|
let mut lock = CLIP_CONN_ENABLED.lock().unwrap();
|
||||||
Some(msg_cliprdr::Union::ready(_)) => {
|
if server_conn_id != 0 {
|
||||||
// proc ready
|
let _ = lock.server_conn_enabled.insert(server_conn_id, enabled);
|
||||||
0
|
}
|
||||||
|
if remote_conn_id != 0 {
|
||||||
|
let _ = lock.remote_conn_enabled.insert(remote_conn_id, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn empty_clipboard(
|
||||||
|
context: &mut Box<CliprdrClientContext>,
|
||||||
|
server_conn_id: i32,
|
||||||
|
remote_conn_id: i32,
|
||||||
|
) -> bool {
|
||||||
|
unsafe {
|
||||||
|
TRUE == cliprdr::empty_cliprdr(
|
||||||
|
&mut (**context),
|
||||||
|
server_conn_id as u32,
|
||||||
|
remote_conn_id as u32,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn server_clip_file(
|
||||||
|
context: &mut Box<CliprdrClientContext>,
|
||||||
|
conn_id: ConnID,
|
||||||
|
msg: ClipbaordFile,
|
||||||
|
) -> u32 {
|
||||||
|
match msg {
|
||||||
|
ClipbaordFile::ServerFormatList {
|
||||||
|
mut server_conn_id,
|
||||||
|
mut remote_conn_id,
|
||||||
|
format_list,
|
||||||
|
} => {
|
||||||
|
if conn_id.server_conn_id != 0 {
|
||||||
|
server_conn_id = conn_id.server_conn_id as i32;
|
||||||
|
}
|
||||||
|
if conn_id.remote_conn_id != 0 {
|
||||||
|
remote_conn_id = conn_id.remote_conn_id as i32;
|
||||||
}
|
}
|
||||||
Some(msg_cliprdr::Union::format_list(req)) => {
|
|
||||||
log::debug!("server_format_list called");
|
log::debug!("server_format_list called");
|
||||||
let ret = server_format_list(context, conn_id, req);
|
let ret = server_format_list(context, server_conn_id, remote_conn_id, format_list);
|
||||||
log::debug!("server_format_list called, return {}", ret);
|
log::debug!("server_format_list called, return {}", ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
Some(msg_cliprdr::Union::format_list_response(req)) => {
|
ClipbaordFile::ServerFormatListResponse {
|
||||||
|
mut server_conn_id,
|
||||||
|
mut remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
} => {
|
||||||
|
if conn_id.server_conn_id != 0 {
|
||||||
|
server_conn_id = conn_id.server_conn_id as i32;
|
||||||
|
}
|
||||||
|
if conn_id.remote_conn_id != 0 {
|
||||||
|
remote_conn_id = conn_id.remote_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, req);
|
let ret =
|
||||||
|
server_format_list_response(context, server_conn_id, remote_conn_id, msg_flags);
|
||||||
log::debug!("server_format_list_response called, return {}", ret);
|
log::debug!("server_format_list_response called, return {}", ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
Some(msg_cliprdr::Union::format_data_request(req)) => {
|
ClipbaordFile::ServerFormatDataRequest {
|
||||||
|
mut server_conn_id,
|
||||||
|
mut remote_conn_id,
|
||||||
|
requested_format_id,
|
||||||
|
} => {
|
||||||
|
if conn_id.server_conn_id != 0 {
|
||||||
|
server_conn_id = conn_id.server_conn_id as i32;
|
||||||
|
}
|
||||||
|
if conn_id.remote_conn_id != 0 {
|
||||||
|
remote_conn_id = conn_id.remote_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, req);
|
let ret = server_format_data_request(
|
||||||
|
context,
|
||||||
|
server_conn_id,
|
||||||
|
remote_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
|
||||||
}
|
}
|
||||||
Some(msg_cliprdr::Union::format_data_response(req)) => {
|
ClipbaordFile::ServerFormatDataResponse {
|
||||||
|
mut server_conn_id,
|
||||||
|
mut remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
format_data,
|
||||||
|
} => {
|
||||||
|
if conn_id.server_conn_id != 0 {
|
||||||
|
server_conn_id = conn_id.server_conn_id as i32;
|
||||||
|
}
|
||||||
|
if conn_id.remote_conn_id != 0 {
|
||||||
|
remote_conn_id = conn_id.remote_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, req);
|
let ret = server_format_data_response(
|
||||||
|
context,
|
||||||
|
server_conn_id,
|
||||||
|
remote_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
|
||||||
}
|
}
|
||||||
Some(msg_cliprdr::Union::file_contents_request(req)) => {
|
ClipbaordFile::FileContentsRequest {
|
||||||
|
mut server_conn_id,
|
||||||
|
mut remote_conn_id,
|
||||||
|
stream_id,
|
||||||
|
list_index,
|
||||||
|
dw_flags,
|
||||||
|
n_position_low,
|
||||||
|
n_position_high,
|
||||||
|
cb_requested,
|
||||||
|
have_clip_data_id,
|
||||||
|
clip_data_id,
|
||||||
|
} => {
|
||||||
|
if conn_id.server_conn_id != 0 {
|
||||||
|
server_conn_id = conn_id.server_conn_id as i32;
|
||||||
|
}
|
||||||
|
if conn_id.remote_conn_id != 0 {
|
||||||
|
remote_conn_id = conn_id.remote_conn_id as i32;
|
||||||
|
}
|
||||||
log::debug!("file_contents_request called");
|
log::debug!("file_contents_request called");
|
||||||
let ret = server_file_contents_request(context, conn_id, req);
|
let ret = server_file_contents_request(
|
||||||
|
context,
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
stream_id,
|
||||||
|
list_index,
|
||||||
|
dw_flags,
|
||||||
|
n_position_low,
|
||||||
|
n_position_high,
|
||||||
|
cb_requested,
|
||||||
|
have_clip_data_id,
|
||||||
|
clip_data_id,
|
||||||
|
);
|
||||||
log::debug!("server_file_contents_request called, return {}", ret);
|
log::debug!("server_file_contents_request called, return {}", ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
Some(msg_cliprdr::Union::file_contents_response(req)) => {
|
ClipbaordFile::FileContentsResponse {
|
||||||
|
mut server_conn_id,
|
||||||
|
mut remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
stream_id,
|
||||||
|
requested_data,
|
||||||
|
} => {
|
||||||
|
if conn_id.server_conn_id != 0 {
|
||||||
|
server_conn_id = conn_id.server_conn_id as i32;
|
||||||
|
}
|
||||||
|
if conn_id.remote_conn_id != 0 {
|
||||||
|
remote_conn_id = conn_id.remote_conn_id as i32;
|
||||||
|
}
|
||||||
log::debug!("file_contents_response called");
|
log::debug!("file_contents_response called");
|
||||||
let ret = server_file_contents_response(context, conn_id, req);
|
let ret = server_file_contents_response(
|
||||||
|
context,
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
stream_id,
|
||||||
|
requested_data,
|
||||||
|
);
|
||||||
log::debug!("server_file_contents_response called, return {}", ret);
|
log::debug!("server_file_contents_response called, return {}", ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
// unreachable!()
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn server_format_list(
|
pub fn server_format_list(
|
||||||
context: &mut Box<CliprdrClientContext>,
|
context: &mut Box<CliprdrClientContext>,
|
||||||
conn_id: ConnID,
|
server_conn_id: i32,
|
||||||
data: CliprdrServerFormatList,
|
remote_conn_id: i32,
|
||||||
|
format_list: Vec<(i32, String)>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
// do not check msgFlags for now
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let num_formats = data.formats.len() as UINT32;
|
let num_formats = format_list.len() as UINT32;
|
||||||
let mut formats = data
|
let mut formats = format_list
|
||||||
.formats
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|format| {
|
.map(|format| {
|
||||||
if format.format.is_empty() {
|
if format.1.is_empty() {
|
||||||
CLIPRDR_FORMAT {
|
CLIPRDR_FORMAT {
|
||||||
formatId: format.id as UINT32,
|
formatId: format.0 as UINT32,
|
||||||
formatName: 0 as *mut _,
|
formatName: 0 as *mut _,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let n = match CString::new(format.format) {
|
let n = match CString::new(format.1) {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(_) => CString::new("").unwrap(),
|
Err(_) => CString::new("").unwrap(),
|
||||||
};
|
};
|
||||||
CLIPRDR_FORMAT {
|
CLIPRDR_FORMAT {
|
||||||
formatId: format.id as UINT32,
|
formatId: format.0 as UINT32,
|
||||||
formatName: n.into_raw(),
|
formatName: n.into_raw(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<CLIPRDR_FORMAT>>();
|
.collect::<Vec<CLIPRDR_FORMAT>>();
|
||||||
|
|
||||||
let server_conn_id = if conn_id.server_conn_id != 0 {
|
|
||||||
conn_id.server_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.server_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let remote_conn_id = if conn_id.remote_conn_id != 0 {
|
|
||||||
conn_id.remote_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.remote_conn_id as UINT32
|
|
||||||
};
|
|
||||||
|
|
||||||
let format_list = CLIPRDR_FORMAT_LIST {
|
let format_list = CLIPRDR_FORMAT_LIST {
|
||||||
serverConnID: server_conn_id,
|
serverConnID: server_conn_id as UINT32,
|
||||||
remoteConnID: remote_conn_id,
|
remoteConnID: remote_conn_id as UINT32,
|
||||||
msgType: 0 as UINT16,
|
msgType: 0 as UINT16,
|
||||||
msgFlags: 0 as UINT16,
|
msgFlags: 0 as UINT16,
|
||||||
dataLen: 0 as UINT32,
|
dataLen: 0 as UINT32,
|
||||||
@ -146,28 +309,18 @@ fn server_format_list(
|
|||||||
ret as u32
|
ret as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn server_format_list_response(
|
pub fn server_format_list_response(
|
||||||
context: &mut Box<CliprdrClientContext>,
|
context: &mut Box<CliprdrClientContext>,
|
||||||
conn_id: ConnID,
|
server_conn_id: i32,
|
||||||
data: CliprdrServerFormatListResponse,
|
remote_conn_id: i32,
|
||||||
|
msg_flags: i32,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let server_conn_id = if conn_id.server_conn_id != 0 {
|
|
||||||
conn_id.server_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.server_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let remote_conn_id = if conn_id.remote_conn_id != 0 {
|
|
||||||
conn_id.remote_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.remote_conn_id as UINT32
|
|
||||||
};
|
|
||||||
|
|
||||||
let format_list_response = CLIPRDR_FORMAT_LIST_RESPONSE {
|
let format_list_response = CLIPRDR_FORMAT_LIST_RESPONSE {
|
||||||
serverConnID: server_conn_id,
|
serverConnID: server_conn_id as UINT32,
|
||||||
remoteConnID: remote_conn_id,
|
remoteConnID: remote_conn_id as UINT32,
|
||||||
msgType: 0 as UINT16,
|
msgType: 0 as UINT16,
|
||||||
msgFlags: data.msg_flags as UINT16,
|
msgFlags: msg_flags as UINT16,
|
||||||
dataLen: 0 as UINT32,
|
dataLen: 0 as UINT32,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -177,59 +330,41 @@ fn server_format_list_response(
|
|||||||
ret as u32
|
ret as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn server_format_data_request(
|
pub fn server_format_data_request(
|
||||||
context: &mut Box<CliprdrClientContext>,
|
context: &mut Box<CliprdrClientContext>,
|
||||||
conn_id: ConnID,
|
server_conn_id: i32,
|
||||||
data: CliprdrServerFormatDataRequest,
|
remote_conn_id: i32,
|
||||||
|
requested_format_id: i32,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let server_conn_id = if conn_id.server_conn_id != 0 {
|
|
||||||
conn_id.server_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.server_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let remote_conn_id = if conn_id.remote_conn_id != 0 {
|
|
||||||
conn_id.remote_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.remote_conn_id as UINT32
|
|
||||||
};
|
|
||||||
|
|
||||||
let format_data_request = CLIPRDR_FORMAT_DATA_REQUEST {
|
let format_data_request = CLIPRDR_FORMAT_DATA_REQUEST {
|
||||||
serverConnID: server_conn_id,
|
serverConnID: server_conn_id as UINT32,
|
||||||
remoteConnID: remote_conn_id,
|
remoteConnID: remote_conn_id as UINT32,
|
||||||
msgType: 0 as UINT16,
|
msgType: 0 as UINT16,
|
||||||
msgFlags: 0 as UINT16,
|
msgFlags: 0 as UINT16,
|
||||||
dataLen: 0 as UINT32,
|
dataLen: 0 as UINT32,
|
||||||
requestedFormatId: data.requested_format_id as UINT32,
|
requestedFormatId: requested_format_id as UINT32,
|
||||||
};
|
};
|
||||||
let ret =
|
let ret =
|
||||||
((**context).ServerFormatDataRequest.unwrap())(&mut (**context), &format_data_request);
|
((**context).ServerFormatDataRequest.unwrap())(&mut (**context), &format_data_request);
|
||||||
ret as u32
|
ret as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn server_format_data_response(
|
pub fn server_format_data_response(
|
||||||
context: &mut Box<CliprdrClientContext>,
|
context: &mut Box<CliprdrClientContext>,
|
||||||
conn_id: ConnID,
|
server_conn_id: i32,
|
||||||
mut data: CliprdrServerFormatDataResponse,
|
remote_conn_id: i32,
|
||||||
|
msg_flags: i32,
|
||||||
|
mut format_data: Vec<u8>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let server_conn_id = if conn_id.server_conn_id != 0 {
|
|
||||||
conn_id.server_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.server_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let remote_conn_id = if conn_id.remote_conn_id != 0 {
|
|
||||||
conn_id.remote_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.remote_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let format_data_response = CLIPRDR_FORMAT_DATA_RESPONSE {
|
let format_data_response = CLIPRDR_FORMAT_DATA_RESPONSE {
|
||||||
serverConnID: server_conn_id,
|
serverConnID: server_conn_id as UINT32,
|
||||||
remoteConnID: remote_conn_id,
|
remoteConnID: remote_conn_id as UINT32,
|
||||||
msgType: 0 as UINT16,
|
msgType: 0 as UINT16,
|
||||||
msgFlags: data.msg_flags as UINT16,
|
msgFlags: msg_flags as UINT16,
|
||||||
dataLen: data.format_data.len() as UINT32,
|
dataLen: format_data.len() as UINT32,
|
||||||
requestedFormatData: data.format_data.as_mut_ptr(),
|
requestedFormatData: format_data.as_mut_ptr(),
|
||||||
};
|
};
|
||||||
let ret = ((**context).ServerFormatDataResponse.unwrap())(
|
let ret = ((**context).ServerFormatDataResponse.unwrap())(
|
||||||
&mut (**context),
|
&mut (**context),
|
||||||
@ -238,36 +373,34 @@ fn server_format_data_response(
|
|||||||
ret as u32
|
ret as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn server_file_contents_request(
|
pub fn server_file_contents_request(
|
||||||
context: &mut Box<CliprdrClientContext>,
|
context: &mut Box<CliprdrClientContext>,
|
||||||
conn_id: ConnID,
|
server_conn_id: i32,
|
||||||
data: CliprdrFileContentsRequest,
|
remote_conn_id: i32,
|
||||||
|
stream_id: i32,
|
||||||
|
list_index: i32,
|
||||||
|
dw_flags: i32,
|
||||||
|
n_position_low: i32,
|
||||||
|
n_position_high: i32,
|
||||||
|
cb_requested: i32,
|
||||||
|
have_clip_data_id: bool,
|
||||||
|
clip_data_id: i32,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let server_conn_id = if conn_id.server_conn_id != 0 {
|
|
||||||
conn_id.server_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.server_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let remote_conn_id = if conn_id.remote_conn_id != 0 {
|
|
||||||
conn_id.remote_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.remote_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let file_contents_request = CLIPRDR_FILE_CONTENTS_REQUEST {
|
let file_contents_request = CLIPRDR_FILE_CONTENTS_REQUEST {
|
||||||
serverConnID: server_conn_id,
|
serverConnID: server_conn_id as UINT32,
|
||||||
remoteConnID: remote_conn_id,
|
remoteConnID: remote_conn_id as UINT32,
|
||||||
msgType: 0 as UINT16,
|
msgType: 0 as UINT16,
|
||||||
msgFlags: 0 as UINT16,
|
msgFlags: 0 as UINT16,
|
||||||
dataLen: 0 as UINT32,
|
dataLen: 0 as UINT32,
|
||||||
streamId: data.stream_id as UINT32,
|
streamId: stream_id as UINT32,
|
||||||
listIndex: data.list_index as UINT32,
|
listIndex: list_index as UINT32,
|
||||||
dwFlags: data.dw_flags as UINT32,
|
dwFlags: dw_flags as UINT32,
|
||||||
nPositionLow: data.n_position_low as UINT32,
|
nPositionLow: n_position_low as UINT32,
|
||||||
nPositionHigh: data.n_position_high as UINT32,
|
nPositionHigh: n_position_high as UINT32,
|
||||||
cbRequested: data.cb_requested as UINT32,
|
cbRequested: cb_requested as UINT32,
|
||||||
haveClipDataId: if data.have_clip_data_id { TRUE } else { FALSE },
|
haveClipDataId: if have_clip_data_id { TRUE } else { FALSE },
|
||||||
clipDataId: data.clip_data_id as UINT32,
|
clipDataId: clip_data_id as UINT32,
|
||||||
};
|
};
|
||||||
let ret = ((**context).ServerFileContentsRequest.unwrap())(
|
let ret = ((**context).ServerFileContentsRequest.unwrap())(
|
||||||
&mut (**context),
|
&mut (**context),
|
||||||
@ -276,31 +409,24 @@ fn server_file_contents_request(
|
|||||||
ret as u32
|
ret as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn server_file_contents_response(
|
pub fn server_file_contents_response(
|
||||||
context: &mut Box<CliprdrClientContext>,
|
context: &mut Box<CliprdrClientContext>,
|
||||||
conn_id: ConnID,
|
server_conn_id: i32,
|
||||||
mut data: CliprdrFileContentsResponse,
|
remote_conn_id: i32,
|
||||||
|
msg_flags: i32,
|
||||||
|
stream_id: i32,
|
||||||
|
mut requested_data: Vec<u8>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let server_conn_id = if conn_id.server_conn_id != 0 {
|
|
||||||
conn_id.server_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.server_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let remote_conn_id = if conn_id.remote_conn_id != 0 {
|
|
||||||
conn_id.remote_conn_id as UINT32
|
|
||||||
} else {
|
|
||||||
data.remote_conn_id as UINT32
|
|
||||||
};
|
|
||||||
let file_contents_response = CLIPRDR_FILE_CONTENTS_RESPONSE {
|
let file_contents_response = CLIPRDR_FILE_CONTENTS_RESPONSE {
|
||||||
serverConnID: server_conn_id,
|
serverConnID: server_conn_id as UINT32,
|
||||||
remoteConnID: remote_conn_id,
|
remoteConnID: remote_conn_id as UINT32,
|
||||||
msgType: 0 as UINT16,
|
msgType: 0 as UINT16,
|
||||||
msgFlags: data.msg_flags as UINT16,
|
msgFlags: msg_flags as UINT16,
|
||||||
dataLen: 4 + data.requested_data.len() as UINT32,
|
dataLen: 4 + requested_data.len() as UINT32,
|
||||||
streamId: data.stream_id as UINT32,
|
streamId: stream_id as UINT32,
|
||||||
cbRequested: data.requested_data.len() as UINT32,
|
cbRequested: requested_data.len() as UINT32,
|
||||||
requestedData: data.requested_data.as_mut_ptr(),
|
requestedData: requested_data.as_mut_ptr(),
|
||||||
};
|
};
|
||||||
let ret = ((**context).ServerFileContentsResponse.unwrap())(
|
let ret = ((**context).ServerFileContentsResponse.unwrap())(
|
||||||
&mut (**context),
|
&mut (**context),
|
||||||
@ -310,10 +436,14 @@ fn server_file_contents_response(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_cliprdr_context(enable_files: bool, enable_others: bool) -> ResultType<Box<CliprdrClientContext>> {
|
pub fn create_cliprdr_context(
|
||||||
|
enable_files: bool,
|
||||||
|
enable_others: bool,
|
||||||
|
) -> ResultType<Box<CliprdrClientContext>> {
|
||||||
Ok(CliprdrClientContext::create(
|
Ok(CliprdrClientContext::create(
|
||||||
enable_files,
|
enable_files,
|
||||||
enable_others,
|
enable_others,
|
||||||
|
Some(check_enabled),
|
||||||
Some(client_format_list),
|
Some(client_format_list),
|
||||||
Some(client_format_list_response),
|
Some(client_format_list_response),
|
||||||
Some(client_format_data_request),
|
Some(client_format_data_request),
|
||||||
@ -323,23 +453,54 @@ pub fn create_cliprdr_context(enable_files: bool, enable_others: bool) -> Result
|
|||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn check_enabled(server_conn_id: UINT32, remote_conn_id: UINT32) -> BOOL {
|
||||||
|
let lock = CLIP_CONN_ENABLED.lock().unwrap();
|
||||||
|
if server_conn_id == 0 && remote_conn_id == 0 {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut server_conn_enabled = false;
|
||||||
|
if server_conn_id != 0 {
|
||||||
|
if let Some(true) = lock.server_conn_enabled.get(&(server_conn_id as i32)) {
|
||||||
|
server_conn_enabled = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
server_conn_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let mut remote_conn_enabled = false;
|
||||||
|
// remote connection is always enabled
|
||||||
|
// if remote_conn_id != 0 {
|
||||||
|
// if let Some(true) = lock.remote_conn_enabled.get(&(remote_conn_id as i32)) {
|
||||||
|
// remote_conn_enabled = true;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// remote_conn_enabled = true;
|
||||||
|
// }
|
||||||
|
let remote_conn_enabled = true;
|
||||||
|
|
||||||
|
if server_conn_enabled && remote_conn_enabled {
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn client_format_list(
|
extern "C" fn client_format_list(
|
||||||
_context: *mut CliprdrClientContext,
|
_context: *mut CliprdrClientContext,
|
||||||
format_list: *const CLIPRDR_FORMAT_LIST,
|
clip_format_list: *const CLIPRDR_FORMAT_LIST,
|
||||||
) -> UINT {
|
) -> UINT {
|
||||||
log::debug!("client_format_list called");
|
log::debug!("client_format_list called");
|
||||||
|
|
||||||
let mut data = CliprdrServerFormatList::default();
|
let server_conn_id;
|
||||||
|
let remote_conn_id;
|
||||||
|
let mut format_list: Vec<(i32, String)> = Vec::new();
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut i = 0u32;
|
let mut i = 0u32;
|
||||||
while i < (*format_list).numFormats {
|
while i < (*clip_format_list).numFormats {
|
||||||
let format_data = &(*(*format_list).formats.offset(i as isize));
|
let format_data = &(*(*clip_format_list).formats.offset(i as isize));
|
||||||
if format_data.formatName.is_null() {
|
if format_data.formatName.is_null() {
|
||||||
data.formats.push(CliprdrFormat {
|
format_list.push((format_data.formatId as i32, "".to_owned()));
|
||||||
id: format_data.formatId as i32,
|
|
||||||
format: "".to_owned(),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
let format_name = CStr::from_ptr(format_data.formatName).to_str();
|
let format_name = CStr::from_ptr(format_data.formatName).to_str();
|
||||||
let format_name = match format_name {
|
let format_name = match format_name {
|
||||||
@ -349,30 +510,25 @@ extern "C" fn client_format_list(
|
|||||||
"".to_owned()
|
"".to_owned()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
data.formats.push(CliprdrFormat {
|
format_list.push((format_data.formatId as i32, format_name));
|
||||||
id: format_data.formatId as i32,
|
|
||||||
format: format_name,
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// log::debug!("format list item {}: format id: {}, format name: {}", i, format_data.formatId, &format_name);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
server_conn_id = (*clip_format_list).serverConnID as i32;
|
||||||
data.server_conn_id = (*format_list).serverConnID as i32;
|
remote_conn_id = (*clip_format_list).remoteConnID as i32;
|
||||||
data.remote_conn_id = (*format_list).remoteConnID as i32;
|
|
||||||
}
|
}
|
||||||
let conn_id = ConnID {
|
let conn_id = ConnID {
|
||||||
server_conn_id: data.server_conn_id as u32,
|
server_conn_id: server_conn_id as u32,
|
||||||
remote_conn_id: data.remote_conn_id as u32,
|
remote_conn_id: remote_conn_id as u32,
|
||||||
|
};
|
||||||
|
let data = ClipbaordFile::ServerFormatList {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
format_list,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut msg = Message::new();
|
|
||||||
let mut cliprdr = Cliprdr::new();
|
|
||||||
cliprdr.set_format_list(data);
|
|
||||||
msg.set_cliprdr(cliprdr);
|
|
||||||
|
|
||||||
// no need to handle result here
|
// no need to handle result here
|
||||||
MSG_CHANNEL_CLIENT.0.send((conn_id, msg)).unwrap();
|
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@ -383,23 +539,25 @@ extern "C" fn client_format_list_response(
|
|||||||
) -> UINT {
|
) -> UINT {
|
||||||
log::debug!("client_format_list_response called");
|
log::debug!("client_format_list_response called");
|
||||||
|
|
||||||
let mut data = CliprdrServerFormatListResponse::default();
|
let server_conn_id;
|
||||||
|
let remote_conn_id;
|
||||||
|
let msg_flags;
|
||||||
unsafe {
|
unsafe {
|
||||||
data.server_conn_id = (*format_list_response).serverConnID as i32;
|
server_conn_id = (*format_list_response).serverConnID as i32;
|
||||||
data.remote_conn_id = (*format_list_response).remoteConnID as i32;
|
remote_conn_id = (*format_list_response).remoteConnID as i32;
|
||||||
data.msg_flags = (*format_list_response).msgFlags as i32;
|
msg_flags = (*format_list_response).msgFlags as i32;
|
||||||
}
|
}
|
||||||
let conn_id = ConnID {
|
let conn_id = ConnID {
|
||||||
server_conn_id: data.server_conn_id as u32,
|
server_conn_id: server_conn_id as u32,
|
||||||
remote_conn_id: data.remote_conn_id as u32,
|
remote_conn_id: remote_conn_id as u32,
|
||||||
|
};
|
||||||
|
let data = ClipbaordFile::ServerFormatListResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut msg = Message::new();
|
|
||||||
let mut cliprdr = Cliprdr::new();
|
|
||||||
cliprdr.set_format_list_response(data);
|
|
||||||
msg.set_cliprdr(cliprdr);
|
|
||||||
// no need to handle result here
|
// no need to handle result here
|
||||||
MSG_CHANNEL_CLIENT.0.send((conn_id, msg)).unwrap();
|
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@ -410,23 +568,25 @@ extern "C" fn client_format_data_request(
|
|||||||
) -> UINT {
|
) -> UINT {
|
||||||
log::debug!("client_format_data_request called");
|
log::debug!("client_format_data_request called");
|
||||||
|
|
||||||
let mut data = CliprdrServerFormatDataRequest::default();
|
let server_conn_id;
|
||||||
|
let remote_conn_id;
|
||||||
|
let requested_format_id;
|
||||||
unsafe {
|
unsafe {
|
||||||
data.server_conn_id = (*format_data_request).serverConnID as i32;
|
server_conn_id = (*format_data_request).serverConnID as i32;
|
||||||
data.remote_conn_id = (*format_data_request).remoteConnID as i32;
|
remote_conn_id = (*format_data_request).remoteConnID as i32;
|
||||||
data.requested_format_id = (*format_data_request).requestedFormatId as i32;
|
requested_format_id = (*format_data_request).requestedFormatId as i32;
|
||||||
}
|
}
|
||||||
let conn_id = ConnID {
|
let conn_id = ConnID {
|
||||||
server_conn_id: data.server_conn_id as u32,
|
server_conn_id: server_conn_id as u32,
|
||||||
remote_conn_id: data.remote_conn_id as u32,
|
remote_conn_id: remote_conn_id as u32,
|
||||||
|
};
|
||||||
|
let data = ClipbaordFile::ServerFormatDataRequest {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
requested_format_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut msg = Message::new();
|
|
||||||
let mut cliprdr = Cliprdr::new();
|
|
||||||
cliprdr.set_format_data_request(data);
|
|
||||||
msg.set_cliprdr(cliprdr);
|
|
||||||
// no need to handle result here
|
// no need to handle result here
|
||||||
MSG_CHANNEL_CLIENT.0.send((conn_id, msg)).unwrap();
|
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@ -437,28 +597,36 @@ extern "C" fn client_format_data_response(
|
|||||||
) -> UINT {
|
) -> UINT {
|
||||||
log::debug!("client_format_data_response called");
|
log::debug!("client_format_data_response called");
|
||||||
|
|
||||||
let mut data = CliprdrServerFormatDataResponse::default();
|
let server_conn_id;
|
||||||
|
let remote_conn_id;
|
||||||
|
let msg_flags;
|
||||||
|
let format_data;
|
||||||
unsafe {
|
unsafe {
|
||||||
data.server_conn_id = (*format_data_response).serverConnID as i32;
|
server_conn_id = (*format_data_response).serverConnID as i32;
|
||||||
data.remote_conn_id = (*format_data_response).remoteConnID as i32;
|
remote_conn_id = (*format_data_response).remoteConnID as i32;
|
||||||
data.msg_flags = (*format_data_response).msgFlags as i32;
|
msg_flags = (*format_data_response).msgFlags as i32;
|
||||||
data.format_data = std::slice::from_raw_parts(
|
if (*format_data_response).requestedFormatData.is_null() {
|
||||||
|
format_data = Vec::new();
|
||||||
|
} else {
|
||||||
|
format_data = std::slice::from_raw_parts(
|
||||||
(*format_data_response).requestedFormatData,
|
(*format_data_response).requestedFormatData,
|
||||||
(*format_data_response).dataLen as usize,
|
(*format_data_response).dataLen as usize,
|
||||||
)
|
)
|
||||||
.to_vec();
|
.to_vec();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let conn_id = ConnID {
|
let conn_id = ConnID {
|
||||||
server_conn_id: data.server_conn_id as u32,
|
server_conn_id: server_conn_id as u32,
|
||||||
remote_conn_id: data.remote_conn_id as u32,
|
remote_conn_id: remote_conn_id as u32,
|
||||||
|
};
|
||||||
|
let data = ClipbaordFile::ServerFormatDataResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
format_data,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut msg = Message::new();
|
|
||||||
let mut cliprdr = Cliprdr::new();
|
|
||||||
cliprdr.set_format_data_response(data);
|
|
||||||
msg.set_cliprdr(cliprdr);
|
|
||||||
// no need to handle result here
|
// no need to handle result here
|
||||||
MSG_CHANNEL_CLIENT.0.send((conn_id, msg)).unwrap();
|
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@ -479,30 +647,47 @@ extern "C" fn client_file_contents_request(
|
|||||||
// return ERROR_INVALID_PARAMETER;
|
// return ERROR_INVALID_PARAMETER;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let mut data = CliprdrFileContentsRequest::default();
|
let server_conn_id;
|
||||||
|
let remote_conn_id;
|
||||||
|
let stream_id;
|
||||||
|
let list_index;
|
||||||
|
let dw_flags;
|
||||||
|
let n_position_low;
|
||||||
|
let n_position_high;
|
||||||
|
let cb_requested;
|
||||||
|
let have_clip_data_id;
|
||||||
|
let clip_data_id;
|
||||||
unsafe {
|
unsafe {
|
||||||
data.server_conn_id = (*file_contents_request).serverConnID as i32;
|
server_conn_id = (*file_contents_request).serverConnID as i32;
|
||||||
data.remote_conn_id = (*file_contents_request).remoteConnID as i32;
|
remote_conn_id = (*file_contents_request).remoteConnID as i32;
|
||||||
data.stream_id = (*file_contents_request).streamId as i32;
|
stream_id = (*file_contents_request).streamId as i32;
|
||||||
data.list_index = (*file_contents_request).listIndex as i32;
|
list_index = (*file_contents_request).listIndex as i32;
|
||||||
data.dw_flags = (*file_contents_request).dwFlags as i32;
|
dw_flags = (*file_contents_request).dwFlags as i32;
|
||||||
data.n_position_low = (*file_contents_request).nPositionLow as i32;
|
n_position_low = (*file_contents_request).nPositionLow as i32;
|
||||||
data.n_position_high = (*file_contents_request).nPositionHigh as i32;
|
n_position_high = (*file_contents_request).nPositionHigh as i32;
|
||||||
data.cb_requested = (*file_contents_request).cbRequested as i32;
|
cb_requested = (*file_contents_request).cbRequested as i32;
|
||||||
data.have_clip_data_id = (*file_contents_request).haveClipDataId == TRUE;
|
have_clip_data_id = (*file_contents_request).haveClipDataId == TRUE;
|
||||||
data.clip_data_id = (*file_contents_request).clipDataId as i32;
|
clip_data_id = (*file_contents_request).clipDataId as i32;
|
||||||
}
|
}
|
||||||
let conn_id = ConnID {
|
let conn_id = ConnID {
|
||||||
server_conn_id: data.server_conn_id as u32,
|
server_conn_id: server_conn_id as u32,
|
||||||
remote_conn_id: data.remote_conn_id as u32,
|
remote_conn_id: remote_conn_id as u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut msg = Message::new();
|
let data = ClipbaordFile::FileContentsRequest {
|
||||||
let mut cliprdr = Cliprdr::new();
|
server_conn_id,
|
||||||
cliprdr.set_file_contents_request(data);
|
remote_conn_id,
|
||||||
msg.set_cliprdr(cliprdr);
|
stream_id,
|
||||||
|
list_index,
|
||||||
|
dw_flags,
|
||||||
|
n_position_low,
|
||||||
|
n_position_high,
|
||||||
|
cb_requested,
|
||||||
|
have_clip_data_id,
|
||||||
|
clip_data_id,
|
||||||
|
};
|
||||||
// no need to handle result here
|
// no need to handle result here
|
||||||
MSG_CHANNEL_CLIENT.0.send((conn_id, msg)).unwrap();
|
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
@ -513,29 +698,40 @@ extern "C" fn client_file_contents_response(
|
|||||||
) -> UINT {
|
) -> UINT {
|
||||||
log::debug!("client_file_contents_response called");
|
log::debug!("client_file_contents_response called");
|
||||||
|
|
||||||
let mut data = CliprdrFileContentsResponse::default();
|
let server_conn_id;
|
||||||
|
let remote_conn_id;
|
||||||
|
let msg_flags;
|
||||||
|
let stream_id;
|
||||||
|
let requested_data;
|
||||||
unsafe {
|
unsafe {
|
||||||
data.server_conn_id = (*file_contents_response).serverConnID as i32;
|
server_conn_id = (*file_contents_response).serverConnID as i32;
|
||||||
data.remote_conn_id = (*file_contents_response).remoteConnID as i32;
|
remote_conn_id = (*file_contents_response).remoteConnID as i32;
|
||||||
data.msg_flags = (*file_contents_response).msgFlags as i32;
|
msg_flags = (*file_contents_response).msgFlags as i32;
|
||||||
data.stream_id = (*file_contents_response).streamId as i32;
|
stream_id = (*file_contents_response).streamId as i32;
|
||||||
data.requested_data = std::slice::from_raw_parts(
|
if (*file_contents_response).requestedData.is_null() {
|
||||||
|
requested_data = Vec::new();
|
||||||
|
} else {
|
||||||
|
requested_data = std::slice::from_raw_parts(
|
||||||
(*file_contents_response).requestedData,
|
(*file_contents_response).requestedData,
|
||||||
(*file_contents_response).cbRequested as usize,
|
(*file_contents_response).cbRequested as usize,
|
||||||
)
|
)
|
||||||
.to_vec();
|
.to_vec();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let conn_id = ConnID {
|
let conn_id = ConnID {
|
||||||
server_conn_id: data.server_conn_id as u32,
|
server_conn_id: server_conn_id as u32,
|
||||||
remote_conn_id: data.remote_conn_id as u32,
|
remote_conn_id: remote_conn_id as u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut msg = Message::new();
|
let data = ClipbaordFile::FileContentsResponse {
|
||||||
let mut cliprdr = Cliprdr::new();
|
server_conn_id,
|
||||||
cliprdr.set_file_contents_response(data);
|
remote_conn_id,
|
||||||
msg.set_cliprdr(cliprdr);
|
msg_flags,
|
||||||
|
stream_id,
|
||||||
|
requested_data,
|
||||||
|
};
|
||||||
// no need to handle result here
|
// no need to handle result here
|
||||||
MSG_CHANNEL_CLIENT.0.send((conn_id, msg)).unwrap();
|
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|||||||
@ -228,6 +228,8 @@ struct wf_clipboard
|
|||||||
HANDLE response_data_event;
|
HANDLE response_data_event;
|
||||||
|
|
||||||
LPDATAOBJECT data_obj;
|
LPDATAOBJECT data_obj;
|
||||||
|
HANDLE data_obj_mutex;
|
||||||
|
|
||||||
ULONG req_fsize;
|
ULONG req_fsize;
|
||||||
char *req_fdata;
|
char *req_fdata;
|
||||||
HANDLE req_fevent;
|
HANDLE req_fevent;
|
||||||
@ -252,6 +254,7 @@ typedef struct wf_clipboard wfClipboard;
|
|||||||
|
|
||||||
BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr);
|
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);
|
||||||
|
|
||||||
static BOOL wf_create_file_obj(UINT32 serverConnID, UINT32 remoteConnID, wfClipboard *cliprdrrdr, IDataObject **ppDataObject);
|
static BOOL wf_create_file_obj(UINT32 serverConnID, UINT32 remoteConnID, wfClipboard *cliprdrrdr, IDataObject **ppDataObject);
|
||||||
static void wf_destroy_file_obj(IDataObject *instance);
|
static void wf_destroy_file_obj(IDataObject *instance);
|
||||||
@ -682,6 +685,10 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
|
|||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
clipboard = (wfClipboard *)instance->m_pData;
|
clipboard = (wfClipboard *)instance->m_pData;
|
||||||
|
if (!clipboard->context->CheckEnabled(instance->m_serverConnID, instance->m_remoteConnID))
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -699,7 +706,13 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
|
|||||||
// DWORD remote_format_id = get_remote_format_id(clipboard, instance->m_pFormatEtc[idx].cfFormat);
|
// DWORD remote_format_id = get_remote_format_id(clipboard, instance->m_pFormatEtc[idx].cfFormat);
|
||||||
// FIXME: origin code may be failed here???
|
// FIXME: origin code may be failed here???
|
||||||
if (cliprdr_send_data_request(instance->m_serverConnID, instance->m_remoteConnID, clipboard, instance->m_pFormatEtc[idx].cfFormat) != 0)
|
if (cliprdr_send_data_request(instance->m_serverConnID, instance->m_remoteConnID, clipboard, instance->m_pFormatEtc[idx].cfFormat) != 0)
|
||||||
|
{
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
if (!clipboard->hmem)
|
||||||
|
{
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
pMedium->hGlobal = clipboard->hmem; /* points to a FILEGROUPDESCRIPTOR structure */
|
pMedium->hGlobal = clipboard->hmem; /* points to a FILEGROUPDESCRIPTOR structure */
|
||||||
/* GlobalLock returns a pointer to the first byte of the memory block,
|
/* GlobalLock returns a pointer to the first byte of the memory block,
|
||||||
@ -1355,7 +1368,16 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard)
|
|||||||
/* Ignore if other app is holding clipboard */
|
/* Ignore if other app is holding clipboard */
|
||||||
if (try_open_clipboard(clipboard->hwnd))
|
if (try_open_clipboard(clipboard->hwnd))
|
||||||
{
|
{
|
||||||
|
// If current process is running as service with SYSTEM user.
|
||||||
|
// Clipboard api works fine for text, but copying files works no good.
|
||||||
|
// GetLastError() returns various error codes
|
||||||
count = CountClipboardFormats();
|
count = CountClipboardFormats();
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
CloseClipboard();
|
||||||
|
return CHANNEL_RC_NULL_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
numFormats = (UINT32)count;
|
numFormats = (UINT32)count;
|
||||||
formats = (CLIPRDR_FORMAT *)calloc(numFormats, sizeof(CLIPRDR_FORMAT));
|
formats = (CLIPRDR_FORMAT *)calloc(numFormats, sizeof(CLIPRDR_FORMAT));
|
||||||
|
|
||||||
@ -1377,7 +1399,7 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (formatId = EnumClipboardFormats(formatId))
|
while (formatId = EnumClipboardFormats(formatId) && index < numFormats)
|
||||||
formats[index++].formatId = formatId;
|
formats[index++].formatId = formatId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1395,6 +1417,10 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard)
|
|||||||
{
|
{
|
||||||
formats[index].formatName = _strdup(formatName);
|
formats[index].formatName = _strdup(formatName);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
formats[index].formatName = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1408,11 +1434,16 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard)
|
|||||||
rc = clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
rc = clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
||||||
|
|
||||||
for (index = 0; index < numFormats; index++)
|
for (index = 0; index < numFormats; index++)
|
||||||
|
{
|
||||||
|
if (formats[index].formatName != NULL)
|
||||||
|
{
|
||||||
free(formats[index].formatName);
|
free(formats[index].formatName);
|
||||||
|
formats[index].formatName = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
free(formats);
|
free(formats);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
// return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT cliprdr_send_data_request(UINT32 serverConnID, UINT32 remoteConnID, wfClipboard *clipboard, UINT32 formatId)
|
static UINT cliprdr_send_data_request(UINT32 serverConnID, UINT32 remoteConnID, wfClipboard *clipboard, UINT32 formatId)
|
||||||
@ -1431,13 +1462,56 @@ static UINT cliprdr_send_data_request(UINT32 serverConnID, UINT32 remoteConnID,
|
|||||||
formatDataRequest.requestedFormatId = remoteFormatId;
|
formatDataRequest.requestedFormatId = remoteFormatId;
|
||||||
clipboard->requestedFormatId = formatId;
|
clipboard->requestedFormatId = formatId;
|
||||||
rc = clipboard->context->ClientFormatDataRequest(clipboard->context, &formatDataRequest);
|
rc = clipboard->context->ClientFormatDataRequest(clipboard->context, &formatDataRequest);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (WaitForSingleObject(clipboard->response_data_event, INFINITE) != WAIT_OBJECT_0)
|
// with default 3min timeout
|
||||||
|
for (int i = 0; i < 20 * 60 * 3; i++)
|
||||||
|
{
|
||||||
|
DWORD waitRes = WaitForSingleObject(clipboard->response_data_event, 50);
|
||||||
|
if (waitRes == WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
if (clipboard->context->CheckEnabled(serverConnID, remoteConnID))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitRes != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ResetEvent(clipboard->response_data_event))
|
||||||
|
{
|
||||||
|
// NOTE: critical error here, crash may be better
|
||||||
rc = ERROR_INTERNAL_ERROR;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
else if (!ResetEvent(clipboard->response_data_event))
|
}
|
||||||
|
|
||||||
|
if (!clipboard->hmem)
|
||||||
|
{
|
||||||
rc = ERROR_INTERNAL_ERROR;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clipboard->hmem)
|
||||||
|
{
|
||||||
|
if (!ResetEvent(clipboard->response_data_event))
|
||||||
|
{
|
||||||
|
// NOTE: critical error here, crash may be better
|
||||||
|
}
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 serverConnID, UINT32 remoteConnID, const void *streamid, ULONG index,
|
UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 serverConnID, UINT32 remoteConnID, const void *streamid, ULONG index,
|
||||||
@ -1461,29 +1535,81 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 serverConn
|
|||||||
fileContentsRequest.clipDataId = 0;
|
fileContentsRequest.clipDataId = 0;
|
||||||
fileContentsRequest.msgFlags = 0;
|
fileContentsRequest.msgFlags = 0;
|
||||||
rc = clipboard->context->ClientFileContentsRequest(clipboard->context, &fileContentsRequest);
|
rc = clipboard->context->ClientFileContentsRequest(clipboard->context, &fileContentsRequest);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (WaitForSingleObject(clipboard->req_fevent, INFINITE) != WAIT_OBJECT_0)
|
// with default 3min timeout
|
||||||
|
for (int i = 0; i < 20 * 60 * 3; i++)
|
||||||
|
{
|
||||||
|
DWORD waitRes = WaitForSingleObject(clipboard->req_fevent, 50);
|
||||||
|
if (waitRes == WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
if (clipboard->context->CheckEnabled(serverConnID, remoteConnID))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitRes != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ResetEvent(clipboard->req_fevent))
|
||||||
|
{
|
||||||
|
// NOTE: critical error here, crash may be better
|
||||||
rc = ERROR_INTERNAL_ERROR;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
else if (!ResetEvent(clipboard->req_fevent))
|
}
|
||||||
|
if (!clipboard->req_fdata)
|
||||||
|
{
|
||||||
rc = ERROR_INTERNAL_ERROR;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clipboard->req_fdata)
|
||||||
|
{
|
||||||
|
if (!ResetEvent(clipboard->req_fevent))
|
||||||
|
{
|
||||||
|
// NOTE: critical error here, crash may be better
|
||||||
|
}
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT cliprdr_send_response_filecontents(wfClipboard *clipboard, UINT32 serverConnID, UINT32 remoteConnID, UINT32 streamId, UINT32 size,
|
static UINT cliprdr_send_response_filecontents(
|
||||||
|
wfClipboard *clipboard,
|
||||||
|
UINT32 serverConnID,
|
||||||
|
UINT32 remoteConnID,
|
||||||
|
UINT16 msgFlags,
|
||||||
|
UINT32 streamId,
|
||||||
|
UINT32 size,
|
||||||
BYTE *data)
|
BYTE *data)
|
||||||
{
|
{
|
||||||
CLIPRDR_FILE_CONTENTS_RESPONSE fileContentsResponse;
|
CLIPRDR_FILE_CONTENTS_RESPONSE fileContentsResponse;
|
||||||
|
|
||||||
if (!clipboard || !clipboard->context || !clipboard->context->ClientFileContentsResponse)
|
if (!clipboard || !clipboard->context || !clipboard->context->ClientFileContentsResponse)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
data = NULL;
|
||||||
|
size = 0;
|
||||||
|
msgFlags = CB_RESPONSE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
fileContentsResponse.serverConnID = serverConnID;
|
fileContentsResponse.serverConnID = serverConnID;
|
||||||
fileContentsResponse.remoteConnID = remoteConnID;
|
fileContentsResponse.remoteConnID = remoteConnID;
|
||||||
fileContentsResponse.streamId = streamId;
|
fileContentsResponse.streamId = streamId;
|
||||||
fileContentsResponse.cbRequested = size;
|
fileContentsResponse.cbRequested = size;
|
||||||
fileContentsResponse.requestedData = data;
|
fileContentsResponse.requestedData = data;
|
||||||
fileContentsResponse.msgFlags = CB_RESPONSE_OK;
|
fileContentsResponse.msgFlags = msgFlags;
|
||||||
return clipboard->context->ClientFileContentsResponse(clipboard->context,
|
return clipboard->context->ClientFileContentsResponse(clipboard->context,
|
||||||
&fileContentsResponse);
|
&fileContentsResponse);
|
||||||
}
|
}
|
||||||
@ -1522,7 +1648,6 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
|||||||
|
|
||||||
case WM_CLIPBOARDUPDATE:
|
case WM_CLIPBOARDUPDATE:
|
||||||
DEBUG_CLIPRDR("info: WM_CLIPBOARDUPDATE");
|
DEBUG_CLIPRDR("info: WM_CLIPBOARDUPDATE");
|
||||||
|
|
||||||
// if (clipboard->sync)
|
// if (clipboard->sync)
|
||||||
{
|
{
|
||||||
if ((GetClipboardOwner() != clipboard->hwnd) &&
|
if ((GetClipboardOwner() != clipboard->hwnd) &&
|
||||||
@ -1614,6 +1739,11 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
|||||||
case OLE_SETCLIPBOARD:
|
case OLE_SETCLIPBOARD:
|
||||||
DEBUG_CLIPRDR("info: OLE_SETCLIPBOARD");
|
DEBUG_CLIPRDR("info: OLE_SETCLIPBOARD");
|
||||||
|
|
||||||
|
if (WaitForSingleObject(clipboard->data_obj_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (clipboard->data_obj != NULL)
|
if (clipboard->data_obj != NULL)
|
||||||
{
|
{
|
||||||
wf_destroy_file_obj(clipboard->data_obj);
|
wf_destroy_file_obj(clipboard->data_obj);
|
||||||
@ -1630,6 +1760,11 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
|||||||
}
|
}
|
||||||
free((void *)lParam);
|
free((void *)lParam);
|
||||||
|
|
||||||
|
if (!ReleaseMutex(clipboard->data_obj_mutex))
|
||||||
|
{
|
||||||
|
// critical error!!!
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DELAYED_RENDERING:
|
case DELAYED_RENDERING:
|
||||||
@ -2270,7 +2405,7 @@ static UINT
|
|||||||
wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
||||||
const CLIPRDR_FORMAT_DATA_REQUEST *formatDataRequest)
|
const CLIPRDR_FORMAT_DATA_REQUEST *formatDataRequest)
|
||||||
{
|
{
|
||||||
UINT rc;
|
UINT rc = ERROR_SUCCESS;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
void *buff = NULL;
|
void *buff = NULL;
|
||||||
char *globlemem = NULL;
|
char *globlemem = NULL;
|
||||||
@ -2280,12 +2415,18 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
wfClipboard *clipboard;
|
wfClipboard *clipboard;
|
||||||
|
|
||||||
if (!context || !formatDataRequest)
|
if (!context || !formatDataRequest)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
clipboard = (wfClipboard *)context->custom;
|
clipboard = (wfClipboard *)context->custom;
|
||||||
|
|
||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
requestedFormatId = formatDataRequest->requestedFormatId;
|
requestedFormatId = formatDataRequest->requestedFormatId;
|
||||||
|
|
||||||
@ -2303,7 +2444,10 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
result = OleGetClipboard(&dataObj);
|
result = OleGetClipboard(&dataObj);
|
||||||
|
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
ZeroMemory(&format_etc, sizeof(FORMATETC));
|
ZeroMemory(&format_etc, sizeof(FORMATETC));
|
||||||
ZeroMemory(&stg_medium, sizeof(STGMEDIUM));
|
ZeroMemory(&stg_medium, sizeof(STGMEDIUM));
|
||||||
@ -2316,7 +2460,7 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
|
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DEBUG_CLIPRDR("dataObj->GetData failed.");
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2327,7 +2471,7 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
GlobalUnlock(stg_medium.hGlobal);
|
GlobalUnlock(stg_medium.hGlobal);
|
||||||
ReleaseStgMedium(&stg_medium);
|
ReleaseStgMedium(&stg_medium);
|
||||||
clipboard->nFiles = 0;
|
clipboard->nFiles = 0;
|
||||||
goto exit;
|
goto resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_file_array(clipboard);
|
clear_file_array(clipboard);
|
||||||
@ -2344,7 +2488,6 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
for (p = (char *)((char *)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0;
|
for (p = (char *)((char *)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0;
|
||||||
p += len + 1, clipboard->nFiles++)
|
p += len + 1, clipboard->nFiles++)
|
||||||
{
|
{
|
||||||
@ -2359,7 +2502,7 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
|
|
||||||
GlobalUnlock(stg_medium.hGlobal);
|
GlobalUnlock(stg_medium.hGlobal);
|
||||||
ReleaseStgMedium(&stg_medium);
|
ReleaseStgMedium(&stg_medium);
|
||||||
exit:
|
resp:
|
||||||
size = 4 + clipboard->nFiles * sizeof(FILEDESCRIPTORW);
|
size = 4 + clipboard->nFiles * sizeof(FILEDESCRIPTORW);
|
||||||
groupDsc = (FILEGROUPDESCRIPTORW *)malloc(size);
|
groupDsc = (FILEGROUPDESCRIPTORW *)malloc(size);
|
||||||
|
|
||||||
@ -2377,6 +2520,7 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
IDataObject_Release(dataObj);
|
IDataObject_Release(dataObj);
|
||||||
|
rc = ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2388,26 +2532,50 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context,
|
|||||||
if (!hClipdata)
|
if (!hClipdata)
|
||||||
{
|
{
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
globlemem = (char *)GlobalLock(hClipdata);
|
globlemem = (char *)GlobalLock(hClipdata);
|
||||||
size = (int)GlobalSize(hClipdata);
|
size = (int)GlobalSize(hClipdata);
|
||||||
buff = malloc(size);
|
buff = malloc(size);
|
||||||
CopyMemory(buff, globlemem, size);
|
CopyMemory(buff, globlemem, size);
|
||||||
GlobalUnlock(hClipdata);
|
GlobalUnlock(hClipdata);
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
rc = ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (rc == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
response.msgFlags = CB_RESPONSE_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.msgFlags = CB_RESPONSE_FAIL;
|
||||||
|
}
|
||||||
response.serverConnID = formatDataRequest->serverConnID;
|
response.serverConnID = formatDataRequest->serverConnID;
|
||||||
response.remoteConnID = formatDataRequest->remoteConnID;
|
response.remoteConnID = formatDataRequest->remoteConnID;
|
||||||
response.msgFlags = CB_RESPONSE_OK;
|
|
||||||
response.dataLen = size;
|
response.dataLen = size;
|
||||||
response.requestedFormatData = (BYTE *)buff;
|
response.requestedFormatData = (BYTE *)buff;
|
||||||
rc = clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
|
if (ERROR_SUCCESS != clipboard->context->ClientFormatDataResponse(clipboard->context, &response))
|
||||||
|
{
|
||||||
|
// CAUTION: if failed to send, server will wait a long time
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buff)
|
||||||
|
{
|
||||||
free(buff);
|
free(buff);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2420,32 +2588,48 @@ static UINT
|
|||||||
wf_cliprdr_server_format_data_response(CliprdrClientContext *context,
|
wf_cliprdr_server_format_data_response(CliprdrClientContext *context,
|
||||||
const CLIPRDR_FORMAT_DATA_RESPONSE *formatDataResponse)
|
const CLIPRDR_FORMAT_DATA_RESPONSE *formatDataResponse)
|
||||||
{
|
{
|
||||||
|
UINT rc = ERROR_INTERNAL_ERROR;
|
||||||
BYTE *data;
|
BYTE *data;
|
||||||
HANDLE hMem;
|
HANDLE hMem;
|
||||||
wfClipboard *clipboard;
|
wfClipboard *clipboard;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
if (!context || !formatDataResponse)
|
if (!context || !formatDataResponse)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
if (formatDataResponse->msgFlags != CB_RESPONSE_OK)
|
break;
|
||||||
return E_FAIL;
|
}
|
||||||
|
|
||||||
clipboard = (wfClipboard *)context->custom;
|
clipboard = (wfClipboard *)context->custom;
|
||||||
|
|
||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
clipboard->hmem = NULL;
|
||||||
|
|
||||||
|
if (formatDataResponse->msgFlags != CB_RESPONSE_OK)
|
||||||
|
{
|
||||||
|
// BOOL emptyRes = wf_do_empty_cliprdr((wfClipboard *)context->custom);
|
||||||
|
// (void)emptyRes;
|
||||||
|
rc = E_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
hMem = GlobalAlloc(GMEM_MOVEABLE, formatDataResponse->dataLen);
|
hMem = GlobalAlloc(GMEM_MOVEABLE, formatDataResponse->dataLen);
|
||||||
|
|
||||||
if (!hMem)
|
if (!hMem)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
data = (BYTE *)GlobalLock(hMem);
|
data = (BYTE *)GlobalLock(hMem);
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
GlobalFree(hMem);
|
GlobalFree(hMem);
|
||||||
return ERROR_INTERNAL_ERROR;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(data, formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
|
CopyMemory(data, formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
|
||||||
@ -2453,15 +2637,20 @@ wf_cliprdr_server_format_data_response(CliprdrClientContext *context,
|
|||||||
if (!GlobalUnlock(hMem) && GetLastError())
|
if (!GlobalUnlock(hMem) && GetLastError())
|
||||||
{
|
{
|
||||||
GlobalFree(hMem);
|
GlobalFree(hMem);
|
||||||
return ERROR_INTERNAL_ERROR;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
clipboard->hmem = hMem;
|
clipboard->hmem = hMem;
|
||||||
|
rc = CHANNEL_RC_OK;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
if (!SetEvent(clipboard->response_data_event))
|
if (!SetEvent(clipboard->response_data_event))
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
// CAUTION: critical error here, process will hang up until wait timeout default 3min.
|
||||||
return CHANNEL_RC_OK;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2488,12 +2677,18 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context,
|
|||||||
UINT32 cbRequested;
|
UINT32 cbRequested;
|
||||||
|
|
||||||
if (!context || !fileContentsRequest)
|
if (!context || !fileContentsRequest)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
clipboard = (wfClipboard *)context->custom;
|
clipboard = (wfClipboard *)context->custom;
|
||||||
|
|
||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
cbRequested = fileContentsRequest->cbRequested;
|
cbRequested = fileContentsRequest->cbRequested;
|
||||||
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
|
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
|
||||||
@ -2502,14 +2697,18 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context,
|
|||||||
pData = (BYTE *)calloc(1, cbRequested);
|
pData = (BYTE *)calloc(1, cbRequested);
|
||||||
|
|
||||||
if (!pData)
|
if (!pData)
|
||||||
goto error;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
hRet = OleGetClipboard(&pDataObj);
|
hRet = OleGetClipboard(&pDataObj);
|
||||||
|
|
||||||
if (FAILED(hRet))
|
if (FAILED(hRet))
|
||||||
{
|
{
|
||||||
printf("filecontents: get ole clipboard failed.\n");
|
printf("filecontents: get ole clipboard failed.\n");
|
||||||
goto error;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroMemory(&vFormatEtc, sizeof(FORMATETC));
|
ZeroMemory(&vFormatEtc, sizeof(FORMATETC));
|
||||||
@ -2593,7 +2792,10 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context,
|
|||||||
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
|
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
|
||||||
{
|
{
|
||||||
if (clipboard->nFiles <= fileContentsRequest->listIndex)
|
if (clipboard->nFiles <= fileContentsRequest->listIndex)
|
||||||
goto error;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
*((UINT32 *)&pData[0]) =
|
*((UINT32 *)&pData[0]) =
|
||||||
clipboard->fileDescriptor[fileContentsRequest->listIndex]->nFileSizeLow;
|
clipboard->fileDescriptor[fileContentsRequest->listIndex]->nFileSizeLow;
|
||||||
*((UINT32 *)&pData[4]) =
|
*((UINT32 *)&pData[4]) =
|
||||||
@ -2604,7 +2806,10 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context,
|
|||||||
{
|
{
|
||||||
BOOL bRet;
|
BOOL bRet;
|
||||||
if (clipboard->nFiles <= fileContentsRequest->listIndex)
|
if (clipboard->nFiles <= fileContentsRequest->listIndex)
|
||||||
goto error;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
bRet = wf_cliprdr_get_file_contents(
|
bRet = wf_cliprdr_get_file_contents(
|
||||||
clipboard->file_names[fileContentsRequest->listIndex], pData,
|
clipboard->file_names[fileContentsRequest->listIndex], pData,
|
||||||
fileContentsRequest->nPositionLow, fileContentsRequest->nPositionHigh, cbRequested,
|
fileContentsRequest->nPositionLow, fileContentsRequest->nPositionHigh, cbRequested,
|
||||||
@ -2614,35 +2819,49 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context,
|
|||||||
{
|
{
|
||||||
printf("get file contents failed.\n");
|
printf("get file contents failed.\n");
|
||||||
uSize = 0;
|
uSize = 0;
|
||||||
goto error;
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = CHANNEL_RC_OK;
|
rc = CHANNEL_RC_OK;
|
||||||
error:
|
exit:
|
||||||
|
|
||||||
if (pDataObj)
|
if (pDataObj)
|
||||||
IDataObject_Release(pDataObj);
|
IDataObject_Release(pDataObj);
|
||||||
|
|
||||||
|
if (rc != CHANNEL_RC_OK)
|
||||||
|
{
|
||||||
|
uSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (uSize == 0)
|
if (uSize == 0)
|
||||||
|
{
|
||||||
|
if (pData)
|
||||||
{
|
{
|
||||||
free(pData);
|
free(pData);
|
||||||
pData = NULL;
|
pData = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sRc =
|
sRc =
|
||||||
cliprdr_send_response_filecontents(
|
cliprdr_send_response_filecontents(
|
||||||
clipboard,
|
clipboard,
|
||||||
fileContentsRequest->serverConnID,
|
fileContentsRequest->serverConnID,
|
||||||
fileContentsRequest->remoteConnID,
|
fileContentsRequest->remoteConnID,
|
||||||
|
rc == CHANNEL_RC_OK ? CB_RESPONSE_OK : CB_RESPONSE_FAIL,
|
||||||
fileContentsRequest->streamId,
|
fileContentsRequest->streamId,
|
||||||
uSize,
|
uSize,
|
||||||
pData);
|
pData);
|
||||||
free(pData);
|
|
||||||
|
|
||||||
if (sRc != CHANNEL_RC_OK)
|
if (pData)
|
||||||
return sRc;
|
{
|
||||||
|
free(pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (sRc != CHANNEL_RC_OK)
|
||||||
|
// return sRc;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2657,34 +2876,50 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context,
|
|||||||
const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse)
|
const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse)
|
||||||
{
|
{
|
||||||
wfClipboard *clipboard;
|
wfClipboard *clipboard;
|
||||||
|
UINT rc = ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
if (!context || !fileContentsResponse)
|
if (!context || !fileContentsResponse)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
if (fileContentsResponse->msgFlags != CB_RESPONSE_OK)
|
break;
|
||||||
return E_FAIL;
|
}
|
||||||
|
|
||||||
clipboard = (wfClipboard *)context->custom;
|
clipboard = (wfClipboard *)context->custom;
|
||||||
|
|
||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
clipboard->req_fsize = 0;
|
||||||
|
clipboard->req_fdata = NULL;
|
||||||
|
|
||||||
|
if (fileContentsResponse->msgFlags != CB_RESPONSE_OK)
|
||||||
|
{
|
||||||
|
rc = E_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
clipboard->req_fsize = fileContentsResponse->cbRequested;
|
clipboard->req_fsize = fileContentsResponse->cbRequested;
|
||||||
clipboard->req_fdata = (char *)malloc(fileContentsResponse->cbRequested);
|
clipboard->req_fdata = (char *)malloc(fileContentsResponse->cbRequested);
|
||||||
|
|
||||||
if (!clipboard->req_fdata)
|
if (!clipboard->req_fdata)
|
||||||
return ERROR_INTERNAL_ERROR;
|
{
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
CopyMemory(clipboard->req_fdata, fileContentsResponse->requestedData,
|
CopyMemory(clipboard->req_fdata, fileContentsResponse->requestedData,
|
||||||
fileContentsResponse->cbRequested);
|
fileContentsResponse->cbRequested);
|
||||||
|
|
||||||
|
rc = CHANNEL_RC_OK;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
if (!SetEvent(clipboard->req_fevent))
|
if (!SetEvent(clipboard->req_fevent))
|
||||||
{
|
{
|
||||||
free(clipboard->req_fdata);
|
// CAUTION: critical error here, process will hang up until wait timeout default 3min.
|
||||||
return ERROR_INTERNAL_ERROR;
|
|
||||||
}
|
}
|
||||||
|
return rc;
|
||||||
return CHANNEL_RC_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||||
@ -2720,6 +2955,9 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
|||||||
if (!(clipboard->response_data_event = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
if (!(clipboard->response_data_event = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (!(clipboard->data_obj_mutex = CreateMutex(NULL, FALSE, "data_obj_mutex")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (!(clipboard->req_fevent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
if (!(clipboard->req_fevent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -2750,6 +2988,23 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
|||||||
|
|
||||||
cliprdr->custom = NULL;
|
cliprdr->custom = NULL;
|
||||||
|
|
||||||
|
/* discard all contexts in clipboard */
|
||||||
|
if (try_open_clipboard(clipboard->hwnd))
|
||||||
|
{
|
||||||
|
if (!EmptyClipboard())
|
||||||
|
{
|
||||||
|
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||||
|
}
|
||||||
|
if (!CloseClipboard())
|
||||||
|
{
|
||||||
|
// critical error!!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
if (clipboard->hwnd)
|
if (clipboard->hwnd)
|
||||||
PostMessage(clipboard->hwnd, WM_QUIT, 0, 0);
|
PostMessage(clipboard->hwnd, WM_QUIT, 0, 0);
|
||||||
|
|
||||||
@ -2768,6 +3023,9 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
|||||||
if (clipboard->response_data_event)
|
if (clipboard->response_data_event)
|
||||||
CloseHandle(clipboard->response_data_event);
|
CloseHandle(clipboard->response_data_event);
|
||||||
|
|
||||||
|
if (clipboard->data_obj_mutex)
|
||||||
|
CloseHandle(clipboard->data_obj_mutex);
|
||||||
|
|
||||||
if (clipboard->req_fevent)
|
if (clipboard->req_fevent)
|
||||||
CloseHandle(clipboard->req_fevent);
|
CloseHandle(clipboard->req_fevent);
|
||||||
|
|
||||||
@ -2788,3 +3046,86 @@ BOOL uninit_cliprdr(CliprdrClientContext *context)
|
|||||||
{
|
{
|
||||||
return wf_cliprdr_uninit(&clipboard, context);
|
return wf_cliprdr_uninit(&clipboard, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL empty_cliprdr(CliprdrClientContext *context, UINT32 server_conn_id, UINT32 remote_conn_id)
|
||||||
|
{
|
||||||
|
wfClipboard *clipboard = NULL;
|
||||||
|
CliprdrDataObject *instance = NULL;
|
||||||
|
BOOL rc = FALSE;
|
||||||
|
if (!context)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (server_conn_id == 0 && remote_conn_id == 0)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clipboard = (wfClipboard *)context->custom;
|
||||||
|
if (!clipboard)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance = clipboard->data_obj;
|
||||||
|
if (instance)
|
||||||
|
{
|
||||||
|
if (server_conn_id != 0 && instance->m_serverConnID != server_conn_id)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (remote_conn_id != 0 && instance->m_remoteConnID != remote_conn_id)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wf_do_empty_cliprdr(clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
||||||
|
{
|
||||||
|
BOOL rc = FALSE;
|
||||||
|
if (!clipboard)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForSingleObject(clipboard->data_obj_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (clipboard->data_obj != NULL)
|
||||||
|
{
|
||||||
|
wf_destroy_file_obj(clipboard->data_obj);
|
||||||
|
clipboard->data_obj = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* discard all contexts in clipboard */
|
||||||
|
if (!try_open_clipboard(clipboard->hwnd))
|
||||||
|
{
|
||||||
|
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||||
|
rc = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EmptyClipboard())
|
||||||
|
{
|
||||||
|
rc = FALSE;
|
||||||
|
}
|
||||||
|
if (!CloseClipboard())
|
||||||
|
{
|
||||||
|
// critical error!!!
|
||||||
|
}
|
||||||
|
rc = TRUE;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (!ReleaseMutex(clipboard->data_obj_mutex))
|
||||||
|
{
|
||||||
|
// critical error!!!
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|||||||
207
src/clipboard_file.rs
Normal file
207
src/clipboard_file.rs
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
use clipboard::ClipbaordFile;
|
||||||
|
use hbb_common::message_proto::*;
|
||||||
|
|
||||||
|
pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
|
||||||
|
match clip {
|
||||||
|
ClipbaordFile::ServerFormatList {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
format_list,
|
||||||
|
} => {
|
||||||
|
let mut formats: Vec<CliprdrFormat> = Vec::new();
|
||||||
|
for v in format_list.iter() {
|
||||||
|
formats.push(CliprdrFormat {
|
||||||
|
server_conn_id: 0,
|
||||||
|
remote_conn_id: 0,
|
||||||
|
id: v.0,
|
||||||
|
format: v.1.clone(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Message {
|
||||||
|
union: Some(message::Union::cliprdr(Cliprdr {
|
||||||
|
union: Some(cliprdr::Union::format_list(CliprdrServerFormatList {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
formats,
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClipbaordFile::ServerFormatListResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
} => Message {
|
||||||
|
union: Some(message::Union::cliprdr(Cliprdr {
|
||||||
|
union: Some(cliprdr::Union::format_list_response(
|
||||||
|
CliprdrServerFormatListResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
ClipbaordFile::ServerFormatDataRequest {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
requested_format_id,
|
||||||
|
} => Message {
|
||||||
|
union: Some(message::Union::cliprdr(Cliprdr {
|
||||||
|
union: Some(cliprdr::Union::format_data_request(
|
||||||
|
CliprdrServerFormatDataRequest {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
requested_format_id,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
ClipbaordFile::ServerFormatDataResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
format_data,
|
||||||
|
} => Message {
|
||||||
|
union: Some(message::Union::cliprdr(Cliprdr {
|
||||||
|
union: Some(cliprdr::Union::format_data_response(
|
||||||
|
CliprdrServerFormatDataResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
format_data,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
ClipbaordFile::FileContentsRequest {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
stream_id,
|
||||||
|
list_index,
|
||||||
|
dw_flags,
|
||||||
|
n_position_low,
|
||||||
|
n_position_high,
|
||||||
|
cb_requested,
|
||||||
|
have_clip_data_id,
|
||||||
|
clip_data_id,
|
||||||
|
} => Message {
|
||||||
|
union: Some(message::Union::cliprdr(Cliprdr {
|
||||||
|
union: Some(cliprdr::Union::file_contents_request(
|
||||||
|
CliprdrFileContentsRequest {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
stream_id,
|
||||||
|
list_index,
|
||||||
|
dw_flags,
|
||||||
|
n_position_low,
|
||||||
|
n_position_high,
|
||||||
|
cb_requested,
|
||||||
|
have_clip_data_id,
|
||||||
|
clip_data_id,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
ClipbaordFile::FileContentsResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
stream_id,
|
||||||
|
requested_data,
|
||||||
|
} => Message {
|
||||||
|
union: Some(message::Union::cliprdr(Cliprdr {
|
||||||
|
union: Some(cliprdr::Union::file_contents_response(
|
||||||
|
CliprdrFileContentsResponse {
|
||||||
|
server_conn_id,
|
||||||
|
remote_conn_id,
|
||||||
|
msg_flags,
|
||||||
|
stream_id,
|
||||||
|
requested_data,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn msg_2_clip(msg: Cliprdr) -> Option<ClipbaordFile> {
|
||||||
|
match msg.union {
|
||||||
|
Some(cliprdr::Union::format_list(data)) => {
|
||||||
|
let mut format_list: Vec<(i32, String)> = Vec::new();
|
||||||
|
for v in data.formats.iter() {
|
||||||
|
format_list.push((v.id, v.format.clone()));
|
||||||
|
}
|
||||||
|
Some(ClipbaordFile::ServerFormatList {
|
||||||
|
server_conn_id: data.server_conn_id,
|
||||||
|
remote_conn_id: data.remote_conn_id,
|
||||||
|
format_list,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some(cliprdr::Union::format_list_response(data)) => {
|
||||||
|
Some(ClipbaordFile::ServerFormatListResponse {
|
||||||
|
server_conn_id: data.server_conn_id,
|
||||||
|
remote_conn_id: data.remote_conn_id,
|
||||||
|
msg_flags: data.msg_flags,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some(cliprdr::Union::format_data_request(data)) => {
|
||||||
|
Some(ClipbaordFile::ServerFormatDataRequest {
|
||||||
|
server_conn_id: data.server_conn_id,
|
||||||
|
remote_conn_id: data.remote_conn_id,
|
||||||
|
requested_format_id: data.requested_format_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some(cliprdr::Union::format_data_response(data)) => {
|
||||||
|
Some(ClipbaordFile::ServerFormatDataResponse {
|
||||||
|
server_conn_id: data.server_conn_id,
|
||||||
|
remote_conn_id: data.remote_conn_id,
|
||||||
|
msg_flags: data.msg_flags,
|
||||||
|
format_data: data.format_data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some(cliprdr::Union::file_contents_request(data)) => {
|
||||||
|
Some(ClipbaordFile::FileContentsRequest {
|
||||||
|
server_conn_id: data.server_conn_id,
|
||||||
|
remote_conn_id: data.remote_conn_id,
|
||||||
|
stream_id: data.stream_id,
|
||||||
|
list_index: data.list_index,
|
||||||
|
dw_flags: data.dw_flags,
|
||||||
|
n_position_low: data.n_position_low,
|
||||||
|
n_position_high: data.n_position_high,
|
||||||
|
cb_requested: data.cb_requested,
|
||||||
|
have_clip_data_id: data.have_clip_data_id,
|
||||||
|
clip_data_id: data.clip_data_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some(cliprdr::Union::file_contents_response(data)) => {
|
||||||
|
Some(ClipbaordFile::FileContentsResponse {
|
||||||
|
server_conn_id: data.server_conn_id,
|
||||||
|
remote_conn_id: data.remote_conn_id,
|
||||||
|
msg_flags: data.msg_flags,
|
||||||
|
stream_id: data.stream_id,
|
||||||
|
requested_data: data.requested_data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::rendezvous_mediator::RendezvousMediator;
|
use crate::rendezvous_mediator::RendezvousMediator;
|
||||||
|
pub use clipboard::ClipbaordFile;
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err, bail, bytes,
|
allow_err, bail, bytes,
|
||||||
bytes_codec::BytesCodec,
|
bytes_codec::BytesCodec,
|
||||||
@ -73,6 +74,7 @@ pub enum Data {
|
|||||||
clipboard: bool,
|
clipboard: bool,
|
||||||
audio: bool,
|
audio: bool,
|
||||||
file: bool,
|
file: bool,
|
||||||
|
file_transfer_enabled: bool,
|
||||||
},
|
},
|
||||||
ChatMessage {
|
ChatMessage {
|
||||||
text: String,
|
text: String,
|
||||||
@ -103,6 +105,8 @@ pub enum Data {
|
|||||||
to: String,
|
to: String,
|
||||||
},
|
},
|
||||||
SyncConfigToUserResp(bool),
|
SyncConfigToUserResp(bool),
|
||||||
|
ClipbaordFile(ClipbaordFile),
|
||||||
|
ClipboardFileEnabled(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
|
|||||||
@ -28,3 +28,6 @@ pub mod cli;
|
|||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
mod port_forward;
|
mod port_forward;
|
||||||
mod lang;
|
mod lang;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub mod clipboard_file;
|
||||||
|
|||||||
@ -29,8 +29,6 @@ use std::{
|
|||||||
|
|
||||||
pub mod audio_service;
|
pub mod audio_service;
|
||||||
mod clipboard_service;
|
mod clipboard_service;
|
||||||
#[cfg(windows)]
|
|
||||||
pub mod clipboard_file_service;
|
|
||||||
mod connection;
|
mod connection;
|
||||||
pub mod input_service;
|
pub mod input_service;
|
||||||
mod service;
|
mod service;
|
||||||
@ -63,8 +61,6 @@ pub fn new() -> ServerPtr {
|
|||||||
server.add_service(Box::new(audio_service::new()));
|
server.add_service(Box::new(audio_service::new()));
|
||||||
server.add_service(Box::new(video_service::new()));
|
server.add_service(Box::new(video_service::new()));
|
||||||
server.add_service(Box::new(clipboard_service::new()));
|
server.add_service(Box::new(clipboard_service::new()));
|
||||||
#[cfg(windows)]
|
|
||||||
server.add_service(Box::new(clipboard_file_service::new()));
|
|
||||||
server.add_service(Box::new(input_service::new_cursor()));
|
server.add_service(Box::new(input_service::new_cursor()));
|
||||||
server.add_service(Box::new(input_service::new_pos()));
|
server.add_service(Box::new(input_service::new_pos()));
|
||||||
Arc::new(RwLock::new(server))
|
Arc::new(RwLock::new(server))
|
||||||
|
|||||||
@ -1,104 +0,0 @@
|
|||||||
use super::*;
|
|
||||||
use clipboard::{create_cliprdr_context, get_rx_client_msg, server_msg, ConnID};
|
|
||||||
use hbb_common::{
|
|
||||||
log,
|
|
||||||
tokio::sync::{
|
|
||||||
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
|
||||||
Mutex as TokioMutex,
|
|
||||||
},
|
|
||||||
tokio::time::{self, Duration, Instant},
|
|
||||||
ResultType,
|
|
||||||
};
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
pub const NAME: &'static str = "cliprdr";
|
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
|
||||||
static ref MSG_CHANNEL_SERVER: (UnboundedSender<(ConnID, Cliprdr)>, TokioMutex<UnboundedReceiver<(ConnID, Cliprdr)>>) = {
|
|
||||||
let (tx, rx) = unbounded_channel();
|
|
||||||
(tx, TokioMutex::new(rx))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static RUNNING: AtomicBool = AtomicBool::new(false);
|
|
||||||
|
|
||||||
pub fn new() -> GenericService {
|
|
||||||
let sp = GenericService::new(NAME, true);
|
|
||||||
sp.run::<_>(listen::run);
|
|
||||||
sp
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_serve_cliprdr_msg(id: i32, msg: Cliprdr) {
|
|
||||||
if RUNNING.load(Ordering::SeqCst) {
|
|
||||||
log::debug!("handle handle_serve_cliprdr_msg");
|
|
||||||
MSG_CHANNEL_SERVER
|
|
||||||
.0
|
|
||||||
.send((
|
|
||||||
ConnID {
|
|
||||||
server_conn_id: id as u32,
|
|
||||||
remote_conn_id: 0,
|
|
||||||
},
|
|
||||||
msg,
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
// should not reach this branch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod listen {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
static WAIT: Duration = Duration::from_millis(1500);
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
pub async fn run(sp: GenericService) -> ResultType<()> {
|
|
||||||
let mut cliprdr_context = create_cliprdr_context(true, false)?;
|
|
||||||
|
|
||||||
RUNNING.store(false, Ordering::SeqCst);
|
|
||||||
|
|
||||||
let mut timer = time::interval_at(Instant::now() + WAIT, WAIT);
|
|
||||||
let mut client_rx = get_rx_client_msg().lock().await;
|
|
||||||
let mut server_rx = MSG_CHANNEL_SERVER.1.lock().await;
|
|
||||||
while sp.ok() {
|
|
||||||
RUNNING.store(true, Ordering::SeqCst);
|
|
||||||
|
|
||||||
tokio::select! {
|
|
||||||
msg = client_rx.recv() => {
|
|
||||||
match msg {
|
|
||||||
Some((conn_id, msg)) => {
|
|
||||||
if conn_id.server_conn_id == 0 {
|
|
||||||
sp.send(msg)
|
|
||||||
} else {
|
|
||||||
sp.send_to(msg, conn_id.server_conn_id as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg = server_rx.recv() => {
|
|
||||||
match msg {
|
|
||||||
Some((conn_id, msg)) => {
|
|
||||||
let res = server_msg(&mut cliprdr_context, conn_id, msg);
|
|
||||||
if res != 0 {
|
|
||||||
// log::warn!("failed to process message for {}", id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ = timer.tick() => {},
|
|
||||||
}
|
|
||||||
sp.snapshot(|_| Ok(()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
RUNNING.store(false, Ordering::SeqCst);
|
|
||||||
log::info!("Clipboard listener stopped!");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,7 @@
|
|||||||
use super::{input_service::*, *};
|
use super::{input_service::*, *};
|
||||||
|
#[cfg(windows)]
|
||||||
|
use crate::{clipboard_file::*, common::update_clipboard, ipc};
|
||||||
|
#[cfg(not(windows))]
|
||||||
use crate::{common::update_clipboard, ipc};
|
use crate::{common::update_clipboard, ipc};
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
config::Config,
|
config::Config,
|
||||||
@ -243,17 +246,18 @@ impl Connection {
|
|||||||
} else if &name == "file" {
|
} else if &name == "file" {
|
||||||
conn.file = enabled;
|
conn.file = enabled;
|
||||||
conn.send_permission(Permission::File, enabled).await;
|
conn.send_permission(Permission::File, enabled).await;
|
||||||
#[cfg(windows)]
|
conn.send_to_cm(ipc::Data::ClipboardFileEnabled(conn.file_transfer_enabled()));
|
||||||
if let Some(s) = conn.server.upgrade() {
|
|
||||||
s.write().unwrap().subscribe(
|
|
||||||
super::clipboard_file_service::NAME,
|
|
||||||
conn.inner.clone(), conn.file_transfer_enabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipc::Data::RawMessage(bytes) => {
|
ipc::Data::RawMessage(bytes) => {
|
||||||
allow_err!(conn.stream.send_raw(bytes).await);
|
allow_err!(conn.stream.send_raw(bytes).await);
|
||||||
}
|
}
|
||||||
|
ipc::Data::ClipbaordFile(_clip) => {
|
||||||
|
if conn.file_transfer_enabled() {
|
||||||
|
#[cfg(windows)]
|
||||||
|
allow_err!(conn.stream.send(&clip_2_msg(_clip)).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -620,10 +624,6 @@ impl Connection {
|
|||||||
if !self.audio_enabled() {
|
if !self.audio_enabled() {
|
||||||
noperms.push(super::audio_service::NAME);
|
noperms.push(super::audio_service::NAME);
|
||||||
}
|
}
|
||||||
if !self.file_transfer_enabled() {
|
|
||||||
#[cfg(windows)]
|
|
||||||
noperms.push(super::clipboard_file_service::NAME);
|
|
||||||
}
|
|
||||||
s.write()
|
s.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.add_connection(self.inner.clone(), &noperms);
|
.add_connection(self.inner.clone(), &noperms);
|
||||||
@ -655,6 +655,7 @@ impl Connection {
|
|||||||
clipboard: self.clipboard,
|
clipboard: self.clipboard,
|
||||||
audio: self.audio,
|
audio: self.audio,
|
||||||
file: self.file,
|
file: self.file,
|
||||||
|
file_transfer_enabled: self.file_transfer_enabled(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,9 +850,13 @@ impl Connection {
|
|||||||
update_clipboard(cb, None);
|
update_clipboard(cb, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(message::Union::cliprdr(_clip)) => {
|
||||||
|
if self.file_transfer_enabled() {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
Some(message::Union::cliprdr(clip)) => {
|
if let Some(clip) = msg_2_clip(_clip) {
|
||||||
clipboard_file_service::handle_serve_cliprdr_msg(self.inner.id, clip)
|
self.send_to_cm(ipc::Data::ClipbaordFile(clip))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(message::Union::file_action(fa)) => {
|
Some(message::Union::file_action(fa)) => {
|
||||||
if self.file_transfer.is_some() {
|
if self.file_transfer.is_some() {
|
||||||
@ -1017,13 +1022,7 @@ impl Connection {
|
|||||||
if let Ok(q) = o.enable_file_transfer.enum_value() {
|
if let Ok(q) = o.enable_file_transfer.enum_value() {
|
||||||
if q != BoolOption::NotSet {
|
if q != BoolOption::NotSet {
|
||||||
self.enable_file_transfer = q == BoolOption::Yes;
|
self.enable_file_transfer = q == BoolOption::Yes;
|
||||||
if let Some(s) = self.server.upgrade() {
|
self.send_to_cm(ipc::Data::ClipboardFileEnabled(self.file_transfer_enabled()));
|
||||||
s.write().unwrap().subscribe(
|
|
||||||
super::clipboard_file_service::NAME,
|
|
||||||
self.inner.clone(),
|
|
||||||
self.file_transfer_enabled(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(q) = o.disable_clipboard.enum_value() {
|
if let Ok(q) = o.disable_clipboard.enum_value() {
|
||||||
|
|||||||
113
src/ui/cm.rs
113
src/ui/cm.rs
@ -1,4 +1,9 @@
|
|||||||
use crate::ipc::{self, new_listener, Connection, Data};
|
use crate::ipc::{self, new_listener, Connection, Data};
|
||||||
|
#[cfg(windows)]
|
||||||
|
use clipboard::{
|
||||||
|
create_cliprdr_context, empty_clipboard, get_rx_clip_client, server_clip_file,
|
||||||
|
set_conn_enabled, ConnID,
|
||||||
|
};
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
config::{Config, ICON},
|
config::{Config, ICON},
|
||||||
@ -106,6 +111,8 @@ impl ConnectionManager {
|
|||||||
&self,
|
&self,
|
||||||
id: i32,
|
id: i32,
|
||||||
data: Data,
|
data: Data,
|
||||||
|
_tx_clip_file: &mpsc::UnboundedSender<(i32, ipc::ClipbaordFile)>,
|
||||||
|
_tx_clip_empty: &mpsc::UnboundedSender<i32>,
|
||||||
write_jobs: &mut Vec<fs::TransferJob>,
|
write_jobs: &mut Vec<fs::TransferJob>,
|
||||||
conn: &mut Connection,
|
conn: &mut Connection,
|
||||||
) {
|
) {
|
||||||
@ -186,6 +193,17 @@ impl ConnectionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Data::ClipbaordFile(_clip) => {
|
||||||
|
#[cfg(windows)]
|
||||||
|
allow_err!(_tx_clip_file.send((id, _clip)));
|
||||||
|
}
|
||||||
|
Data::ClipboardFileEnabled(enabled) => {
|
||||||
|
#[cfg(windows)]
|
||||||
|
set_conn_enabled(id, 0, enabled);
|
||||||
|
if !enabled {
|
||||||
|
allow_err!(_tx_clip_empty.send(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,6 +344,13 @@ impl sciter::EventHandler for ConnectionManager {
|
|||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn start_ipc(cm: ConnectionManager) {
|
async fn start_ipc(cm: ConnectionManager) {
|
||||||
|
let (tx_file, _rx_file) = mpsc::unbounded_channel::<(i32, ipc::ClipbaordFile)>();
|
||||||
|
let (tx_clip_empty, _rx_clip_empty) = mpsc::unbounded_channel::<i32>();
|
||||||
|
#[cfg(windows)]
|
||||||
|
let cm_clip = cm.clone();
|
||||||
|
#[cfg(windows)]
|
||||||
|
std::thread::spawn(move || start_clipboard_file(cm_clip, _rx_file, _rx_clip_empty));
|
||||||
|
|
||||||
match new_listener("_cm").await {
|
match new_listener("_cm").await {
|
||||||
Ok(mut incoming) => {
|
Ok(mut incoming) => {
|
||||||
while let Some(result) = incoming.next().await {
|
while let Some(result) = incoming.next().await {
|
||||||
@ -333,6 +358,8 @@ async fn start_ipc(cm: ConnectionManager) {
|
|||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
let mut stream = Connection::new(stream);
|
let mut stream = Connection::new(stream);
|
||||||
let cm = cm.clone();
|
let cm = cm.clone();
|
||||||
|
let tx_file = tx_file.clone();
|
||||||
|
let tx_clip_empty = tx_clip_empty.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut conn_id: i32 = 0;
|
let mut conn_id: i32 = 0;
|
||||||
let (tx, mut rx) = mpsc::unbounded_channel::<Data>();
|
let (tx, mut rx) = mpsc::unbounded_channel::<Data>();
|
||||||
@ -347,16 +374,22 @@ async fn start_ipc(cm: ConnectionManager) {
|
|||||||
}
|
}
|
||||||
Ok(Some(data)) => {
|
Ok(Some(data)) => {
|
||||||
match data {
|
match data {
|
||||||
Data::Login{id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file} => {
|
Data::Login{id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, file_transfer_enabled} => {
|
||||||
conn_id = id;
|
conn_id = id;
|
||||||
|
#[cfg(windows)]
|
||||||
|
set_conn_enabled(id, 0, file_transfer_enabled);
|
||||||
|
let _ = file_transfer_enabled;
|
||||||
cm.add_connection(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, tx.clone());
|
cm.add_connection(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, tx.clone());
|
||||||
}
|
}
|
||||||
Data::Close => {
|
Data::Close => {
|
||||||
|
allow_err!(tx_clip_empty.send(conn_id));
|
||||||
|
#[cfg(windows)]
|
||||||
|
set_conn_enabled(conn_id, 0, false);
|
||||||
log::info!("cm ipc connection closed from connection request");
|
log::info!("cm ipc connection closed from connection request");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
cm.handle_data(conn_id, data, &mut write_jobs, &mut stream).await;
|
cm.handle_data(conn_id, data, &tx_file, &tx_clip_empty, &mut write_jobs, &mut stream).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -465,3 +498,79 @@ async fn start_pa() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[tokio::main(flavor = "current_thread")]
|
||||||
|
async fn start_clipboard_file(
|
||||||
|
cm: ConnectionManager,
|
||||||
|
mut rx: mpsc::UnboundedReceiver<(i32, ipc::ClipbaordFile)>,
|
||||||
|
mut rx_clip_empty: mpsc::UnboundedReceiver<i32>,
|
||||||
|
) {
|
||||||
|
let mut cliprdr_context = match create_cliprdr_context(true, false) {
|
||||||
|
Ok(context) => {
|
||||||
|
log::info!("clipboard context for file transfer created.");
|
||||||
|
context
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::error!(
|
||||||
|
"Create clipboard context for file transfer: {}",
|
||||||
|
err.to_string()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut rx_clip_client = get_rx_clip_client().lock().await;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
clip_file = rx_clip_client.recv() => match clip_file {
|
||||||
|
Some((conn_id, clip)) => {
|
||||||
|
cmd_inner_send(
|
||||||
|
&cm,
|
||||||
|
conn_id.server_conn_id as i32,
|
||||||
|
Data::ClipbaordFile(clip)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
},
|
||||||
|
server_msg = rx.recv() => match server_msg {
|
||||||
|
Some((server_conn_id, clip)) => {
|
||||||
|
let conn_id = ConnID {
|
||||||
|
server_conn_id: server_conn_id as u32,
|
||||||
|
remote_conn_id: 0,
|
||||||
|
};
|
||||||
|
server_clip_file(&mut cliprdr_context, conn_id, clip);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
server_conn_id = rx_clip_empty.recv() => match server_conn_id {
|
||||||
|
Some(server_conn_id) => {
|
||||||
|
if !empty_clipboard(&mut cliprdr_context, server_conn_id, 0) {
|
||||||
|
// log::error!("failed to empty clipboard");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn cmd_inner_send(cm: &ConnectionManager, id: i32, data: Data) {
|
||||||
|
let lock = cm.read().unwrap();
|
||||||
|
if id != 0 {
|
||||||
|
if let Some(s) = lock.senders.get(&id) {
|
||||||
|
allow_err!(s.send(data));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for s in lock.senders.values() {
|
||||||
|
allow_err!(s.send(data.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,12 +1,18 @@
|
|||||||
use crate::client::*;
|
#[cfg(windows)]
|
||||||
use crate::common::{
|
use crate::{
|
||||||
self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL,
|
client::*,
|
||||||
|
clipboard_file::*,
|
||||||
|
common::{self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL},
|
||||||
|
};
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use crate::{
|
||||||
|
client::*,
|
||||||
|
common::{self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL},
|
||||||
};
|
};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use clipboard::{
|
use clipboard::{
|
||||||
cliprdr::CliprdrClientContext, create_cliprdr_context as create_clipboard_file_context,
|
cliprdr::CliprdrClientContext, create_cliprdr_context as create_clipboard_file_context,
|
||||||
get_rx_client_msg as get_clipboard_file_rx_client_msg, server_msg as clipboard_file_msg,
|
get_rx_clip_client, server_clip_file, ConnID as ClipboardFileConnID,
|
||||||
ConnID as ClipboardFileConnID,
|
|
||||||
};
|
};
|
||||||
use enigo::{self, Enigo, KeyboardControllable};
|
use enigo::{self, Enigo, KeyboardControllable};
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
@ -1313,9 +1319,9 @@ impl Remote {
|
|||||||
|
|
||||||
// just build for now
|
// just build for now
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
let (_, mut clipboard_file_client_rx) = mpsc::unbounded_channel::<i32>();
|
let (_, mut rx_clip_client) = mpsc::unbounded_channel::<i32>();
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut clipboard_file_client_rx = get_clipboard_file_rx_client_msg().lock().await;
|
let mut rx_clip_client = get_rx_clip_client().lock().await;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
@ -1347,12 +1353,12 @@ impl Remote {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_msg = clipboard_file_client_rx.recv() => {
|
_msg = rx_clip_client.recv() => {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
match _msg {
|
match _msg {
|
||||||
Some((conn_id, msg)) => {
|
Some((conn_id, clip)) => {
|
||||||
if conn_id.remote_conn_id == 0 || conn_id.remote_conn_id == self.pid {
|
if conn_id.remote_conn_id == 0 || conn_id.remote_conn_id == self.pid {
|
||||||
allow_err!(peer.send(&msg).await);
|
allow_err!(peer.send(&clip_2_msg(clip)).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -1740,7 +1746,8 @@ impl Remote {
|
|||||||
Some(message::Union::cliprdr(clip)) => {
|
Some(message::Union::cliprdr(clip)) => {
|
||||||
if !self.handler.lc.read().unwrap().disable_clipboard {
|
if !self.handler.lc.read().unwrap().disable_clipboard {
|
||||||
if let Some(context) = &mut self.clipboard_file_context {
|
if let Some(context) = &mut self.clipboard_file_context {
|
||||||
clipboard_file_msg(
|
if let Some(clip) = msg_2_clip(clip) {
|
||||||
|
server_clip_file(
|
||||||
context,
|
context,
|
||||||
ClipboardFileConnID {
|
ClipboardFileConnID {
|
||||||
server_conn_id: 0,
|
server_conn_id: 0,
|
||||||
@ -1751,6 +1758,7 @@ impl Remote {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Some(message::Union::file_response(fr)) => match fr.union {
|
Some(message::Union::file_response(fr)) => match fr.union {
|
||||||
Some(file_response::Union::dir(fd)) => {
|
Some(file_response::Union::dir(fd)) => {
|
||||||
let entries = fd.entries.to_vec();
|
let entries = fd.entries.to_vec();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user