Skip to content

Commit c0462a1

Browse files
First push
1 parent 7a88130 commit c0462a1

18 files changed

+1049
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# ViVe
2+
ViVe is a C# library you can use to make your own programs that interact with Windows 10's A/B feature mechanism
3+
4+
In case you'd like to talk to NTDLL exports directly, you can use its *NativeMethods*.
5+
6+
Otherwise, *RtlFeatureManager* offers the same featureset with the benefit of all unmanaged structures being delivered as standard C# classes instead.
7+
8+
# ViVeTool
9+
ViVeTool is both an example of how to use ViVe, as well as a straightforward tool for power users which want to use the new APIs instantly.
10+
11+
# Compatibility
12+
In order to use ViVe, you must be running Windows 10 build 18963 or newer.
13+
14+
![ViVeTool Helpfile](https://i.imgur.com/HrLiSxe.png)

ViVe.sln

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29306.81
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViVe", "ViVe\ViVe.csproj", "{80DCDA4D-8022-4740-8CCF-459DD3FE6F72}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViVeTool", "ViVeTool\ViVeTool.csproj", "{4DAAB723-3613-4133-AE54-646133538E44}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{80DCDA4D-8022-4740-8CCF-459DD3FE6F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{80DCDA4D-8022-4740-8CCF-459DD3FE6F72}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{80DCDA4D-8022-4740-8CCF-459DD3FE6F72}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{80DCDA4D-8022-4740-8CCF-459DD3FE6F72}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{4DAAB723-3613-4133-AE54-646133538E44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{4DAAB723-3613-4133-AE54-646133538E44}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{4DAAB723-3613-4133-AE54-646133538E44}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{4DAAB723-3613-4133-AE54-646133538E44}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {E5173A5A-E3A8-4C36-9798-11628C4E4684}
30+
EndGlobalSection
31+
EndGlobal

ViVe/FeatureConfiguration.cs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System;
2+
3+
namespace Albacore.ViVe
4+
{
5+
public class FeatureConfiguration
6+
{
7+
private int _group;
8+
private FeatureEnabledState _enabledState;
9+
private int _enabledStateOptions;
10+
private int _variant;
11+
private int _variantPayloadKind;
12+
private FeatureConfigurationAction _action;
13+
14+
public uint FeatureId { get; set; }
15+
public int Group
16+
{
17+
get { return _group; }
18+
set {
19+
if (value > 15)
20+
throw new ArgumentException("Group must not be more than 15");
21+
_group = value;
22+
}
23+
}
24+
public FeatureEnabledState EnabledState
25+
{
26+
get { return _enabledState; }
27+
set
28+
{
29+
if ((int)value > 3)
30+
throw new ArgumentException("EnabledState must not be more than 3");
31+
_enabledState = value;
32+
}
33+
}
34+
public int EnabledStateOptions
35+
{
36+
get { return _enabledStateOptions; }
37+
set
38+
{
39+
if (value > 1)
40+
throw new ArgumentException("EnabledStateOptions must not be more than 1");
41+
_enabledStateOptions = value;
42+
}
43+
}
44+
public int Variant
45+
{
46+
get { return _variant; }
47+
set
48+
{
49+
if (value > 63)
50+
throw new ArgumentException("Variant must not be more than 63");
51+
_variant = value;
52+
}
53+
}
54+
public int VariantPayloadKind
55+
{
56+
get { return _variantPayloadKind; }
57+
set
58+
{
59+
if (value > 3)
60+
throw new ArgumentException("VariantPayloadKind must not be more than 3");
61+
_variantPayloadKind = value;
62+
}
63+
}
64+
public int VariantPayload { get; set; }
65+
public FeatureConfigurationAction Action
66+
{
67+
get { return _action; }
68+
set
69+
{
70+
if ((int)value > 4)
71+
throw new ArgumentException("Invalid feature configuration action");
72+
_action = value;
73+
}
74+
}
75+
}
76+
}

ViVe/FeatureConfigurationAction.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Albacore.ViVe
2+
{
3+
public enum FeatureConfigurationAction
4+
{
5+
None = 0,
6+
UpdateEnabledState = 1,
7+
UpdateVariant = 2,
8+
UpdateAll = 3,
9+
Delete = 4
10+
}
11+
}

ViVe/FeatureConfigurationSection.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Albacore.ViVe
2+
{
3+
public enum FeatureConfigurationSection
4+
{
5+
Boot = 0,
6+
Runtime = 1,
7+
UsageTriggers = 2
8+
}
9+
}

ViVe/FeatureEnabledState.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Albacore.ViVe
2+
{
3+
public enum FeatureEnabledState
4+
{
5+
Default = 0,
6+
Disabled = 1,
7+
Enabled = 2
8+
}
9+
}

ViVe/FeatureUsageReport.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Albacore.ViVe
2+
{
3+
public class FeatureUsageReport
4+
{
5+
public uint FeatureId { get; set; }
6+
public ushort ReportingKind { get; set; }
7+
public ushort ReportingOptions { get; set; }
8+
}
9+
}

ViVe/FeatureUsageSubscription.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Albacore.ViVe
2+
{
3+
public class FeatureUsageSubscription
4+
{
5+
public uint FeatureId { get; set; }
6+
public ushort ReportingKind { get; set; }
7+
public ushort ReportingOptions { get; set; }
8+
public ulong ReportingTarget { get; set; }
9+
}
10+
}

ViVe/NativeMethods.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace Albacore.ViVe
5+
{
6+
public delegate void FeatureConfigurationChangeCallback(IntPtr Context);
7+
8+
public static class NativeMethods
9+
{
10+
[DllImport("ntdll.dll")]
11+
public static extern int RtlQueryAllFeatureConfigurations(
12+
FeatureConfigurationSection sectionType,
13+
ref uint changeStamp,
14+
IntPtr buffer,
15+
ref int featureCount
16+
);
17+
18+
[DllImport("ntdll.dll")]
19+
public static extern int RtlQueryFeatureConfiguration(
20+
uint featureId,
21+
FeatureConfigurationSection sectionType,
22+
ref uint changeStamp,
23+
IntPtr buffer
24+
);
25+
26+
[DllImport("ntdll.dll")]
27+
public static extern uint RtlQueryFeatureConfigurationChangeStamp();
28+
29+
[DllImport("ntdll.dll")]
30+
public static extern int RtlQueryFeatureUsageNotificationSubscriptions(
31+
IntPtr buffer,
32+
ref int subscriptionCount
33+
);
34+
35+
[DllImport("ntdll.dll")]
36+
public static extern int RtlSetFeatureConfigurations(
37+
ref uint changeStamp,
38+
FeatureConfigurationSection sectionType,
39+
byte[] buffer,
40+
int featureCount
41+
);
42+
43+
[DllImport("ntdll.dll")]
44+
public static extern int RtlRegisterFeatureConfigurationChangeNotification(
45+
FeatureConfigurationChangeCallback callback,
46+
IntPtr context,
47+
IntPtr unknown,
48+
out IntPtr subscription
49+
);
50+
51+
[DllImport("ntdll.dll")]
52+
public static extern int RtlUnregisterFeatureConfigurationChangeNotification(
53+
IntPtr subscription
54+
);
55+
56+
[DllImport("ntdll.dll")]
57+
public static extern int RtlSubscribeForFeatureUsageNotification(
58+
byte[] buffer,
59+
int subscriptionCount
60+
);
61+
62+
[DllImport("ntdll.dll")]
63+
public static extern int RtlUnsubscribeFromFeatureUsageNotifications(
64+
byte[] buffer,
65+
int subscriptionCount
66+
);
67+
68+
[DllImport("ntdll.dll")]
69+
public static extern int RtlNotifyFeatureUsage(
70+
byte[] buffer
71+
);
72+
}
73+
}

ViVe/Properties/AssemblyInfo.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("Albacore.ViVe")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("Albacore.ViVe")]
13+
[assembly: AssemblyCopyright("Copyright © @thebookisclosed 2019")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("80dcda4d-8022-4740-8ccf-459dd3fe6f72")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("2019.9.18.1002")]
36+
[assembly: AssemblyFileVersion("2019.9.18.1002")]

ViVe/RtlDataHelpers.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
4+
namespace Albacore.ViVe
5+
{
6+
public static class RtlDataHelpers
7+
{
8+
public static byte[] SerializeFeatureConfigurations(List<FeatureConfiguration> configurations)
9+
{
10+
byte[] retArray = new byte[configurations.Count * 32];
11+
using (MemoryStream ms = new MemoryStream(retArray, true))
12+
{
13+
using (BinaryWriter bw = new BinaryWriter(ms))
14+
foreach (var thing in configurations)
15+
{
16+
bw.Write(thing.FeatureId);
17+
bw.Write(thing.Group);
18+
bw.Write((int)thing.EnabledState);
19+
bw.Write(thing.EnabledStateOptions);
20+
bw.Write(thing.Variant);
21+
bw.Write(thing.VariantPayloadKind);
22+
bw.Write(thing.VariantPayload);
23+
bw.Write((int)thing.Action);
24+
}
25+
}
26+
return retArray;
27+
}
28+
29+
public static byte[] SerializeFeatureUsageSubscriptions(List<FeatureUsageSubscription> subscriptions)
30+
{
31+
byte[] retArray = new byte[subscriptions.Count * 16];
32+
using (MemoryStream ms = new MemoryStream(retArray, true))
33+
{
34+
using (BinaryWriter bw = new BinaryWriter(ms))
35+
foreach (var thing in subscriptions)
36+
{
37+
bw.Write(thing.FeatureId);
38+
bw.Write(thing.ReportingKind);
39+
bw.Write(thing.ReportingOptions);
40+
bw.Write(thing.ReportingTarget);
41+
}
42+
}
43+
return retArray;
44+
}
45+
46+
public static byte[] SerializeFeatureUsageReport(FeatureUsageReport report)
47+
{
48+
byte[] retArray = new byte[8];
49+
using (MemoryStream ms = new MemoryStream(retArray, true))
50+
{
51+
using (BinaryWriter bw = new BinaryWriter(ms))
52+
{
53+
bw.Write(report.FeatureId);
54+
bw.Write(report.ReportingKind);
55+
bw.Write(report.ReportingOptions);
56+
}
57+
}
58+
return retArray;
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)