windows_strings/
hstring_header.rs1use super::*;
2
3pub const HSTRING_REFERENCE_FLAG: u32 = 1;
4
5#[repr(C)]
6pub struct HStringHeader {
7 pub flags: u32,
8 pub len: u32,
9 pub _0: u32,
10 pub _1: u32,
11 pub data: *mut u16,
12 pub count: RefCount,
13 pub buffer_start: u16,
14}
15
16impl HStringHeader {
17 pub fn alloc(len: u32) -> *mut Self {
18 if len == 0 {
19 return core::ptr::null_mut();
20 }
21
22 let bytes = core::mem::size_of::<Self>() + 2 * len as usize;
25
26 let header =
27 unsafe { bindings::HeapAlloc(bindings::GetProcessHeap(), 0, bytes) } as *mut Self;
28
29 if header.is_null() {
30 panic!("allocation failed");
31 }
32
33 unsafe {
34 header.write(core::mem::MaybeUninit::<Self>::zeroed().assume_init());
36 (*header).len = len;
37 (*header).count = RefCount::new(1);
38 (*header).data = &mut (*header).buffer_start;
39 }
40
41 header
42 }
43
44 pub unsafe fn free(header: *mut Self) {
45 if header.is_null() {
46 return;
47 }
48
49 unsafe {
50 bindings::HeapFree(bindings::GetProcessHeap(), 0, header as *mut _);
51 }
52 }
53
54 pub fn duplicate(&self) -> *mut Self {
55 if self.flags & HSTRING_REFERENCE_FLAG == 0 {
56 self.count.add_ref();
58 self as *const Self as *mut Self
59 } else {
60 let copy = Self::alloc(self.len);
62 unsafe {
65 core::ptr::copy_nonoverlapping(self.data, (*copy).data, self.len as usize + 1);
66 }
67 copy
68 }
69 }
70}