winsafe\ole/funcs.rs
1#![allow(non_snake_case)]
2
3use crate::co;
4use crate::decl::*;
5use crate::guard::*;
6use crate::kernel::privs::*;
7use crate::ole::ffi;
8use crate::ole::privs::*;
9use crate::prelude::*;
10
11/// [`CLSIDFromProgID`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-clsidfromprogid)
12/// function.
13///
14/// # Examples
15///
16/// ```no_run
17/// use winsafe::{self as w, prelude::*, co};
18///
19/// let _com_guard = w::CoInitializeEx(
20/// co::COINIT::APARTMENTTHREADED | co::COINIT::DISABLE_OLE1DDE)?;
21///
22/// let cls_id = w::CLSIDFromProgID("Excel.Application")?;
23///
24/// let excel = w::CoCreateInstance::<w::IDispatch>(
25/// &cls_id,
26/// None::<&w::IUnknown>,
27/// co::CLSCTX::LOCAL_SERVER,
28/// )?;
29///
30/// let ids = excel.GetIDsOfNames(&["Workbooks"], w::LCID::USER_DEFAULT)?;
31/// println!("{}", ids[0]);
32/// # w::HrResult::Ok(())
33/// ```
34#[must_use]
35pub fn CLSIDFromProgID(prog_id: &str) -> HrResult<co::CLSID> {
36 let mut clsid = co::CLSID::default();
37 ok_to_hrresult(unsafe {
38 ffi::CLSIDFromProgID(WString::from_str(prog_id).as_ptr(), pvoid(&mut clsid))
39 })
40 .map(|_| clsid)
41}
42
43/// [`CLSIDFromProgIDEx`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-clsidfromprogidex)
44/// function.
45#[must_use]
46pub fn CLSIDFromProgIDEx(prog_id: &str) -> HrResult<co::CLSID> {
47 let mut clsid = co::CLSID::default();
48 ok_to_hrresult(unsafe {
49 ffi::CLSIDFromProgIDEx(WString::from_str(prog_id).as_ptr(), pvoid(&mut clsid))
50 })
51 .map(|_| clsid)
52}
53
54/// [`CLSIDFromString`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-clsidfromstring)
55/// function.
56#[must_use]
57pub fn CLSIDFromString(prog_id: &str) -> HrResult<co::CLSID> {
58 let mut clsid = co::CLSID::default();
59 ok_to_hrresult(unsafe {
60 ffi::CLSIDFromString(WString::from_str(prog_id).as_ptr(), pvoid(&mut clsid))
61 })
62 .map(|_| clsid)
63}
64
65/// [`CoCreateGuid`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateguid)
66/// function.
67///
68/// Returns a globally unique 128-bit integer.
69#[must_use]
70pub fn CoCreateGuid() -> HrResult<GUID> {
71 let mut guid = GUID::default();
72 ok_to_hrresult(unsafe { ffi::CoCreateGuid(pvoid(&mut guid)) }).map(|_| guid)
73}
74
75/// [`CoCreateInstance`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance)
76/// function.
77///
78/// Returns an [`IUnknown`](crate::IUnknown)-derived COM object.
79///
80/// # Examples
81///
82/// Instantiating an [`ITaskbarList`](crate::ITaskbarList) object:
83///
84/// ```rust,ignore
85/// use winsafe::{self as w, prelude::*, co};
86///
87/// let obj = w::CoCreateInstance::<w::ITaskbarList>(
88/// &co::CLSID::TaskbarList,
89/// None::<&w::IUnknown>,
90/// co::CLSCTX::INPROC_SERVER,
91/// )?;
92/// # w::HrResult::Ok(())
93/// ```
94#[must_use]
95pub fn CoCreateInstance<T>(
96 clsid: &co::CLSID,
97 iunk_outer: Option<&impl ole_IUnknown>,
98 cls_context: co::CLSCTX,
99) -> HrResult<T>
100where
101 T: ole_IUnknown,
102{
103 let mut queried = unsafe { T::null() };
104 ok_to_hrresult(unsafe {
105 ffi::CoCreateInstance(
106 pcvoid(clsid),
107 iunk_outer.map_or(std::ptr::null_mut(), |uo| uo.ptr()),
108 cls_context.raw(),
109 pcvoid(&T::IID),
110 queried.as_mut(),
111 )
112 })
113 .map(|_| queried)
114}
115
116/// [`CoInitializeEx`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex)
117/// function, which
118/// [initializes](https://learn.microsoft.com/en-us/windows/win32/learnwin32/initializing-the-com-library)
119/// the COM library. When succeeding, returns an informational error code.
120///
121/// In the original C implementation, you must call
122/// [`CoUninitialize`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-couninitialize)
123/// as a cleanup operation.
124///
125/// Here, the cleanup is performed automatically, because `CoInitializeEx`
126/// returns a [`CoUninitializeGuard`](crate::guard::CoUninitializeGuard), which
127/// automatically calls `CoUninitialize` when the guard goes out of scope. You
128/// must, however, keep the guard alive, otherwise the cleanup will be performed
129/// right away.
130///
131/// # Examples
132///
133/// ```no_run
134/// use winsafe::{self as w, prelude::*, co};
135///
136/// let _com_guard = w::CoInitializeEx( // keep guard alive
137/// co::COINIT::APARTMENTTHREADED
138/// | co::COINIT::DISABLE_OLE1DDE,
139/// )?;
140///
141/// // program runs...
142///
143/// // CoUninitialize() automatically called
144/// # w::HrResult::Ok(())
145/// ```
146#[must_use]
147pub fn CoInitializeEx(coinit: co::COINIT) -> HrResult<CoUninitializeGuard> {
148 unsafe {
149 let hr = co::HRESULT::from_raw(ffi::CoInitializeEx(std::ptr::null_mut(), coinit.raw()));
150 match hr {
151 co::HRESULT::S_OK | co::HRESULT::S_FALSE | co::HRESULT::RPC_E_CHANGED_MODE => {
152 Ok(CoUninitializeGuard::new(hr))
153 },
154 hr => Err(hr),
155 }
156 }
157}
158
159/// [`CoLockObjectExternal`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-colockobjectexternal)
160/// function.
161///
162/// Note that this function will lock the COM object, returning a
163/// [`CoLockObjectExternalGuard`](crate::guard::CoLockObjectExternalGuard). The
164/// unlocking is automatically performed by the guard when it goes out of scope.
165pub fn CoLockObjectExternal<T>(obj: &T) -> HrResult<CoLockObjectExternalGuard<T>>
166where
167 T: ole_IUnknown,
168{
169 unsafe {
170 ok_to_hrresult(ffi::CoLockObjectExternal(obj.ptr(), 1, 0))
171 .map(|_| CoLockObjectExternalGuard::new(obj))
172 }
173}
174
175/// [`CoTaskMemAlloc`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemalloc)
176/// function.
177///
178/// # Examples
179///
180/// ```no_run
181/// use winsafe::{self as w, prelude::*};
182///
183/// let pmem = w::CoTaskMemAlloc(100)?;
184///
185/// // use memory block...
186///
187/// // CoTaskMemFree() automatically called
188/// # w::HrResult::Ok(())
189/// ```
190///
191/// # Related functions
192///
193/// * [`CoTaskMemRealloc`](crate::CoTaskMemRealloc)
194#[must_use]
195pub fn CoTaskMemAlloc(cb: usize) -> HrResult<CoTaskMemFreeGuard> {
196 let p = unsafe { ffi::CoTaskMemAlloc(cb) };
197 if p.is_null() {
198 Err(co::HRESULT::E_OUTOFMEMORY)
199 } else {
200 Ok(unsafe { CoTaskMemFreeGuard::new(p, cb) })
201 }
202}
203
204/// [`CoTaskMemRealloc`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemfree)
205/// function.
206///
207/// Originally this method returns a pointer to the reallocated memory block;
208/// here the original pointer is automatically updated.
209///
210/// # Examples
211///
212/// ```no_run
213/// use winsafe::{self as w, prelude::*};
214///
215/// let mut pmem = w::CoTaskMemAlloc(100)?;
216/// w::CoTaskMemRealloc(&mut pmem, 120)?;
217///
218/// // use memory block...
219///
220/// // CoTaskMemFree() automatically called
221/// # w::HrResult::Ok(())
222/// ```
223///
224/// # Related functions
225///
226/// * [`CoTaskMemAlloc`](crate::CoTaskMemAlloc)
227#[must_use]
228pub fn CoTaskMemRealloc(pv: &mut CoTaskMemFreeGuard, cb: usize) -> HrResult<()> {
229 let (old_pmem, _) = pv.leak();
230 let p = unsafe { ffi::CoTaskMemRealloc(old_pmem, cb) };
231 if p.is_null() {
232 Err(co::HRESULT::E_OUTOFMEMORY)
233 } else {
234 *pv = unsafe { CoTaskMemFreeGuard::new(p, cb) };
235 Ok(())
236 }
237}
238
239/// [`CreateBindCtx`](https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-createbindctx)
240/// function.
241#[must_use]
242pub fn CreateBindCtx() -> HrResult<IBindCtx> {
243 let mut queried = unsafe { IBindCtx::null() };
244 ok_to_hrresult(unsafe { ffi::CreateBindCtx(0, queried.as_mut()) }).map(|_| queried)
245}
246
247/// [`CreateClassMoniker`](https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-createclassmoniker)
248/// function.
249#[must_use]
250pub fn CreateClassMoniker(clsid: &co::CLSID) -> HrResult<IMoniker> {
251 let mut queried = unsafe { IMoniker::null() };
252 ok_to_hrresult(unsafe { ffi::CreateClassMoniker(pcvoid(clsid), queried.as_mut()) })
253 .map(|_| queried)
254}
255
256/// [`CreateFileMoniker`](https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-createfilemoniker)
257/// function.
258#[must_use]
259pub fn CreateFileMoniker(path_name: &str) -> HrResult<IMoniker> {
260 let mut queried = unsafe { IMoniker::null() };
261 ok_to_hrresult(unsafe {
262 ffi::CreateFileMoniker(WString::from_str(path_name).as_ptr(), queried.as_mut())
263 })
264 .map(|_| queried)
265}
266
267/// [`CreateItemMoniker`](https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-createitemmoniker)
268/// function.
269#[must_use]
270pub fn CreateItemMoniker(delim: &str, item: &str) -> HrResult<IMoniker> {
271 let mut queried = unsafe { IMoniker::null() };
272 ok_to_hrresult(unsafe {
273 ffi::CreateItemMoniker(
274 WString::from_str(delim).as_ptr(),
275 WString::from_str(item).as_ptr(),
276 queried.as_mut(),
277 )
278 })
279 .map(|_| queried)
280}
281
282/// [`CreateObjrefMoniker`](https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-createobjrefmoniker)
283/// function.
284#[must_use]
285pub fn CreateObjrefMoniker(unk: &impl ole_IUnknown) -> HrResult<IMoniker> {
286 let mut queried = unsafe { IMoniker::null() };
287 ok_to_hrresult(unsafe { ffi::CreateObjrefMoniker(unk.ptr(), queried.as_mut()) })
288 .map(|_| queried)
289}
290
291/// [`CreatePointerMoniker`](https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-createpointermoniker)
292/// function.
293#[must_use]
294pub fn CreatePointerMoniker(unk: &impl ole_IUnknown) -> HrResult<IMoniker> {
295 let mut queried = unsafe { IMoniker::null() };
296 ok_to_hrresult(unsafe { ffi::CreatePointerMoniker(unk.ptr(), queried.as_mut()) })
297 .map(|_| queried)
298}
299
300/// [`OleInitialize`](https://learn.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-oleinitialize)
301/// function, which calls [`CoInitializeEx`](crate::CoInitializeEx) and enables
302/// OLE operations.
303///
304/// In the original C implementation, you must call
305/// [`OleUninitialize`](https://learn.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-oleuninitialize)
306/// as a cleanup operation.
307///
308/// Here, the cleanup is performed automatically, because `OleInitialize`
309/// returns an [`OleUninitializeGuard`](crate::guard::OleUninitializeGuard),
310/// which automatically calls `OleUninitialize` when the guard goes out of
311/// scope. You must, however, keep the guard alive, otherwise the cleanup will
312/// be performed right away.
313///
314/// # Examples
315///
316/// ```no_run
317/// use winsafe::{self as w, prelude::*, co};
318///
319/// let _ole_guard = w::OleInitialize()?;
320///
321/// // program runs...
322///
323/// // OleUninitialize() automatically called
324/// # w::HrResult::Ok(())
325/// ```
326#[must_use]
327pub fn OleInitialize() -> HrResult<OleUninitializeGuard> {
328 unsafe {
329 ok_to_hrresult(ffi::OleInitialize(std::ptr::null_mut()))
330 .map(|_| OleUninitializeGuard::new())
331 }
332}
333
334/// [`StringFromCLSID`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-stringfromclsid)
335/// function.
336#[must_use]
337pub fn StringFromCLSID(clsid: &co::CLSID) -> HrResult<String> {
338 let mut pstr = std::ptr::null_mut::<u16>();
339 ok_to_hrresult(unsafe { ffi::StringFromCLSID(pcvoid(clsid), &mut pstr) })
340 .map(|_| htaskmem_ptr_to_str(pstr))
341}