From 3c20988f2991b1329773312dad22ed46f893f06e Mon Sep 17 00:00:00 2001 From: dahall Date: Tue, 10 Nov 2020 21:38:59 -0700 Subject: [PATCH] Changed params to GetLogicalProcessorInformationEx overload to return RefEnumerator --- PInvoke/Kernel32/SysInfoApi.cs | 43 ++++++++++++++++++++++++++---- UnitTests/PInvoke/Kernel32/SysInfoTests.cs | 32 +++++++++++++++++++--- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/PInvoke/Kernel32/SysInfoApi.cs b/PInvoke/Kernel32/SysInfoApi.cs index c3865f05..be0239fc 100644 --- a/PInvoke/Kernel32/SysInfoApi.cs +++ b/PInvoke/Kernel32/SysInfoApi.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -1224,8 +1226,9 @@ namespace Vanara.PInvoke /// /// /// + /// The memory allocated for the results in . /// - /// An array of SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX structures. If the function fails, the contents of this buffer are undefined. + /// An array of SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pointers. If the function fails, the contents of this buffer are undefined. /// /// /// @@ -1234,14 +1237,27 @@ namespace Vanara.PInvoke /// /// If the function fails, the return value has error information. /// - public static Win32Error GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, out SafeNativeLinkedList info) + public static unsafe Win32Error GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, out SafeCoTaskMemHandle mem, out RefEnumerator info) { info = default; + mem = default; uint sz = 0; var err = BoolToLastErr(GetLogicalProcessorInformationEx(RelationshipType, IntPtr.Zero, ref sz) || sz > 0); if (err.Failed && err != Win32Error.ERROR_INSUFFICIENT_BUFFER) return err; - info = new SafeNativeLinkedList(sz) { GetNextSizeMethod = i => (long)i.Size }; - return BoolToLastErr(GetLogicalProcessorInformationEx(RelationshipType, info, ref sz)); + mem = new SafeCoTaskMemHandle(sz); + err = BoolToLastErr(GetLogicalProcessorInformationEx(RelationshipType, mem, ref sz)); + if (err.Succeeded) + { + var ret = new List(); + for (IntPtr pCurrent = mem, pEnd = pCurrent.Offset(sz); pCurrent.ToInt64() < pEnd.ToInt64() && pCurrent != IntPtr.Zero;) + { + ret.Add(pCurrent); + pCurrent = pCurrent.Offset(pCurrent.ToStructure().Size); + } + mem.Write(ret, true, (int)sz); + info = new RefEnumerator((SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)mem.DangerousGetHandle().Offset(sz), ret.Count); + } + return err; } /// @@ -3577,7 +3593,7 @@ namespace Vanara.PInvoke // Processor; NUMA_NODE_RELATIONSHIP NumaNode; CACHE_RELATIONSHIP Cache; GROUP_RELATIONSHIP Group; } DUMMYUNIONNAME; } // SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; [PInvokeData("winnt.h", MSDNShortId = "6ff16cda-c1dc-4d5c-ac60-756653cd6b07")] - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{DebugString}")] public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { /// @@ -3650,6 +3666,23 @@ namespace Vanara.PInvoke /// [FieldOffset(0)] public GROUP_RELATIONSHIP Group; } + + internal string DebugString + { + get + { + uint c = Relationship switch + { + LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore => RelationUnion.Processor.GroupCount, + LOGICAL_PROCESSOR_RELATIONSHIP.RelationNumaNode => RelationUnion.NumaNode.NodeNumber, + LOGICAL_PROCESSOR_RELATIONSHIP.RelationCache => RelationUnion.Cache.CacheSize, + LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorPackage => RelationUnion.Processor.GroupCount, + LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup => RelationUnion.Group.ActiveGroupCount, + _ => 0 + }; + return $"{Relationship}, Size={Size}, Count={c}"; + } + } } /// Used by GetProcessorSystemCycleTime. diff --git a/UnitTests/PInvoke/Kernel32/SysInfoTests.cs b/UnitTests/PInvoke/Kernel32/SysInfoTests.cs index e37d84cb..155e6724 100644 --- a/UnitTests/PInvoke/Kernel32/SysInfoTests.cs +++ b/UnitTests/PInvoke/Kernel32/SysInfoTests.cs @@ -55,9 +55,35 @@ namespace Vanara.PInvoke.Tests [Test] public void GetLogicalProcessorInformationExTest() { - Assert.That(GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationAll, out var info), ResultIs.Successful); - Assert.That(info.Count, Is.GreaterThan(0)); - info.WriteValues(); + unsafe + { + Assert.That(GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup, out var mem, out var info), ResultIs.Successful); + using (mem) + { + Assert.That(info.Count, Is.GreaterThan(0)); + for (int i = 0; i < info.Count; i++) + { + switch (info[i].Relationship) + { + case LOGICAL_PROCESSOR_RELATIONSHIP.RelationNumaNode: + info[i].RelationUnion.NumaNode.WriteValues(); + break; + case LOGICAL_PROCESSOR_RELATIONSHIP.RelationCache: + info[i].RelationUnion.Cache.WriteValues(); + break; + case LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore: + case LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorPackage: + info[i].RelationUnion.Processor.WriteValues(); + break; + case LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup: + info[i].RelationUnion.Group.WriteValues(); + break; + default: + break; + } + } + } + } } [Test]