Skip to main content

edlcodegen_core/
helpers.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::{
5    edl_core_ffi::{GetProcessHeap, HeapAlloc, HeapFree},
6    edl_core_types::{AbiError, BOOL, E_FAIL, E_INVALIDARG, HEAP_ZERO_MEMORY, HRESULT, S_OK},
7};
8use core::ffi::c_void;
9
10pub fn abi_func_to_address(func_ptr: extern "system" fn(*mut c_void) -> *mut c_void) -> u64 {
11    func_ptr as *const () as u64
12}
13
14pub fn proc_address_to_isize(
15    func_ptr: unsafe extern "system" fn(*mut c_void) -> *mut c_void,
16) -> isize {
17    func_ptr as *const () as isize
18}
19
20#[inline(always)]
21pub fn hresult_to_pvoid(hr: i32) -> *mut c_void {
22    ((hr as u64) & 0x0000_0000_FFFF_FFFF) as usize as *mut c_void
23}
24
25#[inline(always)]
26pub fn pvoid_to_hresult(ptr: *mut c_void) -> i32 {
27    ((ptr as u64) & 0x0000_0000_FFFF_FFFF) as i32
28}
29
30pub fn allocate_memory(size: usize) -> *mut c_void {
31    unsafe { HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size) }
32}
33
34pub fn deallocate_memory(mem: *mut c_void) -> HRESULT {
35    if mem.is_null() {
36        return HRESULT(S_OK);
37    }
38
39    let res = unsafe { BOOL(HeapFree(GetProcessHeap(), 0, mem as *const c_void)) };
40
41    if !res.as_bool() {
42        return HRESULT(E_FAIL);
43    }
44
45    HRESULT(S_OK)
46}
47
48/// A allocation function that can be called via `CallEnclave`.
49#[unsafe(no_mangle)]
50pub extern "system" fn allocate_memory_ffi(context: *mut c_void) -> *mut c_void {
51    allocate_memory(context as usize)
52}
53
54/// A deallocation function that can be called via `CallEnclave`.
55#[unsafe(no_mangle)]
56pub extern "system" fn deallocate_memory_ffi(memory: *mut c_void) -> *mut c_void {
57    let hr = deallocate_memory(memory);
58    hr.0 as *mut c_void
59}
60
61/// Performs a raw memory copy from a Rust slice into a raw buffer.
62pub fn copy_slice_to_buffer<T>(buffer: *mut c_void, data: &[T]) -> Result<(), AbiError> {
63    if buffer.is_null() {
64        return Err(AbiError::Hresult(E_INVALIDARG));
65    }
66
67    // SAFETY: caller guarantees buffer is valid and non-overlapping
68    unsafe {
69        core::ptr::copy_nonoverlapping(data.as_ptr(), buffer as *mut T, data.len());
70    }
71
72    Ok(())
73}
74
75#[macro_export]
76macro_rules! return_hr_as_pvoid {
77    ($result:expr) => {{
78        if let Some(err) = $result.err() {
79            return $crate::helpers::hresult_to_pvoid(err.to_hresult().0);
80        }
81
82        return $crate::edl_core_types::S_OK as *mut core::ffi::c_void;
83    }};
84}
85
86pub fn assign_if_some<T>(dst: Option<&mut T>, src: Option<T>) {
87    if let (Some(dst_obj), Some(src_obj)) = (dst, src) {
88        *dst_obj = src_obj;
89    }
90}