Skip to content

Instantly share code, notes, and snippets.

@Blizzardo1
Last active December 22, 2015 23:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Blizzardo1/bc6e11c4ea5c8b2a1191 to your computer and use it in GitHub Desktop.
Save Blizzardo1/bc6e11c4ea5c8b2a1191 to your computer and use it in GitHub Desktop.
// MUST COMPILE WITH UNSAFE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
namespace ProductPolicy
{
#region Classes
public static class Extensions
{
public static bool IsNull ( this object o ) => o == null;
}
public class ProductPolicyProgram
{
private const string KeyName = @"SYSTEM\CurrentControlSet\Control\ProductOptions";
private const string ValueName = @"ProductPolicy";
private static readonly RegistryKey _system = Registry.LocalMachine;
/// <summary>
/// Entry-Point for our program
/// </summary>
/// <remarks>This Program takes no Parameters.</remarks>
[STAThread]
internal unsafe static void Main ( )
{
RegistryKey _key;
List<ProductPolicyObject> objs = new List<ProductPolicyObject> ( );
byte [ ] byteData = null;
// Open Registry SubKey( HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions
// If this is null... immediately kill off the program.
if ( ( _key = _system.OpenSubKey ( KeyName, false ) ).IsNull ( ) )
Error ( "Key does not exist." );
// Then get the Value from within ProductOptions (ProductPolicy)
byteData = ( byte [ ] ) _key.GetValue ( ValueName );
if ( byteData.IsNull ( ) )
Error ( "No Byte Data." );
// After capturing the Data from the SubKey, read the data
// This block was originally written by Hounsell
fixed(byte* bytePtr = byteData)
{
TProductPolicyHeader* header = ( TProductPolicyHeader* ) bytePtr;
uint position = ( uint ) sizeof ( TProductPolicyHeader );
while ( ( byteData.Length - header->cbEndMarker ) > position )
{
uint startPosition = position;
ProductPolicyObject pObj = new ProductPolicyObject ( );
byte* recordPtr = bytePtr + position;
TProductPolicyValue* pValue = ( TProductPolicyValue* ) recordPtr;
pObj.Record = *pValue;
position += ( uint ) sizeof ( TProductPolicyValue );
char* recordNamePtr = ( char* ) ( bytePtr + position );
pObj.Name = new string ( recordNamePtr, 0, ( pValue->cbName / sizeof ( char ) ) );
position += pValue->cbName;
switch ( pValue->SlDatatype )
{
case LicensingDataType.Binary:
{
byte [ ] data = new byte [ pValue->cbData ];
for ( int i = 0; i < pValue->cbData; i++ )
data [ i ] = *( bytePtr + position + i );
pObj.Data = data;
break;
}
case LicensingDataType.Integer:
{
pObj.Data = *( ( int* ) ( bytePtr + position ) );
break;
}
case LicensingDataType.MultiString:
{
break;
}
case LicensingDataType.String:
{
char* recordData = ( char* ) ( bytePtr + position );
pObj.Data = new string ( recordData, 0, ( pValue->cbData / sizeof ( char ) ) ).TrimEnd ( '\0' );
break;
}
}
position = startPosition += pValue->cbSize;
objs.Add ( pObj );
}
}
// Block End
// Get the max length string(Name) from within the List
int maxStringSize = objs.Aggregate ( ( x, y ) => x.Name.Length > y.Name.Length ? x : y ).Name.Length;
Console.WriteLine ( $"{"Name".PadRight ( maxStringSize + 5 )} | {"Data".PadLeft ( 20 )} | {"Type".PadLeft ( 10 )}" );
foreach(ProductPolicyObject obj in objs)
{
Console.WriteLine ( $"{obj.Name.PadRight(maxStringSize + 5)} | {obj.Data,20} | {obj.Record.SlDatatype, 10}" );
}
Console.ReadKey ( true );
// Clean up our crap
byteData = null;
_key.Close ( );
_system.Close ( );
objs.Clear ( );
objs = null;
}
private static void Error ( string message )
{
Console.Write ( message );
Console.ReadKey ( true );
Environment.Exit ( -1 );
}
}
public class ProductPolicyObject
{
public TProductPolicyValue Record { get; set; }
public string Name { get; set; }
public object Data { get; set; }
public string DataString
{
get
{
byte [ ] dataBytes = Data as byte [ ];
if ( dataBytes != null )
{
StringBuilder sb = new StringBuilder ( );
for ( int i = 0; i < dataBytes.Length; i++ )
{
sb.Append ( dataBytes [ i ].ToString ( "X2" ) );
}
return sb.ToString ( );
}
else
{
return Data?.ToString ( );
}
}
}
}
#endregion
#region Enums
public enum LicensingDataType : short
{
None = -1,
String = 1,
Binary = 3,
Integer = 4,
MultiString = 7,
Sum = 100
}
#endregion
#region Structures
public struct TProductPolicyHeader
{
public uint cbSize { get; set; }
public uint cbDataSize { get; set; }
public uint cbEndMarker { get; set; }
public uint Unknown1 { get; set; }
public uint Unknown2 { get; set; }
}
public struct TProductPolicyValue
{
public ushort cbSize { get; set; }
public ushort cbName { get; set; }
public LicensingDataType SlDatatype { get; set; }
public ushort cbData { get; set; }
public uint Unknown1 { get; set; }
public uint Unknown2 { get; set; }
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment