| File: Windows\Win32\System\Com\SAFEARRAY.cs | Web Access |
| Project: src\winforms\src\System.Private.Windows.Core\src\Microsoft.Private.Windows.Core.csproj (Microsoft.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 Windows.Win32.System.Variant; using static Windows.Win32.System.Com.ADVANCED_FEATURE_FLAGS; using static Windows.Win32.System.Variant.VARENUM; namespace Windows.Win32.System.Com; internal unsafe partial struct SAFEARRAY { /// <summary> /// Gets the <see cref="SAFEARRAYBOUND"/> of the <paramref name="dimension"/>. /// </summary> public SAFEARRAYBOUND GetBounds(int dimension = 0) { fixed (void* b = &rgsabound) { return new ReadOnlySpan<SAFEARRAYBOUND>(b, cDims)[dimension]; } } /// <summary> /// Creates an empty one-dimensional SAFEARRAY of type <paramref name="arrayType"/>. /// </summary> public static SAFEARRAY* CreateEmpty(VARENUM arrayType) { SAFEARRAYBOUND saBound = new() { cElements = 0, lLbound = 0 }; return PInvokeCore.SafeArrayCreate(arrayType, 1, &saBound); } public VARENUM VarType { get { // Match CLR behavior. ADVANCED_FEATURE_FLAGS hardwiredType = fFeatures & (FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | FADF_VARIANT); if (hardwiredType == FADF_BSTR && cbElements == sizeof(char*)) { return VT_BSTR; } else if (hardwiredType == FADF_UNKNOWN && cbElements == sizeof(IntPtr)) { return VT_UNKNOWN; } else if (hardwiredType == FADF_DISPATCH && cbElements == sizeof(IntPtr)) { return VT_DISPATCH; } else if (hardwiredType == FADF_VARIANT && cbElements == sizeof(VARIANT)) { return VT_VARIANT; } // Call native API. VARENUM vt = VT_EMPTY; fixed (SAFEARRAY* pThis = &this) { PInvokeCore.SafeArrayGetVartype(pThis, &vt).ThrowOnFailure(); return vt; } } } public T GetValue<T>(Span<int> indices) { // SAFEARRAY is laid out in column-major order. // See https://docs.microsoft.com/previous-versions/windows/desktop/automat/array-manipulation-functions int indicesIndex = 0; int c1 = indices[indicesIndex++]; uint dimensionSize = 1; fixed (void* b = &rgsabound) { ReadOnlySpan<SAFEARRAYBOUND> bounds = new(b, cDims); int boundIndex = cDims - 1; uint cell = 0; for (ushort dim = 1; dim < cDims; dim++) { dimensionSize *= bounds[boundIndex--].cElements; int diff = (indices[indicesIndex++] - bounds[boundIndex].lLbound); cell += (uint)diff * dimensionSize; } cell += (uint)(c1 - bounds[cDims - 1].lLbound); void* v = Unsafe.Add<T>(pvData, (int)cell); return Unsafe.AsRef<T>(v); } } }