use super::*;
use winapi::um::{
minwinbase::{LHND, LMEM_FIXED, LMEM_INVALID_HANDLE, LMEM_MOVEABLE, LPTR},
winbase::{
LocalAlloc, LocalFlags, LocalFree, LocalHandle, LocalLock, LocalReAlloc,
LocalSize, LocalUnlock,
},
};
#[derive(Debug, Clone, Copy)]
#[repr(u32)]
pub enum LocalAllocFlags {
Fixed = LMEM_FIXED,
ZeroedFixed = LPTR,
Movable = LMEM_MOVEABLE,
ZeroedMovable = LHND,
}
impl Default for LocalAllocFlags {
fn default() -> Self {
LocalAllocFlags::Fixed
}
}
pub unsafe fn local_alloc(
flags: LocalAllocFlags,
bytes: usize,
) -> Result<HLOCAL, ErrorCode> {
let handle = LocalAlloc(flags as u32, bytes);
if !handle.is_null() {
Ok(handle)
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn local_realloc(
handle: HLOCAL,
size: usize,
flags: u32,
) -> Result<HLOCAL, ErrorCode> {
let output = LocalReAlloc(handle, size, flags);
if !output.is_null() {
Ok(output)
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn local_free(handle: HLOCAL) -> Result<(), ErrorCode> {
let output = LocalFree(handle);
if output.is_null() {
Ok(())
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn local_lock(handle: HLOCAL) -> Result<*mut c_void, ErrorCode> {
let output = LocalLock(handle) as *mut c_void;
if !output.is_null() {
Ok(output)
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn local_unlock(handle: HLOCAL) -> Result<bool, ErrorCode> {
let output = LocalUnlock(handle);
if output != 0 {
Ok(true)
} else {
let e = get_last_error();
if e.0 == NO_ERROR {
Ok(false)
} else {
Err(e)
}
}
}
#[inline]
pub unsafe fn local_flags(handle: HLOCAL) -> Result<u32, ErrorCode> {
let output = LocalFlags(handle);
if output != LMEM_INVALID_HANDLE {
Ok(output)
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn local_size(handle: HLOCAL) -> Result<usize, ErrorCode> {
let output = LocalSize(handle);
if output != 0 {
Ok(output)
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn local_handle(ptr: *mut c_void) -> Result<HLOCAL, ErrorCode> {
let output = LocalHandle(ptr as *mut _);
if !output.is_null() {
Ok(output)
} else {
Err(get_last_error())
}
}
#[derive(Debug)]
pub(crate) struct OwnedLocalHandle(HLOCAL);
#[allow(dead_code)]
impl OwnedLocalHandle {
pub const unsafe fn new(handle: HLOCAL) -> Self {
Self(handle)
}
pub const unsafe fn as_hlocal(&self) -> HLOCAL {
self.0
}
pub fn into_inner(self) -> HLOCAL {
let out = self.0;
core::mem::forget(self);
out
}
}
impl Drop for OwnedLocalHandle {
fn drop(&mut self) {
let free_result = unsafe { local_free(self.0) };
if cfg!(debug_assertions) {
free_result.unwrap();
} else {
free_result.ok();
};
}
}
pub(crate) struct FixedLocalSlice<T> {
handle: OwnedLocalHandle,
data_type: PhantomData<T>,
count: usize,
}
impl<T> FixedLocalSlice<T> {
pub const unsafe fn new(handle: OwnedLocalHandle, count: usize) -> Self {
Self {
handle,
count,
data_type: PhantomData,
}
}
}
impl<T> Deref for FixedLocalSlice<T> {
type Target = [T];
fn deref(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.handle.0 as *const T, self.count) }
}
}