/ src / modules / cmdpal / Microsoft.CmdPal.UI / Helpers / GpoValueChecker.cs
GpoValueChecker.cs
 1  // Copyright (c) Microsoft Corporation
 2  // The Microsoft Corporation licenses this file to you under the MIT license.
 3  // See the LICENSE file in the project root for more information.
 4  
 5  using Microsoft.Win32;
 6  
 7  namespace Microsoft.CmdPal.UI.Helpers;
 8  
 9  internal enum GpoRuleConfiguredValue
10  {
11      WrongValue = -3,
12      Unavailable = -2,
13      NotConfigured = -1,
14      Disabled = 0,
15      Enabled = 1,
16  }
17  
18  /*
19   * Contains methods extracted from PowerToys gpo.h
20   * The idea is to keep CmdPal codebase take as little dependences on the PowerToys codebase as possible.
21   * Having this class to check GPO being contained in CmdPal means we don't need to depend on GPOWrapper.
22   */
23  internal static class GpoValueChecker
24  {
25      private const string PoliciesPath = @"SOFTWARE\Policies\PowerToys";
26      private static readonly RegistryKey PoliciesScopeMachine = Registry.LocalMachine;
27      private static readonly RegistryKey PoliciesScopeUser = Registry.CurrentUser;
28      private const string PolicyConfigureEnabledCmdPal = @"ConfigureEnabledUtilityCmdPal";
29      private const string PolicyConfigureEnabledGlobalAllUtilities = @"ConfigureGlobalUtilityEnabledState";
30  
31      private static GpoRuleConfiguredValue GetConfiguredValue(string registryValueName)
32      {
33          // For GPO policies, machine scope should take precedence over user scope
34          var value = ReadRegistryValue(PoliciesScopeMachine, PoliciesPath, registryValueName);
35  
36          if (!value.HasValue)
37          {
38              // If not found in machine scope, check user scope
39              value = ReadRegistryValue(PoliciesScopeUser, PoliciesPath, registryValueName);
40              if (!value.HasValue)
41              {
42                  return GpoRuleConfiguredValue.NotConfigured;
43              }
44          }
45  
46          return value switch
47          {
48              0 => GpoRuleConfiguredValue.Disabled,
49              1 => GpoRuleConfiguredValue.Enabled,
50              _ => GpoRuleConfiguredValue.WrongValue,
51          };
52      }
53  
54      // Reads an integer registry value if it exists.
55      private static int? ReadRegistryValue(RegistryKey rootKey, string subKeyPath, string valueName)
56      {
57          using (RegistryKey? key = rootKey.OpenSubKey(subKeyPath, false))
58          {
59              if (key is null)
60              {
61                  return null;
62              }
63  
64              var value = key.GetValue(valueName);
65              if (value is int intValue)
66              {
67                  return intValue;
68              }
69  
70              return null;
71          }
72      }
73  
74      private static GpoRuleConfiguredValue GetUtilityEnabledValue(string utilityName)
75      {
76          var individualValue = GetConfiguredValue(utilityName);
77  
78          if (individualValue == GpoRuleConfiguredValue.Disabled || individualValue == GpoRuleConfiguredValue.Enabled)
79          {
80              return individualValue;
81          }
82          else
83          {
84              // If the individual utility value is not set, check the global all utilities policy value.
85              return GetConfiguredValue(PolicyConfigureEnabledGlobalAllUtilities);
86          }
87      }
88  
89      internal static GpoRuleConfiguredValue GetConfiguredCmdPalEnabledValue()
90      {
91          return GetUtilityEnabledValue(PolicyConfigureEnabledCmdPal);
92      }
93  }