File: Windows\Win32\Foundation\GlobalBuffer.cs
Web Access
Project: src\src\System.Private.Windows.Core\src\System.Private.Windows.Core.csproj (System.Private.Windows.Core)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Runtime.InteropServices;
using Windows.Win32.System.Memory;
 
namespace System.Private.Windows.Ole;
 
/// <summary>
///  Simple scope for writing to HGLOBAL memory.
/// </summary>
internal unsafe ref struct GlobalBuffer
{
    private void* _pointer;
    private Span<byte> _buffer;
    private HGLOBAL _hglobal;
 
    public GlobalBuffer(HGLOBAL hglobal, uint length)
    {
        if (hglobal.IsNull)
        {
            Status = HRESULT.E_INVALIDARG;
            return;
        }
 
        _hglobal = PInvokeCore.GlobalReAlloc(
            hglobal,
            length,
            (uint)GLOBAL_ALLOC_FLAGS.GMEM_MOVEABLE);
 
        if (_hglobal.IsNull)
        {
            Status = HRESULT.E_OUTOFMEMORY;
            return;
        }
 
        _pointer = PInvokeCore.GlobalLock(_hglobal);
        if (_pointer is null)
        {
            Status = HRESULT.E_OUTOFMEMORY;
        }
 
        _buffer = new((byte*)_pointer, (int)length);
    }
 
    public HRESULT Status { get; private set; } = HRESULT.S_OK;
    public readonly void* Pointer => _pointer;
 
    public readonly Span<byte> AsSpan() => _buffer;
 
    public readonly Span<char> AsCharSpan() => MemoryMarshal.Cast<byte, char>(_buffer);
 
    public void Dispose()
    {
        if (!_hglobal.IsNull)
        {
            PInvokeCore.GlobalUnlock(_hglobal);
            _buffer = default;
            _pointer = null;
            _hglobal = HGLOBAL.Null;
        }
    }
}