summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dwrote/src/com_helpers.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/dwrote/src/com_helpers.rs
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/dwrote/src/com_helpers.rs')
-rw-r--r--third_party/rust/dwrote/src/com_helpers.rs127
1 files changed, 127 insertions, 0 deletions
diff --git a/third_party/rust/dwrote/src/com_helpers.rs b/third_party/rust/dwrote/src/com_helpers.rs
new file mode 100644
index 0000000000..b4bcf16641
--- /dev/null
+++ b/third_party/rust/dwrote/src/com_helpers.rs
@@ -0,0 +1,127 @@
+// This is only handy for implementing a single-interface-implementing IUnknown.
+
+macro_rules! implement_iunknown {
+ ($interface:ident, $typ:ident) => {
+ IUnknownVtbl {
+ QueryInterface: {
+ #[allow(non_snake_case)]
+ unsafe extern "system" fn QueryInterface(
+ unknown_this: *mut IUnknown,
+ riid: REFIID,
+ ppv_object: *mut *mut c_void,
+ ) -> HRESULT {
+ use $crate::winapi::Interface;
+ let this = if $crate::winapi::shared::guiddef::IsEqualGUID(
+ &*riid,
+ &$interface::uuidof(),
+ ) {
+ mem::transmute(unknown_this)
+ } else if $crate::winapi::shared::guiddef::IsEqualGUID(
+ &*riid,
+ &IUnknown::uuidof(),
+ ) {
+ mem::transmute(unknown_this)
+ } else {
+ return $crate::winapi::shared::winerror::E_NOINTERFACE;
+ };
+
+ (*unknown_this).AddRef();
+ *ppv_object = this;
+ return S_OK;
+ }
+ QueryInterface
+ },
+ AddRef: {
+ unsafe extern "system" fn AddRef(unknown_this: *mut IUnknown) -> ULONG {
+ let this = $typ::from_interface(unknown_this);
+ let count = this.refcount.fetch_add(1, atomic::Ordering::Relaxed) + 1;
+ count as ULONG
+ }
+ AddRef
+ },
+ Release: {
+ unsafe extern "system" fn Release(unknown_this: *mut IUnknown) -> ULONG {
+ let this = $typ::from_interface(unknown_this);
+ let count = this.refcount.fetch_sub(1, atomic::Ordering::Release) - 1;
+ if count == 0 {
+ <$typ as Com<$interface>>::destroy(unknown_this as *mut $interface);
+ }
+ count as ULONG
+ }
+ Release
+ },
+ }
+ };
+ (static $interface:ident, $typ:ident) => {
+ IUnknownVtbl {
+ QueryInterface: {
+ #[allow(non_snake_case)]
+ unsafe extern "system" fn QueryInterface(
+ unknown_this: *mut IUnknown,
+ riid: REFIID,
+ ppvObject: *mut *mut $crate::winapi::ctypes::c_void,
+ ) -> HRESULT {
+ use $crate::winapi::Interface;
+ let this = if $crate::winapi::shared::guiddef::IsEqualGUID(
+ &*riid,
+ &$interface::uuidof(),
+ ) {
+ mem::transmute(unknown_this)
+ } else if $crate::winapi::shared::guiddef::IsEqualGUID(
+ &*riid,
+ &IUnknown::uuidof(),
+ ) {
+ mem::transmute(unknown_this)
+ } else {
+ return $crate::winapi::shared::winerror::E_NOINTERFACE;
+ };
+
+ (*unknown_this).AddRef();
+ *ppvObject = this;
+ return S_OK;
+ }
+ QueryInterface
+ },
+ AddRef: {
+ // FIXME(pcwalton): Uh? Maybe we should actually reference count?
+ #[allow(non_snake_case)]
+ unsafe extern "system" fn AddRef(_: *mut IUnknown) -> ULONG {
+ 1
+ }
+ AddRef
+ },
+ Release: {
+ #[allow(non_snake_case)]
+ unsafe extern "system" fn Release(_: *mut IUnknown) -> ULONG {
+ 1
+ }
+ Release
+ },
+ }
+ };
+}
+
+#[repr(C)]
+pub struct ComRepr<Type, Vtbl>(*const Vtbl, Type);
+
+pub trait Com<Interface>
+where
+ Self: Sized,
+{
+ type Vtbl: 'static;
+
+ fn vtbl() -> &'static Self::Vtbl;
+
+ fn into_interface(self) -> *mut Interface {
+ let com = Box::new(ComRepr(Self::vtbl(), self));
+ Box::into_raw(com) as *mut Interface
+ }
+
+ unsafe fn from_interface<'a>(thing: *mut Interface) -> &'a mut Self {
+ &mut (*(thing as *mut ComRepr<Self, Self::Vtbl>)).1
+ }
+
+ unsafe fn destroy(thing: *mut Interface) {
+ Box::from_raw(thing as *mut ComRepr<Self, Self::Vtbl>);
+ }
+}