namespace ConsoleApplication { using System; using Microshaoft; /// <summary> /// Class1 的摘要说明。 /// </summary> public class Class1 { /// <summary> /// 应用程序的主入口点。 /// </summary> //[STAThread] static void Main(string[] args) { // // TODO: 在此处添加代码以启动应用程序 // Console.WriteLine("Hello World"); string s = AtapiDevice.GetHddInfo(0).SerialNumber; Console.WriteLine(s); Console.WriteLine(Environment.Version.ToString()); } } } namespace Microshaoft { using System; using System.Runtime.InteropServices; using System.Text; [Serializable] public struct HardDiskInfo { /// <summary> /// 型号 /// </summary> public string ModuleNumber; /// <summary> /// 固件版本 /// </summary> public string Firmware; /// <summary> /// 序列号 /// </summary> public string SerialNumber; /// <summary> /// 容量,以M为单位 /// </summary> public uint Capacity; } #region Internal Structs [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct GetVersionOutParams { public byte bVersion; public byte bRevision; public byte bReserved; public byte bIDEDeviceMap; public uint fCapabilities; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public uint[] dwReserved; // For future use. } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct IdeRegs { public byte bFeaturesReg; public byte bSectorCountReg; public byte bSectorNumberReg; public byte bCylLowReg; public byte bCylHighReg; public byte bDriveHeadReg; public byte bCommandReg; public byte bReserved; } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct SendCmdInParams { public uint cBufferSize; public IdeRegs irDriveRegs; public byte bDriveNumber; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] bReserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public uint[] dwReserved; public byte bBuffer; } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct DriverStatus { public byte bDriverError; public byte bIDEStatus; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] bReserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] dwReserved; } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct SendCmdOutParams { public uint cBufferSize; public DriverStatus DriverStatus; public IdSector bBuffer; } [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 512)] internal struct IdSector { public ushort wGenConfig; public ushort wNumCyls; public ushort wReserved; public ushort wNumHeads; public ushort wBytesPerTrack; public ushort wBytesPerSector; public ushort wSectorsPerTrack; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public ushort[] wVendorUnique; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] sSerialNumber; public ushort wBufferType; public ushort wBufferSize; public ushort wECCSize; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] sFirmwareRev; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] public byte[] sModelNumber; public ushort wMoreVendorUnique; public ushort wDoubleWordIO; public ushort wCapabilities; public ushort wReserved1; public ushort wPIOTiming; public ushort wDMATiming; public ushort wBS; public ushort wNumCurrentCyls; public ushort wNumCurrentHeads; public ushort wNumCurrentSectorsPerTrack; public uint ulCurrentSectorCapacity; public ushort wMultSectorStuff; public uint ulTotalAddressableSectors; public ushort wSingleWordDMA; public ushort wMultiWordDMA; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] bReserved; } #endregion /// <summary> /// ATAPI驱动器相关 /// </summary> public class AtapiDevice { #region DllImport [DllImport("kernel32.dll", SetLastError = true)] static extern int CloseHandle(IntPtr hObject); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr CreateFile ( string lpFileName , uint dwDesiredAccess , uint dwShareMode , IntPtr lpSecurityAttributes , uint dwCreationDisposition , uint dwFlagsAndAttributes , IntPtr hTemplateFile ); [DllImport("kernel32.dll")] static extern int DeviceIoControl ( IntPtr hDevice , uint dwIoControlCode , IntPtr lpInBuffer , uint nInBufferSize , ref GetVersionOutParams lpOutBuffer , uint nOutBufferSize , ref uint lpBytesReturned , [Out] IntPtr lpOverlapped ); [DllImport("kernel32.dll")] static extern int DeviceIoControl ( IntPtr hDevice , uint dwIoControlCode , ref SendCmdInParams lpInBuffer , uint nInBufferSize , ref SendCmdOutParams lpOutBuffer , uint nOutBufferSize , ref uint lpBytesReturned , [Out] IntPtr lpOverlapped ); const uint DFP_GET_VERSION = 0x00074080; const uint DFP_SEND_DRIVE_COMMAND = 0x0007c084; const uint DFP_RECEIVE_DRIVE_DATA = 0x0007c088; const uint GENERIC_READ = 0x80000000; const uint GENERIC_WRITE = 0x40000000; const uint FILE_SHARE_READ = 0x00000001; const uint FILE_SHARE_WRITE = 0x00000002; const uint CREATE_NEW = 1; const uint OPEN_EXISTING = 3; #endregion #region GetHddInfo /// <summary> /// 获得硬盘信息 /// </summary> /// <param name="driveIndex">硬盘序号</param> /// <returns>硬盘信息</returns> /// <remarks> /// 参考lu0的文章:http://lu0s1.3322.org/App/2k1103.html /// by sunmast for everyone /// thanks lu0 for his great works /// 在Windows 98/ME中,S.M.A.R.T并不缺省安装,请将SMARTVSD.VXD拷贝到%SYSTEM%\IOSUBSYS目录下。 /// 在Windows 2000/2003下,需要Administrators组的权限。 /// </remarks> /// <example> /// AtapiDevice.GetHddInfo() /// </example> public static HardDiskInfo GetHddInfo(byte driveIndex) { switch (Environment.OSVersion.Platform) { case PlatformID.Win32Windows: return GetHddInfo9x(driveIndex); case PlatformID.Win32NT: return GetHddInfoNT(driveIndex); case PlatformID.Win32S: throw new NotSupportedException("Win32s is not supported."); case PlatformID.WinCE: throw new NotSupportedException("WinCE is not supported."); default: throw new NotSupportedException("Unknown Platform."); } } #region GetHddInfo9x private static HardDiskInfo GetHddInfo9x(byte driveIndex) { GetVersionOutParams vers = new GetVersionOutParams(); SendCmdInParams inParam = new SendCmdInParams(); SendCmdOutParams outParam = new SendCmdOutParams(); uint bytesReturned = 0; IntPtr hDevice = CreateFile ( @"\\.\Smartvsd" , 0 , 0 , IntPtr.Zero , CREATE_NEW , 0 , IntPtr.Zero ); if (hDevice == IntPtr.Zero) { throw new Exception("Open smartvsd.vxd failed."); } if (0 == DeviceIoControl ( hDevice , DFP_GET_VERSION , IntPtr.Zero , 0 , ref vers , (uint) Marshal.SizeOf(vers) , ref bytesReturned , IntPtr.Zero ) ) { CloseHandle(hDevice); throw new Exception("DeviceIoControl failed:DFP_GET_VERSION"); } // If IDE identify command not supported, fails if (0 == (vers.fCapabilities & 1)) { CloseHandle(hDevice); throw new Exception("Error: IDE identify command not supported."); } if (0 != (driveIndex & 1)) { inParam.irDriveRegs.bDriveHeadReg = 0xb0; } else { inParam.irDriveRegs.bDriveHeadReg = 0xa0; } if (0 != (vers.fCapabilities & (16 >> driveIndex))) { // We don''t detect a ATAPI device. CloseHandle(hDevice); throw new Exception(string.Format("Drive {0} is a ATAPI device, we don''t detect it", driveIndex + 1)); } else { inParam.irDriveRegs.bCommandReg = 0xec; } inParam.bDriveNumber = driveIndex; inParam.irDriveRegs.bSectorCountReg = 1; inParam.irDriveRegs.bSectorNumberReg = 1; inParam.cBufferSize = 512; if (0 == DeviceIoControl ( hDevice , DFP_RECEIVE_DRIVE_DATA , ref inParam , (uint) Marshal.SizeOf(inParam) , ref outParam, (uint) Marshal.SizeOf(outParam) , ref bytesReturned , IntPtr.Zero ) ) { CloseHandle(hDevice); throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA"); } CloseHandle(hDevice); return GetHardDiskInfo(outParam.bBuffer); } #endregion #region GetHddInfoNT private static HardDiskInfo GetHddInfoNT(byte driveIndex) { GetVersionOutParams vers = new GetVersionOutParams(); SendCmdInParams inParam = new SendCmdInParams(); SendCmdOutParams outParam = new SendCmdOutParams(); uint bytesReturned = 0; // We start in NT/Win2000 IntPtr hDevice = CreateFile( string.Format(@"\\.\PhysicalDrive{0}", driveIndex), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (hDevice == IntPtr.Zero) { throw new Exception("CreateFile faild."); } if (0 == DeviceIoControl ( hDevice , DFP_GET_VERSION , IntPtr.Zero , 0 , ref vers , (uint) Marshal.SizeOf(vers) , ref bytesReturned , IntPtr.Zero ) ) { CloseHandle(hDevice); throw new Exception(string.Format("Drive {0} may not exists.", driveIndex + 1)); } // If IDE identify command not supported, fails if (0 == (vers.fCapabilities & 1)) { CloseHandle(hDevice); throw new Exception("Error: IDE identify command not supported."); } // Identify the IDE drives if (0 != (driveIndex & 1)) { inParam.irDriveRegs.bDriveHeadReg = 0xb0; } else { inParam.irDriveRegs.bDriveHeadReg = 0xa0; } if (0 != (vers.fCapabilities & (16 >> driveIndex))) { // We don''t detect a ATAPI device. CloseHandle(hDevice); throw new Exception(string.Format("Drive {0} is a ATAPI device, we don''t detect it.", driveIndex + 1)); } else { inParam.irDriveRegs.bCommandReg = 0xec; } inParam.bDriveNumber = driveIndex; inParam.irDriveRegs.bSectorCountReg = 1; inParam.irDriveRegs.bSectorNumberReg = 1; inParam.cBufferSize = 512; if (0 == DeviceIoControl ( hDevice , DFP_RECEIVE_DRIVE_DATA , ref inParam , (uint)Marshal.SizeOf(inParam) , ref outParam , (uint)Marshal.SizeOf(outParam) , ref bytesReturned , IntPtr.Zero ) ) { CloseHandle(hDevice); throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA"); } CloseHandle(hDevice); return GetHardDiskInfo(outParam.bBuffer); } #endregion private static HardDiskInfo GetHardDiskInfo(IdSector phdinfo) { HardDiskInfo hddInfo = new HardDiskInfo(); ChangeByteOrder(phdinfo.sModelNumber); hddInfo.ModuleNumber = Encoding.ASCII.GetString(phdinfo.sModelNumber).Trim(); ChangeByteOrder(phdinfo.sFirmwareRev); hddInfo.Firmware = Encoding.ASCII.GetString(phdinfo.sFirmwareRev).Trim(); ChangeByteOrder(phdinfo.sSerialNumber); hddInfo.SerialNumber = Encoding.ASCII.GetString(phdinfo.sSerialNumber).Trim(); hddInfo.Capacity = phdinfo.ulTotalAddressableSectors / 2 / 1024; return hddInfo; } private static void ChangeByteOrder(byte[] charArray) { byte temp; for (int i = 0; i < charArray.Length; i += 2) { temp = charArray[i]; charArray[i] = charArray[i + 1]; charArray[i + 1] = temp; } } #endregion } }