Skip to content

Commit 1e3a0bf

Browse files
committed
implementing QueryInterface for windows
1 parent da62200 commit 1e3a0bf

File tree

1 file changed

+100
-10
lines changed

1 file changed

+100
-10
lines changed

winit-win32/src/drop_handler.rs

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
11
use std::ffi::{OsString, c_void};
22
use std::os::windows::ffi::OsStringExt;
33
use std::path::PathBuf;
4-
use std::ptr;
4+
use std::ptr::{self, null_mut};
55
use std::sync::atomic::{AtomicUsize, Ordering};
6-
76
use dpi::PhysicalPosition;
87
use tracing::debug;
9-
use windows_sys::Win32::Foundation::{DV_E_FORMATETC, HWND, POINT, POINTL, S_OK};
8+
use windows_sys::Win32::Foundation::{DV_E_FORMATETC, E_NOINTERFACE, HWND, POINT, POINTL, S_OK};
109
use windows_sys::Win32::Graphics::Gdi::ScreenToClient;
1110
use windows_sys::Win32::System::Com::{DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL};
1211
use windows_sys::Win32::System::Ole::{CF_HDROP, DROPEFFECT_COPY, DROPEFFECT_NONE};
1312
use windows_sys::Win32::UI::Shell::{DragFinish, DragQueryFileW, HDROP};
1413
use windows_sys::core::{GUID, HRESULT};
1514
use winit_core::event::WindowEvent;
16-
1715
use crate::definitions::{
1816
IDataObject, IDataObjectVtbl, IDropTarget, IDropTargetVtbl, IUnknown, IUnknownVtbl,
1917
};
2018

19+
const IID_IUNKNOWN: GUID = GUID {
20+
data1: 0x00000000,
21+
data2: 0x0000,
22+
data3: 0x0000,
23+
data4: [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46],
24+
};
25+
26+
const IID_IDROP_TARGET: GUID = GUID {
27+
data1: 0x00000122,
28+
data2: 0x0000,
29+
data3: 0x0000,
30+
data4: [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46],
31+
};
32+
33+
fn guid_eq(a: &GUID, b: &GUID) -> bool {
34+
a.data1 == b.data1 &&
35+
a.data2 == b.data2 &&
36+
a.data3 == b.data3 &&
37+
a.data4 == b.data4
38+
}
39+
2140
#[repr(C)]
2241
pub struct FileDropHandlerData {
2342
pub interface: IDropTarget,
@@ -49,13 +68,26 @@ impl FileDropHandler {
4968

5069
// Implement IUnknown
5170
pub unsafe extern "system" fn QueryInterface(
52-
_this: *mut IUnknown,
53-
_riid: *const GUID,
54-
_ppvObject: *mut *mut c_void,
71+
this: *mut IUnknown,
72+
riid: *const GUID,
73+
ppvObject: *mut *mut c_void,
5574
) -> HRESULT {
56-
// This function doesn't appear to be required for an `IDropTarget`.
57-
// An implementation would be nice however.
58-
unimplemented!();
75+
if riid.is_null() || ppvObject.is_null() {
76+
return E_NOINTERFACE;
77+
}
78+
79+
let drop_handler_data =unsafe{ Self::from_interface(this)};
80+
let requested = unsafe { &*riid };
81+
82+
if guid_eq(requested, &IID_IUNKNOWN) || guid_eq(requested, &IID_IDROP_TARGET) {
83+
unsafe{*ppvObject =this as *mut c_void};
84+
drop_handler_data.refcount.fetch_add(1, Ordering::Release);
85+
return S_OK;
86+
}
87+
88+
// Interface not supported
89+
unsafe { *ppvObject = null_mut() };
90+
E_NOINTERFACE
5991
}
6092

6193
pub unsafe extern "system" fn AddRef(this: *mut IUnknown) -> u32 {
@@ -238,3 +270,61 @@ static DROP_TARGET_VTBL: IDropTargetVtbl = IDropTargetVtbl {
238270
DragLeave: FileDropHandler::DragLeave,
239271
Drop: FileDropHandler::Drop,
240272
};
273+
274+
#[cfg(test)]
275+
mod tests {
276+
use super::*;
277+
use std::ptr::null_mut;
278+
use windows_sys::Win32::Foundation::HWND;
279+
use windows_sys::core::GUID;
280+
281+
282+
#[test]
283+
fn test_file_drop_handler_query_interface() {
284+
let handler = FileDropHandler::new(
285+
0 as HWND, // null window handle
286+
Box::new(|event| {
287+
println!("WindowEvent: {:?}", event);
288+
}),
289+
);
290+
291+
unsafe {
292+
let mut ppv: *mut std::ffi::c_void = null_mut();
293+
let hr_iunknown = FileDropHandler::QueryInterface(
294+
handler.data as *mut IUnknown,
295+
&IID_IUNKNOWN,
296+
&mut ppv as *mut _,
297+
);
298+
assert_eq!(hr_iunknown, S_OK);
299+
assert!(!ppv.is_null());
300+
301+
ppv = null_mut();
302+
303+
let hr_idroptarget = FileDropHandler::QueryInterface(
304+
handler.data as *mut IUnknown,
305+
&IID_IDROP_TARGET,
306+
&mut ppv as *mut _,
307+
);
308+
assert_eq!(hr_idroptarget, S_OK);
309+
assert!(!ppv.is_null());
310+
311+
let unknown_guid = GUID {
312+
data1: 0x12345678,
313+
data2: 0x1234,
314+
data3: 0x5678,
315+
data4: [0x90, 0xAB, 0xCD, 0xEF, 0x00, 0x11, 0x22, 0x33],
316+
};
317+
ppv = null_mut();
318+
let hr_unknown = FileDropHandler::QueryInterface(
319+
handler.data as *mut IUnknown,
320+
&unknown_guid,
321+
&mut ppv as *mut _,
322+
);
323+
assert_eq!(hr_unknown, E_NOINTERFACE);
324+
assert!(ppv.is_null());
325+
}
326+
327+
// Drop the handler manually
328+
unsafe { FileDropHandler::Release(handler.data as *mut IUnknown) };
329+
}
330+
}

0 commit comments

Comments
 (0)