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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
//! Low level memory allocation for Windows.
pub mod heap;
use crate::{NSTDAnyMut, NSTDUInt, NSTD_INT_MAX, NSTD_NULL};
use nstdapi::nstdapi;
use windows_sys::Win32::System::Memory::{
GetProcessHeap, HeapAlloc, HeapFree, HeapReAlloc, HEAP_ZERO_MEMORY,
};
/// Describes an error returned from allocation functions for Windows.
#[nstdapi]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum NSTDWindowsAllocError {
/// No error occurred.
NSTD_WINDOWS_ALLOC_ERROR_NONE,
/// Allocating or reallocating failed.
NSTD_WINDOWS_ALLOC_ERROR_OUT_OF_MEMORY,
/// Deallocating memory failed.
NSTD_WINDOWS_ALLOC_ERROR_MEMORY_NOT_FOUND,
/// Getting a handle to a heap failed.
NSTD_WINDOWS_ALLOC_ERROR_HEAP_NOT_FOUND,
/// A heap is invalid.
NSTD_WINDOWS_ALLOC_ERROR_INVALID_HEAP,
/// An allocation function received input parameters that resulted in an invalid memory layout.
NSTD_WINDOWS_ALLOC_ERROR_INVALID_LAYOUT,
}
/// Allocates a new block of memory on the current process' heap.
///
/// # Parameters:
///
/// - `NSTDUInt size` - The number of bytes to allocate.
///
/// # Returns
///
/// `NSTDAnyMut ptr` - A pointer to the block of memory, null on error.
///
/// # Safety
///
/// See <https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc>.
///
/// # Example
///
/// ```
/// use nstd_sys::{
/// core::mem::nstd_core_mem_zero,
/// os::windows::alloc::{
/// nstd_os_windows_alloc_allocate, nstd_os_windows_alloc_deallocate,
/// NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_NONE,
/// },
/// };
///
/// const SIZE: usize = core::mem::size_of::<[u32; 5]>();
///
/// unsafe {
/// let mut buf = nstd_os_windows_alloc_allocate(SIZE);
/// assert!(!buf.is_null());
///
/// nstd_core_mem_zero(buf.cast(), SIZE);
/// assert!(*buf.cast::<[u32; 5]>() == [0u32; 5]);
///
/// assert!(nstd_os_windows_alloc_deallocate(&mut buf) == NSTD_WINDOWS_ALLOC_ERROR_NONE);
/// }
/// ```
#[inline]
#[nstdapi]
pub unsafe fn nstd_os_windows_alloc_allocate(size: NSTDUInt) -> NSTDAnyMut {
if size <= NSTD_INT_MAX as _ {
let heap = GetProcessHeap();
if heap != 0 {
return HeapAlloc(heap, 0, size);
}
}
NSTD_NULL
}
/// Allocates a new block of zero-initialized memory on the current process' heap.
///
/// # Parameters:
///
/// - `NSTDUInt size` - The number of bytes to allocate.
///
/// # Returns
///
/// `NSTDAnyMut ptr` - A pointer to the block of memory, null on error.
///
/// # Safety
///
/// See <https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc>.
///
/// # Example
///
/// ```
/// use nstd_sys::os::windows::alloc::{
/// nstd_os_windows_alloc_allocate_zeroed, nstd_os_windows_alloc_deallocate,
/// NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_NONE,
/// };
///
/// const SIZE: usize = core::mem::size_of::<[i64; 5]>();
///
/// unsafe {
/// let mut buf = nstd_os_windows_alloc_allocate_zeroed(SIZE);
/// assert!(!buf.is_null());
/// assert!(*buf.cast::<[i64; 5]>() == [0i64; 5]);
/// assert!(nstd_os_windows_alloc_deallocate(&mut buf) == NSTD_WINDOWS_ALLOC_ERROR_NONE);
/// }
/// ```
#[inline]
#[nstdapi]
pub unsafe fn nstd_os_windows_alloc_allocate_zeroed(size: NSTDUInt) -> NSTDAnyMut {
if size <= NSTD_INT_MAX as _ {
let heap = GetProcessHeap();
if heap != 0 {
return HeapAlloc(heap, HEAP_ZERO_MEMORY, size);
}
}
NSTD_NULL
}
/// Reallocates a block of memory previously allocated by
/// `nstd_os_windows_alloc_allocate[_zeroed]`.
///
/// If everything goes right, the pointer will point to the new memory location and 0 will be
/// returned. If this is not the case and allocation fails, the pointer will remain untouched and a
/// value of nonzero is returned.
///
/// # Parameters:
///
/// - `NSTDAnyMut *ptr` - A pointer to the allocated memory.
///
/// - `NSTDUInt new_size` - The number of bytes to reallocate.
///
/// # Returns
///
/// `NSTDWindowsAllocError errc` - The allocation operation error code.
///
/// # Safety
///
/// See <https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heaprealloc>.
///
/// # Example
///
/// ```
/// use nstd_sys::os::windows::alloc::{
/// nstd_os_windows_alloc_allocate_zeroed, nstd_os_windows_alloc_deallocate,
/// nstd_os_windows_alloc_reallocate, NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_NONE,
/// };
///
/// const SIZE: usize = core::mem::size_of::<[i16; 10]>();
///
/// unsafe {
/// let mut buf = nstd_os_windows_alloc_allocate_zeroed(SIZE);
/// assert!(!buf.is_null());
/// assert!(*buf.cast::<[i16; 10]>() == [0i16; 10]);
///
/// let mut errc = nstd_os_windows_alloc_reallocate(&mut buf, SIZE / 2);
/// assert!(errc == NSTD_WINDOWS_ALLOC_ERROR_NONE);
/// assert!(*buf.cast::<[i16; 5]>() == [0i16; 5]);
///
/// errc = nstd_os_windows_alloc_deallocate(&mut buf);
/// assert!(errc == NSTD_WINDOWS_ALLOC_ERROR_NONE);
/// }
/// ```
#[nstdapi]
pub unsafe fn nstd_os_windows_alloc_reallocate(
ptr: &mut NSTDAnyMut,
new_size: NSTDUInt,
) -> NSTDWindowsAllocError {
if new_size > NSTD_INT_MAX as _ {
return NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_INVALID_LAYOUT;
}
match GetProcessHeap() {
0 => NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_HEAP_NOT_FOUND,
heap => match HeapReAlloc(heap, 0, *ptr, new_size) {
NSTD_NULL => NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_OUT_OF_MEMORY,
new_mem => {
*ptr = new_mem;
NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_NONE
}
},
}
}
/// Deallocates a block of memory previously allocated by
/// `nstd_os_windows_alloc_allocate[_zeroed]`.
///
/// # Parameters:
///
/// - `NSTDAnyMut *ptr` - A pointer to the allocated memory.
///
/// # Returns
///
/// `NSTDWindowsAllocError errc` - The allocation operation error code.
///
/// # Safety
///
/// See <https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapfree>.
///
/// # Example
///
/// ```
/// use nstd_sys::os::windows::alloc::{
/// nstd_os_windows_alloc_allocate, nstd_os_windows_alloc_deallocate,
/// NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_NONE,
/// };
///
/// unsafe {
/// let mut buf = nstd_os_windows_alloc_allocate(128);
/// assert!(!buf.is_null());
/// assert!(nstd_os_windows_alloc_deallocate(&mut buf) == NSTD_WINDOWS_ALLOC_ERROR_NONE);
/// }
/// ```
#[nstdapi]
pub unsafe fn nstd_os_windows_alloc_deallocate(ptr: &mut NSTDAnyMut) -> NSTDWindowsAllocError {
match GetProcessHeap() {
0 => NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_HEAP_NOT_FOUND,
heap => match HeapFree(heap, 0, *ptr) {
0 => NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_MEMORY_NOT_FOUND,
_ => {
*ptr = NSTD_NULL;
NSTDWindowsAllocError::NSTD_WINDOWS_ALLOC_ERROR_NONE
}
},
}
}