1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use crate::opc_da::errors::{OpcError, OpcResult};
use windows::Win32::System::Com::{FORMATETC, STGMEDIUM};
/// Data transfer functionality using COM's structured storage.
///
/// Provides methods to transfer data between client and server using
/// structured storage formats and advisory connections.
pub trait DataObjectTrait {
fn interface(&self) -> OpcResult<&windows::Win32::System::Com::IDataObject>;
/// Gets data from the object in the specified format.
///
/// # Arguments
/// * `format` - Format specification including clipboard format and storage medium
///
/// # Returns
/// Storage medium containing the requested data
fn get_data(&self, format: &FORMATETC) -> OpcResult<STGMEDIUM> {
// SAFETY: Calling COM method GetData with valid formatetc reference.
unsafe { Ok(self.interface()?.GetData(format)?) }
}
/// Gets data in place using the specified format.
///
/// # Arguments
/// * `format` - Format specification including clipboard format and storage medium
///
/// # Returns
/// Storage medium updated with the requested data
fn get_data_here(&self, format: &FORMATETC) -> OpcResult<STGMEDIUM> {
let mut output = STGMEDIUM::default();
// SAFETY: Calling COM method GetDataHere with output stgmedium reference.
unsafe { self.interface()?.GetDataHere(format, &mut output)? };
Ok(output)
}
/// Tests if data is available in the specified format.
///
/// # Arguments
/// * `format` - Format specification to test for availability
///
/// # Returns
/// Ok(()) if the format is supported, error otherwise
fn query_get_data(&self, format: &FORMATETC) -> OpcResult<()> {
// SAFETY: Calling COM method QueryGetData.
unsafe {
self.interface()?
.QueryGetData(format)
.ok()
.map_err(OpcError::from)
}
}
/// Gets the canonical format equivalent to the specified format.
///
/// # Arguments
/// * `format_in` - Format specification to convert
///
/// # Returns
/// Canonical format specification
fn get_canonical_format(&self, format_in: &FORMATETC) -> OpcResult<FORMATETC> {
let mut output = FORMATETC::default();
// SAFETY: Calling COM method GetCanonicalFormatEtc.
unsafe {
self.interface()?
.GetCanonicalFormatEtc(format_in, &mut output)
}
.ok()?;
Ok(output)
}
/// Sets data in the specified format.
///
/// # Arguments
/// * `format` - Format specification for the data
/// * `medium` - Storage medium containing the data
/// * `release` - If true, the object takes ownership of medium
///
/// # Returns
/// Ok(()) if data was set successfully
fn set_data(&self, format: &FORMATETC, medium: &STGMEDIUM, release: bool) -> OpcResult<()> {
// SAFETY: Calling COM method SetData.
unsafe { Ok(self.interface()?.SetData(format, medium, release)?) }
}
/// Enumerates available data formats.
///
/// # Arguments
/// * `direction` - Direction of data flow (DATADIR_GET = 1, DATADIR_SET = 2)
///
/// # Returns
/// Enumerator for available format specifications
fn enumerate_formats(
&self,
direction: u32,
) -> OpcResult<windows::Win32::System::Com::IEnumFORMATETC> {
// SAFETY: Calling COM method EnumFormatEtc.
unsafe { Ok(self.interface()?.EnumFormatEtc(direction)?) }
}
/// Establishes an advisory connection for data change notifications.
///
/// # Arguments
/// * `format` - Format specification to monitor
/// * `advf` - Advisory flags controlling notification behavior
/// * `sink` - Sink interface to receive notifications
///
/// # Returns
/// Connection token for the advisory connection
fn dadvise(
&self,
format: &FORMATETC,
advf: u32,
sink: &windows::Win32::System::Com::IAdviseSink,
) -> OpcResult<u32> {
// SAFETY: Calling COM method DAdvise.
unsafe { Ok(self.interface()?.DAdvise(format, advf, sink)?) }
}
/// Terminates an advisory connection.
///
/// # Arguments
/// * `connection` - Connection token from dadvise
///
/// # Returns
/// Ok(()) if connection was terminated successfully
fn dunadvise(&self, connection: u32) -> OpcResult<()> {
// SAFETY: Calling COM method DUnadvise.
unsafe { Ok(self.interface()?.DUnadvise(connection)?) }
}
/// Enumerates active advisory connections.
///
/// # Returns
/// Enumerator for active advisory connections
fn enum_dadvise(&self) -> OpcResult<windows::Win32::System::Com::IEnumSTATDATA> {
// SAFETY: Calling COM method EnumDAdvise.
unsafe { Ok(self.interface()?.EnumDAdvise()?) }
}
}