windows: Remove SmartGlobal
(#30366)
Closes #29657 Using `with_clipboard_data()` to ensure that `GlobalLock` and `GlobalUnlock` are called correctly. Release Notes: - N/A
This commit is contained in:
parent
30f3efe697
commit
89ce49d5b7
2 changed files with 58 additions and 74 deletions
|
@ -5,23 +5,21 @@ use collections::{FxHashMap, FxHashSet};
|
|||
use itertools::Itertools;
|
||||
use util::ResultExt;
|
||||
use windows::Win32::{
|
||||
Foundation::HANDLE,
|
||||
Foundation::{HANDLE, HGLOBAL},
|
||||
System::{
|
||||
DataExchange::{
|
||||
CloseClipboard, CountClipboardFormats, EmptyClipboard, EnumClipboardFormats,
|
||||
GetClipboardData, GetClipboardFormatNameW, IsClipboardFormatAvailable, OpenClipboard,
|
||||
RegisterClipboardFormatW, SetClipboardData,
|
||||
},
|
||||
Memory::{GMEM_MOVEABLE, GlobalAlloc, GlobalLock, GlobalUnlock},
|
||||
Memory::{GMEM_MOVEABLE, GlobalAlloc, GlobalLock, GlobalSize, GlobalUnlock},
|
||||
Ole::{CF_HDROP, CF_UNICODETEXT},
|
||||
},
|
||||
UI::Shell::{DragQueryFileW, HDROP},
|
||||
};
|
||||
use windows_core::PCWSTR;
|
||||
|
||||
use crate::{
|
||||
ClipboardEntry, ClipboardItem, ClipboardString, Image, ImageFormat, SmartGlobal, hash,
|
||||
};
|
||||
use crate::{ClipboardEntry, ClipboardItem, ClipboardString, Image, ImageFormat, hash};
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-dragqueryfilew
|
||||
const DRAGDROP_GET_FILES_COUNT: u32 = 0xFFFFFFFF;
|
||||
|
@ -268,13 +266,10 @@ where
|
|||
}
|
||||
|
||||
fn read_string_from_clipboard() -> Option<ClipboardEntry> {
|
||||
let text = {
|
||||
let global = SmartGlobal::from_raw_ptr(
|
||||
unsafe { GetClipboardData(CF_UNICODETEXT.0 as u32).log_err() }?.0,
|
||||
);
|
||||
let text = PCWSTR(global.lock() as *const u16);
|
||||
String::from_utf16_lossy(unsafe { text.as_wide() })
|
||||
};
|
||||
let text = with_clipboard_data(CF_UNICODETEXT.0 as u32, |data_ptr| {
|
||||
let pcwstr = PCWSTR(data_ptr as *const u16);
|
||||
String::from_utf16_lossy(unsafe { pcwstr.as_wide() })
|
||||
})?;
|
||||
let Some(hash) = read_hash_from_clipboard() else {
|
||||
return Some(ClipboardEntry::String(ClipboardString::new(text)));
|
||||
};
|
||||
|
@ -295,25 +290,23 @@ fn read_hash_from_clipboard() -> Option<u64> {
|
|||
if unsafe { IsClipboardFormatAvailable(*CLIPBOARD_HASH_FORMAT).is_err() } {
|
||||
return None;
|
||||
}
|
||||
let global =
|
||||
SmartGlobal::from_raw_ptr(unsafe { GetClipboardData(*CLIPBOARD_HASH_FORMAT).log_err() }?.0);
|
||||
let raw_ptr = global.lock() as *const u16;
|
||||
let hash_bytes: [u8; 8] = unsafe {
|
||||
std::slice::from_raw_parts(raw_ptr.cast::<u8>(), 8)
|
||||
.to_vec()
|
||||
.try_into()
|
||||
.log_err()
|
||||
}?;
|
||||
Some(u64::from_ne_bytes(hash_bytes))
|
||||
with_clipboard_data(*CLIPBOARD_HASH_FORMAT, |data_ptr| {
|
||||
let hash_bytes: [u8; 8] = unsafe {
|
||||
std::slice::from_raw_parts(data_ptr.cast::<u8>(), 8)
|
||||
.to_vec()
|
||||
.try_into()
|
||||
.log_err()
|
||||
}?;
|
||||
Some(u64::from_ne_bytes(hash_bytes))
|
||||
})?
|
||||
}
|
||||
|
||||
fn read_metadata_from_clipboard() -> Option<String> {
|
||||
unsafe { IsClipboardFormatAvailable(*CLIPBOARD_METADATA_FORMAT).log_err()? };
|
||||
let global = SmartGlobal::from_raw_ptr(
|
||||
unsafe { GetClipboardData(*CLIPBOARD_METADATA_FORMAT).log_err() }?.0,
|
||||
);
|
||||
let text = PCWSTR(global.lock() as *const u16);
|
||||
Some(String::from_utf16_lossy(unsafe { text.as_wide() }))
|
||||
with_clipboard_data(*CLIPBOARD_METADATA_FORMAT, |data_ptr| {
|
||||
let pcwstr = PCWSTR(data_ptr as *const u16);
|
||||
String::from_utf16_lossy(unsafe { pcwstr.as_wide() })
|
||||
})
|
||||
}
|
||||
|
||||
fn read_image_from_clipboard(format: u32) -> Option<ClipboardEntry> {
|
||||
|
@ -327,29 +320,52 @@ fn format_number_to_image_format(format_number: u32) -> Option<&'static ImageFor
|
|||
}
|
||||
|
||||
fn read_image_for_type(format_number: u32, format: ImageFormat) -> Option<ClipboardEntry> {
|
||||
let global = SmartGlobal::from_raw_ptr(unsafe { GetClipboardData(format_number).log_err() }?.0);
|
||||
let image_ptr = global.lock();
|
||||
let iamge_size = global.size();
|
||||
let bytes =
|
||||
unsafe { std::slice::from_raw_parts(image_ptr as *mut u8 as _, iamge_size).to_vec() };
|
||||
let id = hash(&bytes);
|
||||
let (bytes, id) = with_clipboard_data_and_size(format_number, |data_ptr, size| {
|
||||
let bytes = unsafe { std::slice::from_raw_parts(data_ptr as *mut u8 as _, size).to_vec() };
|
||||
let id = hash(&bytes);
|
||||
(bytes, id)
|
||||
})?;
|
||||
Some(ClipboardEntry::Image(Image { format, bytes, id }))
|
||||
}
|
||||
|
||||
fn read_files_from_clipboard() -> Option<ClipboardEntry> {
|
||||
let global =
|
||||
SmartGlobal::from_raw_ptr(unsafe { GetClipboardData(CF_HDROP.0 as u32).log_err() }?.0);
|
||||
let hdrop = HDROP(global.lock());
|
||||
let mut filenames = String::new();
|
||||
with_file_names(hdrop, |file_name| {
|
||||
filenames.push_str(&file_name);
|
||||
});
|
||||
let text = with_clipboard_data(CF_HDROP.0 as u32, |data_ptr| {
|
||||
let hdrop = HDROP(data_ptr);
|
||||
let mut filenames = String::new();
|
||||
with_file_names(hdrop, |file_name| {
|
||||
filenames.push_str(&file_name);
|
||||
});
|
||||
filenames
|
||||
})?;
|
||||
Some(ClipboardEntry::String(ClipboardString {
|
||||
text: filenames,
|
||||
text,
|
||||
metadata: None,
|
||||
}))
|
||||
}
|
||||
|
||||
fn with_clipboard_data<F, R>(format: u32, f: F) -> Option<R>
|
||||
where
|
||||
F: FnOnce(*mut std::ffi::c_void) -> R,
|
||||
{
|
||||
let global = HGLOBAL(unsafe { GetClipboardData(format).log_err() }?.0);
|
||||
let data_ptr = unsafe { GlobalLock(global) };
|
||||
let result = f(data_ptr);
|
||||
unsafe { GlobalUnlock(global).log_err() };
|
||||
Some(result)
|
||||
}
|
||||
|
||||
fn with_clipboard_data_and_size<F, R>(format: u32, f: F) -> Option<R>
|
||||
where
|
||||
F: FnOnce(*mut std::ffi::c_void, usize) -> R,
|
||||
{
|
||||
let global = HGLOBAL(unsafe { GetClipboardData(format).log_err() }?.0);
|
||||
let size = unsafe { GlobalSize(global) };
|
||||
let data_ptr = unsafe { GlobalLock(global) };
|
||||
let result = f(data_ptr, size);
|
||||
unsafe { GlobalUnlock(global).log_err() };
|
||||
Some(result)
|
||||
}
|
||||
|
||||
impl From<ImageFormat> for image::ImageFormat {
|
||||
fn from(value: ImageFormat) -> Self {
|
||||
match value {
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use util::ResultExt;
|
||||
use windows::Win32::{
|
||||
Foundation::{HANDLE, HGLOBAL},
|
||||
System::Memory::{GlobalLock, GlobalSize, GlobalUnlock},
|
||||
UI::WindowsAndMessaging::HCURSOR,
|
||||
};
|
||||
use windows::Win32::{Foundation::HANDLE, UI::WindowsAndMessaging::HCURSOR};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) struct SafeHandle {
|
||||
|
@ -50,30 +45,3 @@ impl Deref for SafeCursor {
|
|||
&self.raw
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct SmartGlobal {
|
||||
raw: HGLOBAL,
|
||||
}
|
||||
|
||||
impl SmartGlobal {
|
||||
pub(crate) fn from_raw_ptr(ptr: *mut std::ffi::c_void) -> Self {
|
||||
Self { raw: HGLOBAL(ptr) }
|
||||
}
|
||||
|
||||
pub(crate) fn lock(&self) -> *mut std::ffi::c_void {
|
||||
unsafe { GlobalLock(self.raw) }
|
||||
}
|
||||
|
||||
pub(crate) fn size(&self) -> usize {
|
||||
unsafe { GlobalSize(self.raw) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SmartGlobal {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
GlobalUnlock(self.raw).log_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue