| File: System\Diagnostics\PerformanceDataRegistryKey.cs | Web Access |
| Project: src\runtime\src\libraries\System.Diagnostics.PerformanceCounter\src\System.Diagnostics.PerformanceCounter.csproj (System.Diagnostics.PerformanceCounter) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Buffers; using System.IO; using System.Runtime.InteropServices; using Internal.Win32.SafeHandles; using Microsoft.Win32; namespace System.Diagnostics { internal sealed class PerformanceDataRegistryKey : IDisposable { private const int PerformanceData = (int)RegistryHive.PerformanceData; private readonly SafeRegistryHandle _hkey; private PerformanceDataRegistryKey(SafeRegistryHandle hkey) { _hkey = hkey; } public static PerformanceDataRegistryKey OpenRemoteBaseKey(string machineName) { // connect to the specified remote registry int ret = Interop.Advapi32.RegConnectRegistry(machineName, new IntPtr(PerformanceData), out SafeRegistryHandle foreignHKey); if (ret == 0 && !foreignHKey.IsInvalid) { return new PerformanceDataRegistryKey(foreignHKey); } foreignHKey.Dispose(); if (ret == Interop.Errors.ERROR_DLL_INIT_FAILED) { // return value indicates an error occurred throw new ArgumentException(SR.Format(SR.Arg_DllInitFailure, machineName)); } if (ret != 0) { Win32Error(ret, null); } // return value indicates an error occurred throw new ArgumentException(SR.Format(SR.Arg_RegKeyNoRemoteConnect, machineName)); } public static PerformanceDataRegistryKey OpenLocal() { var key = new SafeRegistryHandle(new IntPtr(PerformanceData), ownsHandle: true); return new PerformanceDataRegistryKey(key); } public byte[] GetValue(string name, bool usePool) { int size = 65000; int sizeInput = size; int ret; int type = 0; byte[] data = CreateBlob(size, usePool); while (Interop.Errors.ERROR_MORE_DATA == (ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, lpReserved: null, ref type, data, ref sizeInput))) { if (size == int.MaxValue) { ReleaseData(data, usePool); // ERROR_MORE_DATA was returned however we cannot increase the buffer size beyond Int32.MaxValue Win32Error(ret, name); } else if (size > (int.MaxValue / 2)) { // at this point in the loop "size * 2" would cause an overflow size = int.MaxValue; } else { size *= 2; } sizeInput = size; ReleaseData(data, usePool); data = CreateBlob(size, usePool); } if (ret != 0) { ReleaseData(data, usePool); Win32Error(ret, name); } return data; } internal static void ReleaseData(byte[] data, bool usePool = true) { if (usePool) { ArrayPool<byte>.Shared.Return(data); } } public void Close() { Dispose(); } public void Dispose() { _hkey.Dispose(); } private static byte[] CreateBlob(int size, in bool usePool) { return usePool ? ArrayPool<byte>.Shared.Rent(size) : new byte[size]; } private static void Win32Error(in int errorCode, string name) { if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED) { throw new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_RegistryKeyGeneric_Key, name)); } throw new IOException(Interop.Kernel32.GetMessage(errorCode), errorCode); } } }