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);
}
}