1850 lines
58 KiB
C#
1850 lines
58 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using Microsoft.Win32.SafeHandles;
|
|
using System.Security;
|
|
using Common.Utils;
|
|
|
|
namespace Intel.Management.Mei
|
|
{
|
|
[ComVisible(false)]
|
|
public class HECIClass
|
|
{
|
|
private SafeFileHandle _handle;
|
|
|
|
private uint _maxLen;//buffer size for requests
|
|
private string _version; // detected version
|
|
private byte _protocol; // protocol
|
|
|
|
Guid _infGuid; // interface GUID (null= HECI)
|
|
//private string _fqdn;//
|
|
|
|
|
|
internal class DeviceOverlapped : IDisposable
|
|
{
|
|
private IntPtr _ptr = IntPtr.Zero;
|
|
|
|
private int _InternalLow = 0;
|
|
private int _InternalHigh = 0;
|
|
private int _OffsetLow = 0;
|
|
private int _OffsetHigh = 0;
|
|
private int _EventHandle = 0;
|
|
|
|
public DeviceOverlapped()
|
|
{
|
|
_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeOverlapped)));
|
|
|
|
_InternalLow = Marshal.OffsetOf(typeof(NativeOverlapped), "InternalLow").ToInt32();
|
|
_InternalHigh = Marshal.OffsetOf(typeof(NativeOverlapped), "InternalHigh").ToInt32();
|
|
_OffsetLow = Marshal.OffsetOf(typeof(NativeOverlapped), "OffsetLow").ToInt32();
|
|
_OffsetHigh = Marshal.OffsetOf(typeof(NativeOverlapped), "OffsetHigh").ToInt32();
|
|
_EventHandle = Marshal.OffsetOf(typeof(NativeOverlapped), "EventHandle").ToInt32();
|
|
}
|
|
|
|
public IntPtr InternalLow
|
|
{
|
|
get { return Marshal.ReadIntPtr(_ptr, _InternalLow); }
|
|
set { Marshal.WriteIntPtr(_ptr, _InternalLow, value); }
|
|
}
|
|
|
|
public IntPtr InternalHigh
|
|
{
|
|
get { return Marshal.ReadIntPtr(_ptr, _InternalHigh); }
|
|
set { Marshal.WriteIntPtr(_ptr, _InternalHigh, value); }
|
|
}
|
|
|
|
public int OffsetLow
|
|
{
|
|
get { return Marshal.ReadInt32(_ptr, _OffsetLow); }
|
|
set { Marshal.WriteInt32(_ptr, _OffsetLow, value); }
|
|
}
|
|
|
|
public int OffsetHigh
|
|
{
|
|
get { return Marshal.ReadInt32(_ptr, _OffsetHigh); }
|
|
set { Marshal.WriteInt32(_ptr, _OffsetHigh, value); }
|
|
}
|
|
|
|
public IntPtr EventHandle
|
|
{
|
|
get { return Marshal.ReadIntPtr(_ptr, _EventHandle); }
|
|
set { Marshal.WriteIntPtr(_ptr, _EventHandle, value); }
|
|
}
|
|
|
|
public IntPtr ToPointer()
|
|
{
|
|
return _ptr;
|
|
}
|
|
|
|
public void Reset(IntPtr hEventOverlapped)
|
|
{
|
|
EventHandle = hEventOverlapped;
|
|
InternalLow = IntPtr.Zero;
|
|
InternalHigh = IntPtr.Zero;
|
|
OffsetLow = 0;
|
|
OffsetHigh = 0;
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
if (_ptr != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(_ptr);
|
|
_ptr = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
#region IDisposable Members
|
|
|
|
private bool _disposed = false;
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
if (disposing)
|
|
{
|
|
|
|
}
|
|
Close();
|
|
_disposed = true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
~DeviceOverlapped()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class MeiException : Exception
|
|
{
|
|
public MeiException(string message) : base(message) { }
|
|
public MeiException(string message, Exception inner) : base(message, inner) { }
|
|
}
|
|
|
|
public class DriverNotFoundException : MeiException
|
|
{
|
|
public DriverNotFoundException(string message) : base(message) { }
|
|
public DriverNotFoundException(string message, Exception inner) : base(message, inner) { }
|
|
}
|
|
|
|
public class UnauthorizedException : MeiException
|
|
{
|
|
public UnauthorizedException(string message) : base(message) { }
|
|
public UnauthorizedException(string message, Exception inner) : base(message, inner) { }
|
|
}
|
|
|
|
public class StatusException : MeiException
|
|
{
|
|
public StatusException(UInt32 status) : base("AmtStatus " + status.ToString()) { }
|
|
}
|
|
|
|
|
|
|
|
public HECIClass()
|
|
{
|
|
_handle = null;
|
|
|
|
}
|
|
|
|
public static Guid HECIGuid
|
|
{
|
|
get
|
|
{
|
|
return new Guid("12F80028-B4B7-4B2D-ACA8-46E0FF65814C");
|
|
}
|
|
}
|
|
|
|
public static Guid WatchDogGuid
|
|
{
|
|
get
|
|
{
|
|
return new Guid("05B79A6F-4628-4D7F-899D-A91514CB32AB");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void Init()
|
|
{
|
|
Init(HECIGuid);
|
|
}
|
|
|
|
public void Init(Guid guid)
|
|
{
|
|
Guid devGuid = new Guid("E2D1FF34-3458-49A9-88DA-8E6915CE9BE5");
|
|
|
|
const int DIGCF_PRESENT = 0x02;
|
|
const int DIGCF_DEVICEINTERFACE = 0x10;
|
|
|
|
IntPtr hDevInfo = SetupDiGetClassDevs(ref devGuid, IntPtr.Zero, IntPtr.Zero,
|
|
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
|
|
|
if (hDevInfo.Equals((IntPtr)(-1)))
|
|
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
|
|
|
|
SP_DEVICE_INTERFACE_DATA spdata = new SP_DEVICE_INTERFACE_DATA();
|
|
SP_DEVICE_INTERFACE_DETAIL_DATA spDetail = new SP_DEVICE_INTERFACE_DETAIL_DATA();
|
|
SP_DEVINFO_DATA spInfo = new SP_DEVINFO_DATA();
|
|
spInfo.cbSize = (uint)Marshal.SizeOf(spInfo);
|
|
spdata.cbSize = (uint)Marshal.SizeOf(spdata);
|
|
|
|
if (IntPtr.Size == 8) // for 64 bit operating systems
|
|
spDetail.cbSize = 8;
|
|
else
|
|
spDetail.cbSize = 4 + (uint)Marshal.SystemDefaultCharSize; // for 32 bit systems
|
|
|
|
|
|
uint bufferSize = 0;
|
|
UInt32 index = 0;
|
|
bool bOk = false;
|
|
while (SetupDiEnumDeviceInterfaces(hDevInfo,
|
|
IntPtr.Zero,
|
|
ref devGuid,
|
|
index++,
|
|
ref spdata))
|
|
{
|
|
|
|
bOk = SetupDiGetDeviceInterfaceDetail(hDevInfo,
|
|
ref spdata,
|
|
ref spDetail,
|
|
(uint)System.Runtime.InteropServices.Marshal.SizeOf(spDetail),
|
|
out bufferSize,
|
|
ref spInfo);
|
|
}
|
|
|
|
if (!bOk)
|
|
new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
|
|
|
|
|
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
|
|
|
|
|
// flags for create File
|
|
const uint GENERIC_READ = 0x80000000;
|
|
const uint GENERIC_WRITE = 0x40000000;
|
|
const uint FILE_SHARE_READ = 0x00000001;
|
|
const uint FILE_SHARE_WRITE = 0x00000002;
|
|
const uint OPEN_EXISTING = 3;
|
|
const uint FILE_FLAG_OVERLAPPED = 0x40000000;
|
|
|
|
|
|
_handle = CreateFile(spDetail.DevicePath,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
IntPtr.Zero,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_OVERLAPPED,
|
|
IntPtr.Zero);
|
|
|
|
if (_handle.IsInvalid)
|
|
{
|
|
int errorCode = Marshal.GetLastWin32Error();
|
|
_handle = null;
|
|
if (errorCode == 5)
|
|
throw new UnauthorizedAccessException();
|
|
|
|
throw new FileNotFoundException("Unable to open HECI Device", spDetail.DevicePath, new System.ComponentModel.Win32Exception(errorCode));
|
|
}
|
|
|
|
//get version
|
|
int size = Marshal.SizeOf(typeof(HECI_VERSION));
|
|
HECI_VERSION heciVer = new HECI_VERSION();
|
|
IntPtr outPtr = SendIOControl(2147540992, null, 0, heciVer, size);
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
heciVer = (HECI_VERSION)Marshal.PtrToStructure(outPtr, typeof(HECI_VERSION));
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
builder.Append(heciVer.major.ToString());
|
|
builder.Append(".");
|
|
builder.Append(heciVer.minor.ToString());
|
|
builder.Append(".");
|
|
builder.Append(heciVer.hotfix.ToString());
|
|
builder.Append(".");
|
|
builder.Append(heciVer.build.ToString());
|
|
_version = builder.ToString();
|
|
|
|
}
|
|
|
|
|
|
size = Marshal.SizeOf(typeof(HECI_CLIENT));
|
|
HECI_CLIENT heciClt = new HECI_CLIENT();
|
|
|
|
//connect to heci
|
|
//guid = new Guid("12F80028-B4B7-4B2D-ACA8-46E0FF65814C");
|
|
byte[] guidData = guid.ToByteArray();
|
|
outPtr = SendIOControl(2147540996, guidData,
|
|
guidData.Length, heciClt, size);
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
heciClt = (HECI_CLIENT)Marshal.PtrToStructure(outPtr, typeof(HECI_CLIENT));
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
_maxLen = heciClt.MaxMessageLength;
|
|
_protocol = heciClt.ProtocolVersion;
|
|
}
|
|
}
|
|
|
|
public void DeInit()
|
|
{
|
|
if (_handle != null)
|
|
_handle.Close();
|
|
}
|
|
|
|
public bool GetLocalAdminCredentials(out string userName, out SecureString password)
|
|
{
|
|
userName = string.Empty;
|
|
password = new SecureString();
|
|
CFG_GET_LOCAL_SYSTEM_ACCOUNT_REQUEST input = new CFG_GET_LOCAL_SYSTEM_ACCOUNT_REQUEST();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108967;
|
|
input.Length = 40;
|
|
int inSize = Marshal.SizeOf(typeof(CFG_GET_LOCAL_SYSTEM_ACCOUNT_REQUEST));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
if (outPtr.Equals(IntPtr.Zero))
|
|
return false;
|
|
|
|
CFG_GET_LOCAL_SYSETM_ACCOUNT_RESPONSE output;
|
|
output = (CFG_GET_LOCAL_SYSETM_ACCOUNT_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(CFG_GET_LOCAL_SYSETM_ACCOUNT_RESPONSE));
|
|
|
|
userName = output.UserName;
|
|
password.Dispose();
|
|
password = output.Password;
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
public bool GetProvisioningState(out ProvisioningState state)
|
|
{
|
|
state = ProvisioningState.In;
|
|
bool result = false;
|
|
|
|
//0x04000011
|
|
//
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108881;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_PROVISIONING_STATE_RESPONSE));
|
|
GET_PROVISIONING_STATE_RESPONSE output;
|
|
|
|
output = (GET_PROVISIONING_STATE_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_PROVISIONING_STATE_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
state = output.State;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public bool GetProvisioningMode(out ProvisioningMode mode)
|
|
{
|
|
bool result = false;
|
|
mode = ProvisioningMode.None;
|
|
|
|
//0x04000011
|
|
//
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108872;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_PROVISIONING_MODE_RESPONSE));
|
|
GET_PROVISIONING_MODE_RESPONSE output;
|
|
|
|
output = (GET_PROVISIONING_MODE_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_PROVISIONING_MODE_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
mode = output.Mode;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
public bool QueryStateIndependence()
|
|
{
|
|
bool isEnabled = false;
|
|
|
|
STATE_INDEPENDENCE_COMMAND input = new STATE_INDEPENDENCE_COMMAND();
|
|
input.Cmd = 5;
|
|
input.ByteCount = 2;
|
|
input.SubCmd = 81;
|
|
input.Version = 16;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(STATE_INDEPENDENCE_COMMAND));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
if (outPtr.Equals(IntPtr.Zero))
|
|
return false;
|
|
|
|
STATE_INDEPENDENCE_RESPONSE output;
|
|
output = (STATE_INDEPENDENCE_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(STATE_INDEPENDENCE_RESPONSE));
|
|
|
|
|
|
isEnabled = output.Status != 0;
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
return isEnabled;
|
|
}
|
|
|
|
|
|
public bool EnableStateIndependence()
|
|
{
|
|
bool isEnabled = false;
|
|
|
|
STATE_INDEPENDENCE_COMMAND input = new STATE_INDEPENDENCE_COMMAND();
|
|
input.Cmd = 5;
|
|
input.ByteCount = 2;
|
|
input.SubCmd = 82;
|
|
input.Version = 16;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(STATE_INDEPENDENCE_COMMAND));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
if (outPtr.Equals(IntPtr.Zero))
|
|
return false;
|
|
|
|
STATE_INDEPENDENCE_RESPONSE output;
|
|
output = (STATE_INDEPENDENCE_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(STATE_INDEPENDENCE_RESPONSE));
|
|
|
|
|
|
isEnabled = output.Status == 0;
|
|
//158 means Transition to Intel AMT is not currenlty allowed
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
return isEnabled;
|
|
}
|
|
|
|
public bool StartConfiguration()
|
|
{
|
|
bool result = false;
|
|
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108905;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_HECI_RESPONSE));
|
|
GET_HECI_RESPONSE output;
|
|
|
|
output = (GET_HECI_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_HECI_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
public bool StartConfigurationEx(bool enableIpv6)
|
|
{
|
|
bool result = false;
|
|
|
|
|
|
CFG_START_CONFIGURATION_EX_REQUEST input = new CFG_START_CONFIGURATION_EX_REQUEST();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108962;//04000062
|
|
|
|
input.Length = sizeof(uint);
|
|
if (enableIpv6)
|
|
input.Ipv6Enable = 1;
|
|
else
|
|
input.Ipv6Enable = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(CFG_START_CONFIGURATION_EX_REQUEST));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_HECI_RESPONSE));
|
|
GET_HECI_RESPONSE output;
|
|
|
|
output = (GET_HECI_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_HECI_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
public bool SetOTP(SecureString password)
|
|
{
|
|
bool result = false;
|
|
byte[] ansiData = password.ConvertToByteArray();
|
|
if (ansiData == null)
|
|
return result;
|
|
|
|
CFG_SET_PROVISIONING_SERVER_OTP_REQUEST input = new CFG_SET_PROVISIONING_SERVER_OTP_REQUEST();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108906;//400002A
|
|
input.Length = sizeof(ushort) + (uint)ansiData.Length;
|
|
try
|
|
{
|
|
input.PasswordLength = (ushort)ansiData.Length;//Conversion from int to ushort
|
|
}
|
|
catch (System.OverflowException e)
|
|
{
|
|
throw new System.OverflowException(e.ToString());
|
|
}
|
|
|
|
int inSize = Marshal.SizeOf(typeof(CFG_SET_PROVISIONING_SERVER_OTP_REQUEST)) + ansiData.Length;
|
|
|
|
IntPtr outPtr = IntPtr.Zero;
|
|
IntPtr inPtr = Marshal.AllocCoTaskMem(inSize);
|
|
try
|
|
{
|
|
IntPtr offSetPtr = new IntPtr(inPtr.ToInt64() + Marshal.SizeOf(typeof(CFG_SET_PROVISIONING_SERVER_OTP_REQUEST)));
|
|
Marshal.StructureToPtr(input, inPtr, true);
|
|
//copy ansi data
|
|
Marshal.Copy(ansiData, 0, offSetPtr, ansiData.Length);
|
|
// byte[] data = new byte[8];
|
|
//Marshal.Copy(inPtr, data, Marshal.SizeOf(typeof(CFG_SET_PROVISIONING_SERVER_OTP_REQUEST)), data.Length);
|
|
|
|
outPtr = SendMessage(inPtr, inSize);
|
|
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeCoTaskMem(inPtr);
|
|
Array.Clear(ansiData, 0, ansiData.Length);
|
|
}
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_HECI_RESPONSE));
|
|
GET_HECI_RESPONSE output;
|
|
|
|
output = (GET_HECI_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_HECI_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
public bool GetRngSeedStatus(out RngSeedStatus status)
|
|
{
|
|
bool result = false;
|
|
status = RngSeedStatus.Exists;
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108904;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_RNG_SEED_STATUS_RESPONSE));
|
|
GET_RNG_SEED_STATUS_RESPONSE output;
|
|
|
|
output = (GET_RNG_SEED_STATUS_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_RNG_SEED_STATUS_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = (int)output.RngStatus > 0 && (int)output.RngStatus < 3;
|
|
status = output.RngStatus;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
public bool GetZeroTouchEnabled(out bool enabled)
|
|
{
|
|
bool result = false;
|
|
enabled = false;
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108912;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_ZERO_TOUCH_ENABLED_RESPONSE));
|
|
GET_ZERO_TOUCH_ENABLED_RESPONSE output;
|
|
|
|
output = (GET_ZERO_TOUCH_ENABLED_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_ZERO_TOUCH_ENABLED_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
enabled = output.TlsEnabled != 0;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
public bool GetTlsMode(out TlsMode mode)
|
|
{
|
|
bool result = false;
|
|
mode = TlsMode.NotReady;
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108907;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_PROVISIONING_TLS_MODE_RESPONSE));
|
|
GET_PROVISIONING_TLS_MODE_RESPONSE output;
|
|
|
|
output = (GET_PROVISIONING_TLS_MODE_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_PROVISIONING_TLS_MODE_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
mode = output.TlsMode;
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public bool GetConfigServer(out string fqdn)
|
|
{
|
|
bool result = false;
|
|
fqdn = string.Empty;
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108915;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_CONF_SERVER_FQDN_RESPONSE));
|
|
GET_CONF_SERVER_FQDN_RESPONSE output;
|
|
|
|
output = (GET_CONF_SERVER_FQDN_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_CONF_SERVER_FQDN_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
byte[] data = new byte[outSize + output.NameLength];
|
|
Marshal.Copy(outPtr, data, 0, data.Length);
|
|
fqdn = Encoding.ASCII.GetString(data, outSize, output.NameLength);
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
public bool GetDnsSuffix(out string suffix)
|
|
{
|
|
bool result = false;
|
|
suffix = string.Empty;
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108918;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_CONF_SERVER_FQDN_RESPONSE));
|
|
GET_CONF_SERVER_FQDN_RESPONSE output;
|
|
|
|
output = (GET_CONF_SERVER_FQDN_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_CONF_SERVER_FQDN_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
byte[] data = new byte[outSize + output.NameLength];
|
|
Marshal.Copy(outPtr, data, 0, data.Length);
|
|
suffix = Encoding.ASCII.GetString(data, outSize, output.NameLength);
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public bool GetAuditRecord(out AuditRecord record)
|
|
{
|
|
bool result = false;
|
|
record = null;
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108903;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_AUDIT_RECORD_RESPONSE));
|
|
GET_AUDIT_RECORD_RESPONSE output;
|
|
|
|
output = (GET_AUDIT_RECORD_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_AUDIT_RECORD_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
|
|
DateTime timestamp = new DateTime((int)output.Year, (int)output.Month, (int)output.Day,
|
|
(int)output.Hour, (int)output.Minute, (int)output.Second);
|
|
|
|
byte[] data = new byte[outSize + output.NameLength];
|
|
Marshal.Copy(outPtr, data, 0, data.Length);
|
|
|
|
|
|
string suffix = Encoding.ASCII.GetString(data, outSize, output.NameLength);
|
|
record = new AuditRecord(timestamp, suffix, output.ProvServerIP,
|
|
output.IsOemDefault, output.SelectedHashData, output.SelectedHashType,
|
|
output.IsTimeValid,
|
|
output.AdditionalCaSerialNums, output.CaCertificateSerials);
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public bool GetCertHashes(out HashEntry[] hashes)
|
|
{
|
|
bool result = false;
|
|
hashes = null;
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108908;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_HASH_HANDLES_RESPONSE));
|
|
GET_HASH_HANDLES_RESPONSE output;
|
|
|
|
output = (GET_HASH_HANDLES_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_HASH_HANDLES_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
result = true;
|
|
int offset = outSize;
|
|
hashes = new HashEntry[output.HashHandleCount];
|
|
for (int i = 0; hashes != null && i < output.HashHandleCount; i++)
|
|
{
|
|
UInt32 hashHandle = (UInt32)Marshal.ReadInt32(outPtr, offset);
|
|
offset += sizeof(UInt32);
|
|
hashes[i] = GetHashEntry(hashHandle);
|
|
if (hashes[i] == null)
|
|
{
|
|
hashes = null;
|
|
result = false;
|
|
}
|
|
}
|
|
}
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
public bool GetCodeVersions(out string bios, out AMT_VERSION_TYPE[] versions)
|
|
{
|
|
|
|
List<AMT_VERSION_TYPE> verList = new List<AMT_VERSION_TYPE>();
|
|
versions = verList.ToArray();
|
|
bios = string.Empty;
|
|
bool result = false;
|
|
|
|
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108890;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
|
|
int outSize = Marshal.SizeOf(typeof(CFG_GET_CODE_VERSIONS_RESPONSE));
|
|
CFG_GET_CODE_VERSIONS_RESPONSE output;
|
|
|
|
output = (CFG_GET_CODE_VERSIONS_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(CFG_GET_CODE_VERSIONS_RESPONSE));
|
|
|
|
|
|
int eltSize = Marshal.SizeOf(typeof(AMT_VERSION_TYPE));
|
|
IntPtr inPtr = Marshal.AllocCoTaskMem(eltSize);
|
|
for (int i = 0; i < output.VersionCount; i++)
|
|
{
|
|
for (int k = 0; k < eltSize; k++)
|
|
{
|
|
Marshal.WriteByte(inPtr, k,
|
|
Marshal.ReadByte(outPtr, outSize + (i * eltSize) + k));
|
|
}
|
|
verList.Add((AMT_VERSION_TYPE)
|
|
Marshal.PtrToStructure(inPtr, typeof(AMT_VERSION_TYPE)));
|
|
|
|
}
|
|
Marshal.FreeCoTaskMem(inPtr);
|
|
|
|
versions = verList.ToArray();
|
|
bios = output.BiosVersion;
|
|
result = output.AmtStatus == 0;
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
public bool UnProvision()
|
|
{
|
|
CFG_UNPROVISION_REQUEST input = new CFG_UNPROVISION_REQUEST();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108880;
|
|
input.Length = sizeof(uint);
|
|
input.Mode = 0;
|
|
int inSize = Marshal.SizeOf(typeof(CFG_UNPROVISION_REQUEST));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
if (outPtr.Equals(IntPtr.Zero))
|
|
return false;
|
|
|
|
CFG_UNPROVISION_RESPONSE output;
|
|
output = (CFG_UNPROVISION_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(CFG_UNPROVISION_RESPONSE));
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
return output.AmtStatus == 0;
|
|
}
|
|
|
|
|
|
public bool OpenUserInitiatedConnection()
|
|
{
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108932;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
if (outPtr.Equals(IntPtr.Zero))
|
|
return false;
|
|
|
|
GET_HECI_RESPONSE output;
|
|
output = (GET_HECI_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_HECI_RESPONSE));
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
return output.AmtStatus == 0;
|
|
}
|
|
|
|
public bool CloseUserInitiatedConnection()
|
|
{
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108933;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
if (outPtr.Equals(IntPtr.Zero))
|
|
return false;
|
|
|
|
GET_HECI_RESPONSE output;
|
|
output = (GET_HECI_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_HECI_RESPONSE));
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
return output.AmtStatus == 0;
|
|
}
|
|
|
|
public bool StopConfiguration()
|
|
{
|
|
GET_COMMAND_HEADER input = new GET_COMMAND_HEADER();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 75497566;
|
|
input.Length = 0;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_COMMAND_HEADER));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
if (outPtr.Equals(IntPtr.Zero))
|
|
return false;
|
|
|
|
GET_HECI_RESPONSE output;
|
|
output = (GET_HECI_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_HECI_RESPONSE));
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
|
|
return output.AmtStatus == 0;
|
|
}
|
|
|
|
|
|
private HashEntry GetHashEntry(UInt32 handle)
|
|
{
|
|
|
|
HashEntry result = null;
|
|
|
|
GET_CERTHASH_ENTRY_REQUEST input = new GET_CERTHASH_ENTRY_REQUEST();
|
|
input.MajorNumber = 1;
|
|
input.MinorNumber = 1;
|
|
input.Command = 67108909;
|
|
input.Length = sizeof(UInt32);
|
|
input.HashHandle = handle;
|
|
|
|
int inSize = Marshal.SizeOf(typeof(GET_CERTHASH_ENTRY_REQUEST));
|
|
|
|
IntPtr outPtr = SendMessage(input, inSize);
|
|
|
|
if (!outPtr.Equals(IntPtr.Zero))
|
|
{
|
|
int outSize = Marshal.SizeOf(typeof(GET_CERTHASH_ENTRY_RESPONSE));
|
|
GET_CERTHASH_ENTRY_RESPONSE output;
|
|
|
|
output = (GET_CERTHASH_ENTRY_RESPONSE)Marshal.PtrToStructure(outPtr,
|
|
typeof(GET_CERTHASH_ENTRY_RESPONSE));
|
|
|
|
if (output.AmtStatus == 0)
|
|
{
|
|
byte[] data = new byte[outSize + output.NameLength];
|
|
Marshal.Copy(outPtr, data, 0, data.Length);
|
|
|
|
string name = Encoding.ASCII.GetString(data, outSize, output.NameLength);
|
|
|
|
result = new HashEntry(output.IsActive != 0,
|
|
output.IsDefault != 0,
|
|
output.HashAlgorithm,
|
|
output.CertificateHash,
|
|
name,
|
|
handle);
|
|
}
|
|
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
private IntPtr SendMessage(object input, int inSize)
|
|
{
|
|
uint bytesRead;
|
|
|
|
IntPtr inPtr = IntPtr.Zero;
|
|
|
|
if (!(input is IntPtr))
|
|
{
|
|
inPtr = Marshal.AllocCoTaskMem(inSize);
|
|
Marshal.StructureToPtr(input, inPtr, true);
|
|
}
|
|
else
|
|
{
|
|
inPtr = (IntPtr)input;
|
|
}
|
|
|
|
DeviceOverlapped deviceIoOverlapped;
|
|
ManualResetEvent waitEvent;
|
|
using (deviceIoOverlapped = new DeviceOverlapped())
|
|
{
|
|
using (waitEvent = new ManualResetEvent(false))
|
|
{
|
|
deviceIoOverlapped.Reset(waitEvent.SafeWaitHandle.DangerousGetHandle());
|
|
|
|
bool bOk = WriteFile(_handle, inPtr, (uint)inSize, out bytesRead, deviceIoOverlapped.ToPointer());
|
|
|
|
//997 means wait
|
|
int err = Marshal.GetLastWin32Error();
|
|
|
|
if (bOk == false && err == ERROR_IO_PENDING)
|
|
{
|
|
waitEvent.WaitOne();
|
|
bOk = GetOverlappedResult(_handle, deviceIoOverlapped.ToPointer(), out bytesRead, true);
|
|
err = Marshal.GetLastWin32Error();
|
|
}
|
|
|
|
if (!(input is IntPtr))
|
|
Marshal.FreeCoTaskMem(inPtr);
|
|
inPtr = IntPtr.Zero;
|
|
deviceIoOverlapped.Close();
|
|
waitEvent.Close();
|
|
|
|
using (deviceIoOverlapped = new DeviceOverlapped())
|
|
{
|
|
using (waitEvent = new ManualResetEvent(false))
|
|
{
|
|
deviceIoOverlapped.Reset(waitEvent.SafeWaitHandle.DangerousGetHandle());
|
|
inPtr = Marshal.AllocCoTaskMem((int)_maxLen);
|
|
|
|
|
|
if (bOk)
|
|
{
|
|
bOk = ReadFile(_handle, inPtr, _maxLen, ref bytesRead, deviceIoOverlapped.ToPointer());
|
|
err = Marshal.GetLastWin32Error();
|
|
}
|
|
|
|
|
|
if (bOk == false && err == ERROR_IO_PENDING)
|
|
{
|
|
waitEvent.WaitOne();
|
|
bOk = GetOverlappedResult(_handle, deviceIoOverlapped.ToPointer(), out bytesRead, true);
|
|
err = Marshal.GetLastWin32Error();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// don't bother returning empty response
|
|
if (bOk == false || (bOk && bytesRead == 0))
|
|
{
|
|
Marshal.FreeCoTaskMem(inPtr);
|
|
inPtr = IntPtr.Zero;
|
|
}
|
|
}
|
|
}
|
|
return inPtr;
|
|
}
|
|
|
|
private IntPtr SendIOControl(uint code, object input, int inSize, object output, int outSize)
|
|
{
|
|
uint bytesRead;
|
|
IntPtr outPtr = IntPtr.Zero;
|
|
IntPtr inPtr = IntPtr.Zero;
|
|
|
|
if (output != null)
|
|
{
|
|
outPtr = Marshal.AllocCoTaskMem(outSize);
|
|
Marshal.StructureToPtr(output, outPtr, false);
|
|
}
|
|
|
|
if (input != null)
|
|
{
|
|
inPtr = Marshal.AllocCoTaskMem(inSize);
|
|
if (input.GetType().IsArray)
|
|
{
|
|
Marshal.Copy((byte[])input, 0, inPtr, inSize);
|
|
}
|
|
else
|
|
{
|
|
Marshal.StructureToPtr(input, inPtr, false);
|
|
}
|
|
}
|
|
|
|
using (DeviceOverlapped deviceIoOverlapped = new DeviceOverlapped())
|
|
{
|
|
using (ManualResetEvent waitEvent = new ManualResetEvent(false))
|
|
{
|
|
deviceIoOverlapped.Reset(waitEvent.SafeWaitHandle.DangerousGetHandle());
|
|
|
|
|
|
bool bOk = DeviceIoControl(_handle, code,
|
|
inPtr, (uint)inSize,
|
|
outPtr, (uint)outSize,
|
|
out bytesRead, deviceIoOverlapped.ToPointer());
|
|
|
|
int err = Marshal.GetLastWin32Error();
|
|
|
|
|
|
if (bOk == false && err == ERROR_IO_PENDING)
|
|
{
|
|
waitEvent.WaitOne();
|
|
bOk = GetOverlappedResult(_handle,
|
|
deviceIoOverlapped.ToPointer()
|
|
, out bytesRead, true);
|
|
}
|
|
|
|
if (!inPtr.Equals(IntPtr.Zero))
|
|
Marshal.FreeCoTaskMem(inPtr);
|
|
|
|
|
|
if (!bOk)
|
|
{
|
|
Marshal.FreeCoTaskMem(outPtr);
|
|
outPtr = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
}
|
|
return outPtr;
|
|
}
|
|
|
|
static readonly int ERROR_IO_PENDING = 997;
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct STATE_INDEPENDENCE_COMMAND
|
|
{
|
|
public byte Cmd;
|
|
public byte ByteCount;
|
|
public byte SubCmd;
|
|
public byte Version;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct STATE_INDEPENDENCE_RESPONSE
|
|
{
|
|
public uint Status;
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct HECI_VERSION
|
|
{
|
|
public byte major;
|
|
public byte minor;
|
|
public byte hotfix;
|
|
public short build;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
public struct AMT_UNICODE_STRING
|
|
{
|
|
public UInt16 Length;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
|
|
public string Text;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct AMT_VERSION_TYPE
|
|
{
|
|
public AMT_UNICODE_STRING Description;
|
|
public AMT_UNICODE_STRING Version;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct GET_COMMAND_HEADER
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
private struct CFG_GET_CODE_VERSIONS_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)]
|
|
public string BiosVersion;
|
|
public UInt32 VersionCount;
|
|
}
|
|
|
|
public enum ProvisioningMode
|
|
{
|
|
None = 0,
|
|
Enterprise = 1,
|
|
SmallBusiness = 2
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct GET_PROVISIONING_MODE_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public UInt32 Legacy;
|
|
public ProvisioningMode Mode;
|
|
}
|
|
|
|
public enum ProvisioningState
|
|
{
|
|
Pre = 0,
|
|
In = 1,
|
|
Post = 2
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct GET_PROVISIONING_STATE_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public ProvisioningState State;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct CFG_SET_PROVISIONING_SERVER_OTP_REQUEST
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public ushort PasswordLength;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct CFG_START_CONFIGURATION_EX_REQUEST
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 Ipv6Enable;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct CFG_UNPROVISION_REQUEST
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 Mode;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct CFG_UNPROVISION_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct CFG_GET_LOCAL_SYSTEM_ACCOUNT_REQUEST
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
|
|
public byte[] Reserved2;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
private struct CFG_GET_LOCAL_SYSETM_ACCOUNT_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)]
|
|
public string UserName;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)]
|
|
public SecureString Password;
|
|
}
|
|
|
|
public enum RngSeedStatus
|
|
{
|
|
Exists = 0,
|
|
InProgress = 1,
|
|
NotExists = 2
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
private struct GET_RNG_SEED_STATUS_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public RngSeedStatus RngStatus;
|
|
|
|
|
|
};
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
private struct GET_HASH_HANDLES_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public UInt32 HashHandleCount;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct GET_CERTHASH_ENTRY_REQUEST
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 HashHandle;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
private struct GET_CERTHASH_ENTRY_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public UInt32 IsDefault;
|
|
public UInt32 IsActive;
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
|
|
public byte[] CertificateHash;
|
|
public byte HashAlgorithm;
|
|
public UInt16 NameLength;
|
|
}
|
|
|
|
public enum HashAlgorithm
|
|
{
|
|
MD5 = 0,
|
|
SHA1 = 1,
|
|
SHA256 = 2,
|
|
SHA384 = 3,
|
|
SHA512 = 4
|
|
}
|
|
|
|
public class HashEntry
|
|
{
|
|
bool _isActive;
|
|
bool _isDefault;
|
|
HashAlgorithm _hashAlg;
|
|
byte[] _hashData;
|
|
string _name;
|
|
UInt32 _handle;
|
|
|
|
public HashEntry(bool isActive, bool isDefault, byte hashAlg, byte[] hash, string name, UInt32 handle)
|
|
{
|
|
_isActive = isActive;
|
|
_isDefault = isDefault;
|
|
_hashAlg = (HashAlgorithm)hashAlg;
|
|
|
|
_name = name;
|
|
_handle = handle;
|
|
|
|
// copy hash based on size
|
|
switch (_hashAlg)
|
|
{
|
|
case HashAlgorithm.MD5:
|
|
_hashData = new byte[16];
|
|
break;
|
|
case HashAlgorithm.SHA1:
|
|
_hashData = new byte[20];
|
|
break;
|
|
case HashAlgorithm.SHA256:
|
|
_hashData = new byte[32];
|
|
break;
|
|
case HashAlgorithm.SHA384:
|
|
_hashData = new byte[48];
|
|
break;
|
|
default:
|
|
_hashData = new byte[64];
|
|
break;
|
|
}
|
|
Array.Copy(hash, _hashData, _hashData.Length);
|
|
}
|
|
public bool IsDefault
|
|
{
|
|
get
|
|
{
|
|
return _isDefault;
|
|
}
|
|
|
|
}
|
|
public bool IsActive
|
|
{
|
|
get
|
|
{
|
|
return _isActive;
|
|
}
|
|
|
|
}
|
|
public UInt32 Handle
|
|
{
|
|
get
|
|
{
|
|
return _handle;
|
|
}
|
|
}
|
|
|
|
public string HashString
|
|
{
|
|
get
|
|
{
|
|
return Convert.ToBase64String(_hashData);
|
|
}
|
|
}
|
|
public string Thumbprint
|
|
{
|
|
get
|
|
{
|
|
string result = BitConverter.ToString(_hashData);
|
|
result = result.Replace("-", string.Empty);
|
|
return result;
|
|
}
|
|
}
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
return _name;
|
|
}
|
|
}
|
|
|
|
public byte[] HashData
|
|
{
|
|
get
|
|
{
|
|
return _hashData;
|
|
}
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct GET_ZERO_TOUCH_ENABLED_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public UInt32 TlsEnabled;
|
|
}
|
|
|
|
public enum TlsMode
|
|
{
|
|
NotReady = 0,
|
|
PSK = 1,
|
|
PKI = 2
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
struct GET_PROVISIONING_TLS_MODE_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public TlsMode TlsMode;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
struct GET_CONF_SERVER_FQDN_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public UInt16 NameLength;
|
|
}
|
|
|
|
public class AuditRecord
|
|
{
|
|
string _domainSuffix;
|
|
DateTime _timpstamp;
|
|
bool _isDefault;
|
|
bool _timeValid;
|
|
|
|
bool _additionalCaNums;
|
|
string _ipAddress;
|
|
string _hash;
|
|
string[] _caSerials;
|
|
HashAlgorithm _hashAlg;
|
|
|
|
|
|
public AuditRecord(DateTime timestamp, string suffix, uint ipAddress,
|
|
uint isDefault, byte[] hash, HashAlgorithm selectedHashType,
|
|
uint timeValid, uint additionalCaNums,
|
|
byte[] caSerials)
|
|
{
|
|
_timpstamp = timestamp;
|
|
_domainSuffix = suffix;
|
|
|
|
System.Net.IPAddress add = new System.Net.IPAddress(ipAddress);
|
|
|
|
_ipAddress = add.ToString();
|
|
_isDefault = !isDefault.Equals(0);
|
|
|
|
byte[] hashValue = null;
|
|
_hashAlg = selectedHashType;
|
|
switch (selectedHashType)
|
|
{
|
|
case HashAlgorithm.MD5:
|
|
hashValue = new byte[16];
|
|
break;
|
|
case HashAlgorithm.SHA1:
|
|
hashValue = new byte[20];
|
|
break;
|
|
case HashAlgorithm.SHA256:
|
|
hashValue = new byte[32];
|
|
break;
|
|
case HashAlgorithm.SHA384:
|
|
hashValue = new byte[48];
|
|
break;
|
|
case HashAlgorithm.SHA512:
|
|
hashValue = new byte[64];
|
|
break;
|
|
default:
|
|
hashValue = new byte[0];
|
|
break;
|
|
}
|
|
|
|
Array.Copy(hash, hashValue, hashValue.Length);
|
|
|
|
_hash = BitConverter.ToString(hashValue);
|
|
_hash = _hash.Replace("-", string.Empty);
|
|
_hash = _hash.ToUpper();
|
|
|
|
_timeValid = !timeValid.Equals(0);
|
|
|
|
_additionalCaNums = !additionalCaNums.Equals(0);
|
|
_caSerials = new string[0];
|
|
}
|
|
|
|
public string ProvServerFQDN
|
|
{
|
|
get { return _domainSuffix; }
|
|
}
|
|
|
|
public DateTime Timestamp
|
|
{
|
|
get { return _timpstamp; }
|
|
}
|
|
|
|
public string HashData
|
|
{
|
|
get { return _hash; }
|
|
}
|
|
|
|
public HashAlgorithm HashAlgorithm
|
|
{
|
|
get { return _hashAlg; }
|
|
}
|
|
|
|
public bool HashIsOemDefault
|
|
{
|
|
get { return _isDefault; }
|
|
}
|
|
|
|
public bool TimeValid
|
|
{
|
|
get { return _timeValid; }
|
|
}
|
|
|
|
public bool AdditionalCaSerialNums
|
|
{
|
|
get { return _additionalCaNums; }
|
|
}
|
|
|
|
public string[] CaCertificateSerials
|
|
{
|
|
get { return _caSerials; }
|
|
}
|
|
|
|
public string ProvServerIP
|
|
{
|
|
get { return _ipAddress; }
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
struct GET_AUDIT_RECORD_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
public byte ProvisioningTLSMode;
|
|
public UInt32 SecureDNS;
|
|
public UInt32 HostInitiated;
|
|
public HashAlgorithm SelectedHashType;
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
|
|
public byte[] SelectedHashData;
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
|
|
public byte[] CaCertificateSerials;
|
|
public UInt32 AdditionalCaSerialNums;
|
|
public UInt32 IsOemDefault;
|
|
public UInt32 IsTimeValid;
|
|
public UInt32 ProvServerIP;
|
|
public UInt16 Year;
|
|
public UInt16 Month;
|
|
public UInt16 DayOfWeek;
|
|
public UInt16 Day;
|
|
public UInt16 Hour;
|
|
public UInt16 Minute;
|
|
public UInt16 Second;
|
|
public UInt16 NameLength;
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
struct GET_HECI_RESPONSE
|
|
{
|
|
public byte MajorNumber;
|
|
public byte MinorNumber;
|
|
public UInt16 Reserved;
|
|
public UInt32 Command;
|
|
public UInt32 Length;
|
|
public UInt32 AmtStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct HECI_CLIENT
|
|
{
|
|
public UInt32 MaxMessageLength;
|
|
public byte ProtocolVersion;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct SP_DEVINFO_DATA
|
|
{
|
|
public UInt32 cbSize;
|
|
public Guid ClassGuid;
|
|
public UInt32 DevInst;
|
|
public IntPtr Reserved;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct SP_DEVICE_INTERFACE_DATA
|
|
{
|
|
public uint cbSize;
|
|
public Guid InterfaceClassGuid;
|
|
public uint Flags;
|
|
public IntPtr Reserved;
|
|
}
|
|
|
|
// Device interface detail data
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
|
struct SP_DEVICE_INTERFACE_DETAIL_DATA
|
|
{
|
|
public UInt32 cbSize;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
|
public string DevicePath;
|
|
}
|
|
|
|
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
static extern Boolean SetupDiGetDeviceInterfaceDetail(
|
|
IntPtr hDevInfo,
|
|
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
|
|
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
|
|
UInt32 deviceInterfaceDetailDataSize,
|
|
out UInt32 requiredSize,
|
|
ref SP_DEVINFO_DATA deviceInfoData
|
|
);
|
|
|
|
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
static extern Boolean SetupDiEnumDeviceInterfaces(
|
|
IntPtr hDevInfo,
|
|
IntPtr devInfo,
|
|
ref Guid interfaceClassGuid,
|
|
UInt32 memberIndex,
|
|
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData
|
|
);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
static extern bool CloseHandle(IntPtr hObject);
|
|
|
|
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
|
|
static extern IntPtr SetupDiGetClassDevs(
|
|
ref Guid ClassGuid,
|
|
IntPtr Enumerator,
|
|
IntPtr hwndParent,
|
|
int Flags);
|
|
|
|
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr hDevInfo);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
public static extern SafeFileHandle CreateFile(
|
|
string lpFileName,
|
|
uint dwDesiredAccess,
|
|
uint dwShareMode,
|
|
IntPtr lpSecurityAttributes,
|
|
uint dwCreationDisposition,
|
|
uint dwFlagsAndAttributes,
|
|
IntPtr hTemplateFile);
|
|
|
|
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
static extern bool DeviceIoControl(SafeFileHandle hDevice, uint dwIoControlCode,
|
|
IntPtr lpInBuffer, uint nInBufferSize,
|
|
IntPtr lpOutBuffer, uint nOutBufferSize,
|
|
out uint lpBytesReturned, IntPtr lpOverlapped);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool WriteFile(SafeFileHandle hFile,
|
|
IntPtr lpBuffer,
|
|
uint lpNumberOfBytesToWrite,
|
|
out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool ReadFile(SafeFileHandle hFile,
|
|
IntPtr lpBuffer,
|
|
uint numBytesToRead,
|
|
ref uint lpNumberOfBytesRead, IntPtr lpOverlapped);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool GetOverlappedResult(SafeHandle hFile,
|
|
[In] IntPtr lpOverlapped,
|
|
out uint lpNumberOfBytesTransferred, bool bWait);
|
|
|
|
}
|
|
} |