Skip to content

Commit

Permalink
Tool 0.3.2
Browse files Browse the repository at this point in the history
Persistence improvements, argument handling fixes, dictionary locating improved
  • Loading branch information
thebookisclosed committed Oct 19, 2022
1 parent f98ac99 commit 56e0bb4
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 33 deletions.
6 changes: 3 additions & 3 deletions ViVeTool/ArgumentBlock.cs
Expand Up @@ -65,11 +65,10 @@ internal static void Initialize(string[] args, ArgumentBlockFlags flags)
for (int i = 1; i < args.Length && flags != 0; i++)
{
var firstSc = args[i].IndexOf(':');
//if (firstSc == -1) continue;
var hasValue = firstSc != -1;
var lower = args[i].ToLowerInvariant();
var key = hasValue ? lower.Substring(0, firstSc) : lower;
var value = hasValue ? args[i].Substring(firstSc + 1) : null;
var value = hasValue ? args[i].Substring(firstSc + 1) : string.Empty;
if (flags.HasFlag(ArgumentBlockFlags.Store) && key == "/store")
{
if (Enum.TryParse(value, true, out FeatureConfigurationTypeEx parsedStore))
Expand Down Expand Up @@ -142,7 +141,8 @@ internal static void Initialize(string[] args, ArgumentBlockFlags flags)
}
else if (flags.HasFlag(ArgumentBlockFlags.Priority) && key == "/priority")
{
if (!Enum.TryParse(value, true, out RTL_FEATURE_CONFIGURATION_PRIORITY parsedPriority))
if (!Enum.TryParse(value, true, out RTL_FEATURE_CONFIGURATION_PRIORITY parsedPriority) ||
((int)parsedPriority < 1 || (int)parsedPriority > 14))
{
ConsoleEx.WriteErrorLine(Properties.Resources.InvalidEnumSpec, value, "Priority");
HelpMode = true;
Expand Down
9 changes: 5 additions & 4 deletions ViVeTool/FeatureNaming.cs
Expand Up @@ -25,13 +25,14 @@ namespace Albacore.ViVeTool
internal class FeatureNaming
{
internal const string DictFileName = "FeatureDictionary.pfs";
internal static string DictFilePath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), DictFileName);
internal static List<uint> FindIdsForNames(IEnumerable<string> featureNames)
{
if (!File.Exists(DictFileName))
if (!File.Exists(DictFilePath))
return null;
var result = new List<uint>();
var namesCommas = featureNames.Select(x => x.ToLowerInvariant() + ",").ToList();
using (StreamReader reader = new StreamReader(File.OpenRead(DictFileName)))
using (StreamReader reader = new StreamReader(File.OpenRead(DictFilePath)))
{
while (!reader.EndOfStream)
{
Expand All @@ -55,10 +56,10 @@ internal static List<uint> FindIdsForNames(IEnumerable<string> featureNames)
internal static Dictionary<uint, string> FindNamesForFeatures(IEnumerable<uint> featureIDs)
{
var result = new Dictionary<uint, string>();
if (!File.Exists(DictFileName))
if (!File.Exists(DictFilePath))
return null;
var idsCommas = featureIDs.Select(x => "," + x.ToString()).ToList();
using (StreamReader reader = new StreamReader(File.OpenRead(DictFileName)))
using (StreamReader reader = new StreamReader(File.OpenRead(DictFilePath)))
{
while (!reader.EndOfStream)
{
Expand Down
81 changes: 73 additions & 8 deletions ViVeTool/Program.cs
Expand Up @@ -120,6 +120,9 @@ static void ProcessArgs(string[] args)
ArgumentBlock.Initialize(args, 0);
HandleFixLKG();
break;
case "/fixpriority":
HandleFixPriority();
break;
case "/appupdate":
HandleAppUpdate();
break;
Expand Down Expand Up @@ -183,7 +186,8 @@ static void HandleQuery()
foreach (var config in retrievedConfigs)
{
string name = null;
try { name = namesAll[config.FeatureId]; } catch { }
if (namesAll != null)
try { name = namesAll[config.FeatureId]; } catch { }
PrintFeatureConfig(config, name);
}
}
Expand All @@ -199,7 +203,8 @@ static void HandleQuery()
if (config != null)
{
string name = null;
try { name = namesSpecific[id]; } catch { }
if (namesSpecific != null)
try { name = namesSpecific[id]; } catch { }
PrintFeatureConfig(config.Value, name);
}
else
Expand Down Expand Up @@ -234,7 +239,7 @@ static void HandleSet(RTL_FEATURE_ENABLED_STATE state)
FeatureId = ArgumentBlock.IdList[i],
EnabledState = state,
EnabledStateOptions = fcp.EnabledStateOptions,
Priority = fcp.Priority ?? RTL_FEATURE_CONFIGURATION_PRIORITY.Service,
Priority = fcp.Priority ?? RTL_FEATURE_CONFIGURATION_PRIORITY.User,
Variant = fcp.Variant,
VariantPayloadKind = fcp.VariantPayloadKind,
VariantPayload = fcp.VariantPayload,
Expand Down Expand Up @@ -315,7 +320,8 @@ static void HandleQuerySubs()
foreach (var sub in retrievedSubs)
{
string name = null;
try { name = names[sub.FeatureId]; } catch { }
if (names != null)
try { name = names[sub.FeatureId]; } catch { }
PrintSubscription(sub, name);
}
}
Expand Down Expand Up @@ -533,6 +539,14 @@ static void HandleFixLKG()
Console.WriteLine(Properties.Resources.FixLKGNotNeeded);
}

static void HandleFixPriority()
{
var success = FixPriorityInternal(RTL_FEATURE_CONFIGURATION_TYPE.Runtime);
if (!success)
return;
FixPriorityInternal(RTL_FEATURE_CONFIGURATION_TYPE.Boot);
}

static void HandleAppUpdate()
{
Console.WriteLine(Properties.Resources.CheckingAppUpdates);
Expand Down Expand Up @@ -605,7 +619,7 @@ static void FindResettablesInternal(RTL_FEATURE_CONFIGURATION_TYPE type, bool fu
}
}

static void FinalizeSet(RTL_FEATURE_CONFIGURATION_UPDATE[] updates, bool isReset)
static bool FinalizeSet(RTL_FEATURE_CONFIGURATION_UPDATE[] updates, bool isReset)
{
var useBothStores = ArgumentBlock.ShouldUseBothStores;
if (useBothStores || ArgumentBlock.Store == FeatureConfigurationTypeEx.Runtime)
Expand All @@ -615,7 +629,7 @@ static void FinalizeSet(RTL_FEATURE_CONFIGURATION_UPDATE[] updates, bool isReset
{
ConsoleEx.WriteErrorLine(isReset ? Properties.Resources.ResetRuntimeFailed : Properties.Resources.SetRuntimeFailed,
GetHumanErrorDescription(result));
return;
return false;
}
}
if (useBothStores || ArgumentBlock.Store == FeatureConfigurationTypeEx.Boot)
Expand All @@ -625,13 +639,14 @@ static void FinalizeSet(RTL_FEATURE_CONFIGURATION_UPDATE[] updates, bool isReset
{
ConsoleEx.WriteErrorLine(isReset ? Properties.Resources.ResetBootFailed : Properties.Resources.SetBootFailed,
GetHumanErrorDescription(result));
return;
return false;
}

UpdateLKGStatus(BSD_FEATURE_CONFIGURATION_STATE.BootPending);
}

Console.WriteLine(isReset ? Properties.Resources.ResetSuccess : Properties.Resources.SetSuccess);
return true;
}

static void UpdateLKGStatus(BSD_FEATURE_CONFIGURATION_STATE newStatus)
Expand Down Expand Up @@ -708,6 +723,53 @@ static RTL_FEATURE_CONFIGURATION_UPDATE[] ConvertConfigsToUpdates(List<RTL_FEATU
return updates;
}

static bool FixPriorityInternal(RTL_FEATURE_CONFIGURATION_TYPE configurationType)
{
Console.WriteLine(Properties.Resources.FixPriorityProcessing, configurationType);
var features = FeatureManager.QueryAllFeatureConfigurations(configurationType);
var fixUpdates = MakePriorityFixUpdates(features);
if (fixUpdates == null)
{
Console.WriteLine(Properties.Resources.FixPriorityNotNeeded);
return true;
}
ArgumentBlock.Store = (FeatureConfigurationTypeEx)configurationType;
var success = FinalizeSet(fixUpdates, false);
if (configurationType == RTL_FEATURE_CONFIGURATION_TYPE.Boot)
Console.WriteLine(Properties.Resources.RebootRecommended);
return success;
}

static RTL_FEATURE_CONFIGURATION_UPDATE[] MakePriorityFixUpdates(RTL_FEATURE_CONFIGURATION[] configurations)
{
var configsToFix = configurations.Where(x => x.Priority == RTL_FEATURE_CONFIGURATION_PRIORITY.Service && !x.IsWexpConfiguration);
if (!configsToFix.Any())
return null;
var priorityFixUpdates = new RTL_FEATURE_CONFIGURATION_UPDATE[configsToFix.Count() * 2];
var updatesCreated = 0;
foreach (var cfg in configsToFix)
{
priorityFixUpdates[updatesCreated] = new RTL_FEATURE_CONFIGURATION_UPDATE()
{
FeatureId = cfg.FeatureId,
Priority = cfg.Priority,
Operation = RTL_FEATURE_CONFIGURATION_OPERATION.ResetState
};
priorityFixUpdates[updatesCreated + 1] = new RTL_FEATURE_CONFIGURATION_UPDATE()
{
FeatureId = cfg.FeatureId,
Priority = RTL_FEATURE_CONFIGURATION_PRIORITY.User,
EnabledState = cfg.EnabledState,
Variant = cfg.Variant,
VariantPayloadKind = cfg.VariantPayloadKind,
VariantPayload = cfg.VariantPayload,
Operation = RTL_FEATURE_CONFIGURATION_OPERATION.FeatureState | RTL_FEATURE_CONFIGURATION_OPERATION.VariantState
};
updatesCreated += 2;
}
return priorityFixUpdates;
}

static void CommandMigrationInfoTip(string oldCommand, string newCommand)
{
ConsoleEx.WriteWarnLine(Properties.Resources.CommandMigrationNote, oldCommand, newCommand);
Expand Down Expand Up @@ -735,7 +797,10 @@ static void PrintFeatureConfig(RTL_FEATURE_CONFIGURATION config, string name = n
Console.Write(" ({0})", name);
Console.WriteLine();
Console.ForegroundColor = defaultFg;
Console.WriteLine(Properties.Resources.FeatureDisplay_Priority, config.Priority, (uint)config.Priority);
if (Enum.IsDefined(typeof(RTL_FEATURE_CONFIGURATION_PRIORITY), config.Priority))
Console.WriteLine(Properties.Resources.FeatureDisplay_Priority + " ({1})", config.Priority, (uint)config.Priority);
else
Console.WriteLine(Properties.Resources.FeatureDisplay_Priority, config.Priority, (uint)config.Priority);
Console.WriteLine(Properties.Resources.FeatureDisplay_State, config.EnabledState, (uint)config.EnabledState);
Console.WriteLine(Properties.Resources.FeatureDisplay_Type,
config.IsWexpConfiguration ? Properties.Resources.FeatureType_Experiment : Properties.Resources.FeatureType_Override,
Expand Down
4 changes: 2 additions & 2 deletions ViVeTool/Properties/AssemblyInfo.cs
Expand Up @@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.3.1.0")]
[assembly: AssemblyFileVersion("0.3.1.0")]
[assembly: AssemblyVersion("0.3.2.0")]
[assembly: AssemblyFileVersion("0.3.2.0")]
31 changes: 24 additions & 7 deletions ViVeTool/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 15 additions & 7 deletions ViVeTool/Properties/Resources.resx
Expand Up @@ -121,7 +121,7 @@
<value>Boot store changes require a reboot to fully take effect, please do so if a configuration appears to be missing</value>
</data>
<data name="Branding" xml:space="preserve">
<value>ViVeTool v0.3.1 - Windows feature configuration tool
<value>ViVeTool v0.3.2 - Windows feature configuration tool
</value>
</data>
<data name="ChangestampDisplay" xml:space="preserve">
Expand Down Expand Up @@ -160,7 +160,7 @@ Arguments are now position independent and clearly labeled, ambiguous strings of
<value>PayloadKind : {0} ({1})</value>
</data>
<data name="FeatureDisplay_Priority" xml:space="preserve">
<value>Priority : {0} ({1})</value>
<value>Priority : {0}</value>
</data>
<data name="FeatureDisplay_State" xml:space="preserve">
<value>State : {0} ({1})</value>
Expand All @@ -183,6 +183,12 @@ Arguments are now position independent and clearly labeled, ambiguous strings of
<data name="FixLKGPerformed" xml:space="preserve">
<value>'Last Known Good' rollback system data has been fixed successfully</value>
</data>
<data name="FixPriorityNotNeeded" xml:space="preserve">
<value>No configurations in this store need to be moved</value>
</data>
<data name="FixPriorityProcessing" xml:space="preserve">
<value>Moving Override type {0} configurations from Service to User priority...</value>
</data>
<data name="FullResetCanceled" xml:space="preserve">
<value>Full reset canceled</value>
</data>
Expand All @@ -205,6 +211,7 @@ Arguments are now position independent and clearly labeled, ambiguous strings of
/import Imports custom feature configurations
/lkgstatus Prints the current 'Last Known Good' rollback system status
/fixlkg Fixes 'Last Known Good' rollback system corruption
/fixpriority Moves Override type configurations from Service to User priority*
/appupdate Checks for a new version of ViVeTool*
/dictupdate Checks for a new version of the feature name dictionary*

Expand Down Expand Up @@ -305,7 +312,7 @@ Examples:
<data name="Help_Reset" xml:space="preserve">
<value>Syntax:
/reset {{/id:&lt;comma delimited feature IDs&gt; | /name:&lt;comma delimited feature names&gt;}}
[/priority:&lt;enrollment | service | user | userpolicy | test&gt;] [/store:&lt;both | runtime | boot&gt;]
[/priority:{{&lt;enrollment | service | user | userpolicy | test&gt; | &lt;1-14&gt;}}] [/store:&lt;both | runtime | boot&gt;]

Features can be specified using both their IDs and names, mixing and matching is allowed.

Expand All @@ -323,20 +330,21 @@ Examples:
<value>Syntax:
{0} {{/id:&lt;comma delimited feature IDs&gt; | /name:&lt;comma delimited feature names&gt;}} [/variant:&lt;0-63&gt;]
[/variantpayloadkind:&lt;none | resident | external&gt;] [/variantpayload:&lt;0-4294967295&gt;] [/experiment]
[/priority:&lt;enrollment | service | user | userpolicy | test&gt;] [/store:&lt;both | runtime | boot&gt;]
[/priority:{{&lt;enrollment | service | user | userpolicy | test&gt; | &lt;1-14&gt;}}] [/store:&lt;both | runtime | boot&gt;]

The parameters in square brackets don't need to be specified and will use these defaults:
Variant : 0
VariantPayloadKind: None
VariantPayload : 0
Experiment : false
Priority : Service
Priority : User
Store : Both

Features can be specified using both their IDs and names, mixing and matching is allowed.

When an override is marked as an Experiment it becomes eligible for deletion by Windows's automatic
A/B feature delivery mechanism. Do NOT use this flag if you want overrides to persist.
Service priority overrides are managed by Windows's automated A/B feature delivery mechanism. Experiment
type overrides with this priority may get deleted without notice. Creating non-Experiment overrides with this
priority may negatively impact automated A/B feature delivery. Using the Service priority is not recommended.

Writing to the Boot store is necessary for features to persist across reboots. Changes to this store become
effective the next time you reboot. The Runtime store can be used to make instantenous changes, however not
Expand Down

0 comments on commit 56e0bb4

Please sign in to comment.