From 89ce49d5b74952d6392432f763897680c4a716e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Fri, 9 May 2025 20:05:53 +0800 Subject: [PATCH] windows: Remove `SmartGlobal` (#30366) Closes #29657 Using `with_clipboard_data()` to ensure that `GlobalLock` and `GlobalUnlock` are called correctly. Release Notes: - N/A --- crates/gpui/src/platform/windows/clipboard.rs | 98 +++++++++++-------- crates/gpui/src/platform/windows/wrapper.rs | 34 +------ 2 files changed, 58 insertions(+), 74 deletions(-) diff --git a/crates/gpui/src/platform/windows/clipboard.rs b/crates/gpui/src/platform/windows/clipboard.rs index 19b5c6cacdfadb61ffa25eef12e75a06c495700c..915dbab3901aef2fc092626f13fbad783f68858a 100644 --- a/crates/gpui/src/platform/windows/clipboard.rs +++ b/crates/gpui/src/platform/windows/clipboard.rs @@ -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 { - 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 { 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::(), 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::(), 8) + .to_vec() + .try_into() + .log_err() + }?; + Some(u64::from_ne_bytes(hash_bytes)) + })? } fn read_metadata_from_clipboard() -> Option { 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 { @@ -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 { - 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 { - 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(format: u32, f: F) -> Option +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(format: u32, f: F) -> Option +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 for image::ImageFormat { fn from(value: ImageFormat) -> Self { match value { diff --git a/crates/gpui/src/platform/windows/wrapper.rs b/crates/gpui/src/platform/windows/wrapper.rs index e6e645e61aebdf0349173fc7761a8b27bff50cd8..6015dffdab299754d9469684ead08a9d5c95d4c6 100644 --- a/crates/gpui/src/platform/windows/wrapper.rs +++ b/crates/gpui/src/platform/windows/wrapper.rs @@ -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(); - } - } -}