好人作到底。。<br><br>贴代码给你。<br><br><br>{******************************************************************************}<br>{ CnPack For Delphi/C++Builder }<br>{ 中国人自己的开放源码第三方开发包 }<br>{ (C)Copyright 2001-2008 CnPack 开发组 }<br>{ ------------------------------------ }<br>{ }<br>{ 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }<br>{ 改和重新发布这一程序。 }<br>{ }<br>{ 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }<br>{ 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }<br>{ }<br>{ 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }<br>{ 还没有,可访问我们的网站: }<br>{ }<br>{ 网站地址:http://www.cnpack.org }<br>{ 电子邮件:master@cnpack.org }<br>{ }<br>{******************************************************************************}<br><br>unit CnHardWareInfo;<br>{* |<PRE><br>================================================================================<br>* 软件名称:CnPack 组件包<br>* 单元名称:硬件信息单元<br>* 单元作者:SkyJacker<br>* LiuXiao<br>* Yock<br>* Bahamut<br>* 备 注:硬件信息单元,目前只实现获取多核、多CPU系统中指定CPU的序列号与占用率<br>* 以及部分 BIOS 的 ID.<br>* 开发平台:WindowsXP sp2 + Delphi 6.0 up2<br>* 兼容测试:Win2000/XP + Delphi 5、6<br>* 本 地 化:该单元中的字符串均符合本地化处理方式<br>* 单元标识:$Id: CnHardWareInfo.pas,v 1.9 2008/09/25 12:41:12 liuxiao Exp $<br>* 修改记录:2008.08.01 V1.3<br>* 加入 Bahamut 的获取 BIOS ID 的过程,但只支持小部分 BIOS<br>* 2008.04.12 V1.2<br>* LiuXiao 加入对 CPU 生产厂商名的读取与是否支持 cpuid 指令与序列号<br>* 的属性,感谢 Yock。<br>* 2008.01.12 V1.1<br>* LiuXiao 加入对 CPU 占用率的读取<br>* 2007.01.23 V1.0<br>* 创建单元,实现功能<br>================================================================================<br>|</PRE>}<br><br>interface<br><br>{$I CnPack.inc}<br><br>uses<br> Classes, Windows, SysUtils, ExtCtrls;<br> <br>type<br> TCnCPUIdFormat = (ifContinuous, ifDashed);<br> {* CPU序列号与信息串显示样式<br> |<PRE><br> ifContinuous: -连续型<br> ifDashed: -使用分割符'-'分割<br> |</PRE><br> }<br><br> TCnCpuId = class(TPersistent)<br> {CPU 信息类}<br> private<br> FTimer: TTimer;<br> FCPUCount: Integer;<br> FCPUIds: TStrings;<br> FCPUInfos: TStrings;<br> FSupportCpuIds: TList;<br> FSupportCpuSns: TList;<br> FCPUOems: TStrings;<br> FCPUIdFormat: TCnCPUIdFormat;<br> FCPUUsageRead: Boolean;<br> FCPUUsage: array[0..255] of Integer; // 总不会超过 256 个 CPU 吧?<br> FCurCnt, FLastCnt: array[0..255] of Integer;<br> FAverageCPUUsage: Integer;<br> function GetFirstCPUId: string;<br> function GetCPUId(Index: Integer): string;<br> procedure SetCPUIdFormat(ACPUIdFormat: TCnCPUIdFormat);<br> function GetAverageCPUUsage: Integer;<br> function GetCPUUsage(Index: Integer): Integer;<br> function GetFirstCPUUsage: Integer;<br><br> function RefreshCPUUsages: Cardinal; // 只被定时调用<br> procedure CpuUsageTimer(Sender: TObject);<br> function GetCPUOem(Index: Integer): string;<br> function GetFirstCPUOem: string;<br> function GetSupportCPUId(Index: Integer): Boolean;<br> function GetSupportCPUSn(Index: Integer): Boolean;<br> function GetFirstSupportCPUId: Boolean;<br> function GetFirstSupportCPUSn: Boolean;<br> function GetCPUInfoString(Index: Integer): string;<br> function GetFirstCPUInfoString: string;<br> public<br> constructor Create;<br> {* 构造函数,创建 FCPUIds 并调用 ReadCPUId}<br> destructor Destroy; override;<br><br> procedure ReadCPUId;<br> {* 获得所有 CPU 内核的序列号和其他信息,并存入各个列表}<br><br> property CPUIdFormat: TCnCPUIdFormat read FCPUIdFormat write SetCPUIdFormat;<br> {* CPU 序列号显示样式}<br> property CPUCount: Integer read FCPUCount;<br> {* 系统中 CPU 核总数}<br> property FirstCPUId: string read GetFirstCPUId;<br> {* 获取首个 CPU 的 ID,用于单 CPU 系统}<br> property FirstCPUInfoString: string read GetFirstCPUInfoString;<br> {* 获取首个 CPU 的信息字符串,用于单 CPU 系统}<br> property FirstCPUOem: string read GetFirstCPUOem;<br> {* 获取首个 CPU 的生产厂商,用于单 CPU 系统}<br> property FirstSupportCPUId: Boolean read GetFirstSupportCPUId;<br> {* 获取首个 CPU 是否支持 CPUID 指令,用于单 CPU 系统}<br> property FirstSupportCPUSn: Boolean read GetFirstSupportCPUSn;<br> {* 获取首个 CPU 是否支持读取 CPU 序列号,用于单 CPU 系统}<br> property SupportCPUId[Index: Integer]: Boolean read GetSupportCPUId;<br> {* 获取指定 CPU 是否支持 CPUID 指令}<br> property SupportCPUSn[Index: Integer]: Boolean read GetSupportCPUSn;<br> {* 获取指定 CPU 是否支持读取 CPU 序列号}<br> property CPUId[Index: Integer]: string read GetCPUId;<br> {* 获得指定 CPU 的序列号。索引 Index 从 0 开始。<br> 需要说明的是,序列号很多 CPU 被禁止读取了因此此属性全 0;而网络上流传的<br> CPU 序列号读取,很多情况下读的是下面的“信息字符串”的属性}<br> property CPUInfoString[Index: Integer]: string read GetCPUInfoString;<br> {* 获得指定 CPU 的信息字符串。索引 Index 从 0 开始。<br> 此信息字符串包括了 CPU 的一些特性说明,非唯一,很多情况下被误当做 CPU ID。}<br> property CPUOem[Index: Integer]: string read GetCPUOem;<br> {* 获得指定 CPU 的生产厂商。索引 Index 从 0 开始}<br> property CPUUsage[Index: Integer]: Integer read GetCPUUsage;<br> {* 获得指定 CPU 的占用率,0 到 100<br> 需要说明的是,本类在 NT 系统上采用定时采样获得 CPU 的忙周期数再计算而来,<br> 因此在刚实例化、未采样完成时,得到的 CPU 占用率可能有误。以下同。<br> }<br> property AverageCPUUsage: Integer read GetAverageCPUUsage;<br> {* 获得平均 CPU 占用率,0 到 100}<br> property FirstCPUUsage: Integer read GetFirstCPUUsage;<br> {* 获得首个 CPU 的占用率,0 到 100,用于单 CPU 系统}<br> end;<br><br>function CnGetBiosID: string;<br>{* 获得 BIOS 的 ID,只支持小部分 BIOS,而且旧式的主板由于不规范,无法获取 ID}<br><br>implementation<br><br>const<br> BiosOffset: array[0..2] of DWORD = ($6577, $7196, $7550);<br><br>type<br> PUNICODE_STRING = ^TUNICODE_STRING;<br> _UNICODE_STRING = record<br> Length: Word;<br> MaximumLength: Word;<br> Buffer: PWChar;<br> end;<br> TUNICODE_STRING = _UNICODE_STRING;<br><br> POBJECT_ATTRIBUTES = ^TOBJECT_ATTRIBUTES;<br> _OBJECT_ATTRIBUTES = record<br> Length: ULONG;<br> RootDirectory: THandle;<br> ObjectName: PUNICODE_STRING;<br> Attributes: ULONG;<br> SecurityDescriptor: Pointer;<br> SecurityQualityOfService: Pointer;<br> end;<br> TOBJECT_ATTRIBUTES = _OBJECT_ATTRIBUTES;<br><br> PLARGE_INTEGER = ^LARGE_INTEGER;<br> PPByte = ^PByte;<br><br> _SYSTEM_BASIC_INFORMATION = record<br> Unknown: ULONG;<br> MaximumIncrement: ULONG;<br> PhysicalPageSize: ULONG;<br> NumberOfPhysicalPages: ULONG;<br> LowestPhysicalPage: ULONG;<br> HighestPhysicalPage: ULONG;<br> AllocationGranularity: ULONG;<br> LowestUserAddress: ULONG;<br> HighestUserAddress: ULONG;<br> ActiveProcessors: ULONG;<br> NumberProcessors: UCHAR;<br> end;<br> SYSTEM_BASIC_INFORMATION = _SYSTEM_BASIC_INFORMATION;<br> PSYSTEM_BASIC_INFORMATION = ^SYSTEM_BASIC_INFORMATION;<br> TSystemBasicInformation = SYSTEM_BASIC_INFORMATION;<br> PSystemBasicInformation = ^TSystemBasicInformation;<br><br> SYSTEM_PROCESSOR_TIMES = packed record<br> IdleTime: LARGE_INTEGER;<br> KernelTime: LARGE_INTEGER;<br> UserTime: LARGE_INTEGER;<br> DpcTime: LARGE_INTEGER;<br> InterruptTime: LARGE_INTEGER;<br> InterruptCount: ULONG;<br> end;<br> TSystemProcessorTimes = SYSTEM_PROCESSOR_TIMES;<br> PSystemProcessorTimes = ^TSystemProcessorTimes;<br> <br> SYSTEM_INFORMATION_CLASS = (<br> SystemBasicInformation,<br> SystemProcessorInformation,<br> SystemPerformanceInformation,<br> SystemTimeOfDayInformation,<br> SystemNotImplemented1,<br> SystemProcessesAndThreadsInformation,<br> SystemCallCounts,<br> SystemConfigurationInformation,<br> SystemProcessorTimes,<br> SystemGlobalFlag,<br> SystemNotImplemented2,<br> SystemModuleInformation,<br> SystemLockInformation,<br> SystemNotImplemented3,<br> SystemNotImplemented4,<br> SystemNotImplemented5,<br> SystemHandleInformation,<br> SystemObjectInformation,<br> SystemPagefileInformation,<br> SystemInstructionEmulationCounts,<br> SystemInvalidInfoClass1,<br> SystemCacheInformation,<br> SystemPoolTagInformation,<br> SystemProcessorStatistics,<br> SystemDpcInformation,<br> SystemNotImplemented6,<br> SystemLoadImage,<br> SystemUnloadImage,<br> SystemTimeAdjustment,<br> SystemNotImplemented7,<br> SystemNotImplemented8,<br> SystemNotImplemented9,<br> SystemCrashDumpInformation,<br> SystemExceptionInformation,<br> SystemCrashDumpStateInformation,<br> SystemKernelDebuggerInformation,<br> SystemContextSwitchInformation,<br> SystemRegistryQuotaInformation,<br> SystemLoadAndCallImage,<br> SystemPrioritySeparation,<br> SystemNotImplemented10,<br> SystemNotImplemented11,<br> SystemInvalidInfoClass2,<br> SystemInvalidInfoClass3,<br> SystemTimeZoneInformation,<br> SystemLookasideInformation,<br> SystemSetTimeSlipEvent,<br> SystemCreateSession,<br> SystemDeleteSession,<br> SystemInvalidInfoClass4,<br> SystemRangeStartInformation,<br> SystemVerifierInformation,<br> SystemAddVerifier,<br> SystemSessionProcessesInformation);<br> TSystemInformationClass = SYSTEM_INFORMATION_CLASS;<br> <br> TNativeQuerySystemInformation = function(SystemInformationClass:<br> TSystemInformationClass; SystemInformation: Pointer; SystemInformationLength:<br> Cardinal; ReturnLength: PDWORD): Cardinal; stdcall;<br><br> TZwOpenSection = function (var hWnd: THandle; dwMask: DWORD; PObject: POBJECT_ATTRIBUTES): DWORD; stdcall;<br><br> TZwMapViewOfSection = function (hWnd: THandle; ViewHandle: THandle; PBaseAddr: Pointer;<br> dwLength: ULONG; dwAllocLen: ULONG; PRealAddr: PLARGE_INTEGER; PReadLen: PDWORD;<br> dwInherite: DWORD; dwAllocType: ULONG; dwProtectType: ULONG): DWORD; stdcall;<br><br> TZwUnmapViewOfSection = function (hWnd: THandle; PBaseAddr: Pointer): DWORD; stdcall;<br><br>const<br> STATUS_SUCCESS = $00000000;<br><br>var<br> NtDllHandle: THandle = 0;<br> NtDllNeedFree: Boolean = False;<br><br> NtQuerySystemInformation: TNativeQuerySystemInformation = nil;<br><br> ZwOpenSection: TZwOpenSection = nil;<br><br> ZwMapViewOfSection: TZwMapViewOfSection = nil;<br><br> ZwUnmapViewOfSection: TZwUnmapViewOfSection = nil;<br><br>function GetNtNativeAPIs: Boolean;<br>begin<br> if Win32Platform = VER_PLATFORM_WIN32_NT then<br> begin<br> NtDllHandle := GetModuleHandle('NTDLL.DLL');<br> if NtDllHandle = 0 then<br> begin<br> NtDllHandle := LoadLibrary('NTDLL.DLL');<br> NtDllNeedFree := NtDllHandle <> 0;<br> end;<br><br> if NtDllHandle <> 0 then<br> begin<br>// @NtQueryInformationToken:=GetProcAddress(NtDllHandle,'NtQueryInformationToken');<br>// @NtOpenProcessToken := GetProcAddress(NtDllHandle,'NtOpenProcessToken');<br>// @NtOpenSection := GetProcAddress(NtDllHandle,'NtOpenSection');<br>// @NtClose := GetProcAddress(NtDllHandle,'NtClose');<br>// @NtOpenProcess := GetProcAddress(NtDllHandle,'NtOpenProcess');<br> @NtQuerySystemInformation := GetProcAddress(NtDllHandle, 'NtQuerySystemInformation');<br>// @NtCreateSection := GetProcAddress(NtDllHandle,'NtCreateSection');<br>// @NtCreateToken := GetProcAddress(NtDllHandle,'NtCreateToken');<br>// @NtMapViewOfSection := GetProcAddress(NtDllHandle,'NtMapViewOfSection');<br>// @NtUnmapViewOfSection := GetProcAddress(NtDllHandle,'NtUnmapViewOfSection');<br>// @NtOpenFile := GetProcAddress(NtDllHandle,'NtOpenFile');<br>// @NtCreateFile := GetProcAddress(NtDllHandle,'NtCreateFile');<br>// @NtQueryObject := GetProcAddress(NtDllHandle,'NtQueryObject');<br>// @NtQueryInformationProcess := GetProcAddress(NtDllHandle,'NtQueryInformationProcess');<br>// @NtQueryInformationThread := GetProcAddress(NtDllHandle,'NtQueryInformationThread');<br>// @NtQueryInformationFile := GetProcAddress(NtDllHandle,'NtQueryInformationFile');<br>// @NtDuplicateObject := GetProcAddress(NtDllHandle,'NtDuplicateObject');<br>// @NtDeviceIoControlFile := GetProcAddress(NtDllHandle,'NtDeviceIoControlFile');<br><br> @ZwOpenSection := GetProcAddress(NtDllHandle, 'ZwOpenSection');<br> @ZwMapViewOfSection := GetProcAddress(NtDllHandle, 'ZwMapViewOfSection');<br> @ZwUnmapViewOfSection := GetProcAddress(NtDllHandle, 'ZwUnmapViewOfSection');<br> end;<br> end;<br> Result := NtDllHandle <> 0;<br>end;<br><br>procedure FreeNtNativeAPIs;<br>begin<br> if (NtDllHandle <> 0) and NtDllNeedFree then<br> begin<br> FreeLibrary(NtDllHandle);<br> NtDllHandle := 0;<br> end;<br>end;<br><br>constructor TCnCpuId.Create;<br>begin<br> FSupportCpuIds := TList.Create;<br> FSupportCpuSns := TList.Create;<br> FCPUIds := TStringList.Create;<br> FCPUInfos := TStringList.Create;<br> FCPUOems := TStringList.Create;<br> FCPUIdFormat := ifContinuous;<br> ReadCPUId;<br><br> FTimer := TTimer.Create(nil);<br> FTimer.Interval := 1000;<br> FTimer.OnTimer := CpuUsageTimer;<br> FTimer.Enabled := True;<br> RefreshCPUUsages;<br><br> if Win32Platform = VER_PLATFORM_WIN32_NT then // NT 下需要采样判断<br> FCPUUsageRead := False;<br>end;<br><br>destructor TCnCpuId.Destroy;<br>begin<br> FTimer.Free;<br> FCPUOems.Free;<br> FCPUInfos.Free;<br> FCPUIds.Free;<br> FSupportCpuSns.Free;<br> FSupportCpuIds.Free;<br>end;<br><br>// 获取所有 CPU 的序列号<br>procedure TCnCpuId.ReadCPUId;<br>const<br> SCN_CPUID_BIT = $200000; //CPU ID 位标记<br>var<br> I: Integer;<br> Mask: Integer;<br> CurrProc: THandle;<br> SysInfo: TSystemInfo;<br> ProcessAffinityOld: Cardinal;<br> ProcessAffinity: Cardinal;<br> SystemAffinity: Cardinal;<br><br> function GetCnCpuIdSupport: Boolean;<br> asm<br> PUSHFD //不允许直接存取,必须通过堆栈<br> POP EAX<br> MOV EDX, EAX<br> XOR EAX, SCN_CPUID_BIT<br> PUSH EAX<br> POPFD<br> PUSHFD<br> POP EAX<br> XOR EAX,EDX // 检测 ID 位是否受影响<br> JZ @exit // CPUID 无效<br> MOV AL, 1 // CPUID 有效<br> @exit:<br> end;<br><br> // 获取 CPU 信息字符串<br> function GetCnCPUInfoString: string;<br> const<br> cnIFContinuous = '%.8x%.8x%.8x%.8x';<br> cnIFDashed = '%.8x-%.8x-%.8x-%.8x';<br> var<br> iEax,iEbx,iEcx,iEdx: Integer;<br> begin<br> asm<br> push ebx<br> push ecx<br> push edx<br> mov eax, $1<br> dw $A20F //CPUID<br> mov iEax, eax<br> mov iEbx, ebx<br> mov iEcx, ecx<br> mov iEdx, edx<br> pop edx<br> pop ecx<br> pop ebx<br> end;<br> if FCPUIdFormat = ifContinuous then<br> Result := Format(cnIFContinuous, [iEax, iEbx, iEcx, iEdx])<br> else<br> Result := Format(cnIFDashed, [iEax, iEbx, iEcx, iEdx])<br> end;<br><br> // 获取 CPU 序列号<br> function GetCnCPUID: string;<br> const<br> SCnIFContinuous = '%.4x%.4x%.4x%.4x%.4x%.4x';<br> SCnIFDashed = '%.4x-%.4x-%.4x-%.4x-%.4x-%.4x';<br> var<br> SFmt: string;<br> iEax, iEcx, iEdx, iEdx1: Integer;<br> begin<br> asm<br> push ebx<br> push ecx<br> push edx<br> mov eax, $1<br> dw $A20F //CPUID<br> mov iEax, eax<br> mov iEdx1, edx<br> mov eax, $3<br> dw $A20F<br> mov iEcx, ecx<br> mov iEdx, edx<br> pop edx<br> pop ecx<br> pop ebx<br> end;<br><br> if FCPUIdFormat=ifContinuous then<br> SFmt := SCnIFContinuous<br> else<br> SFmt := SCnIFDashed;<br><br> if iEdx1 and (1 shr 18) = 0 then // Cpu 序列号不能读,返回全0<br> begin<br> Result := Format(SFmt, [0, 0, 0, 0, 0, 0]);<br> FSupportCpuSns.Add(nil); // 加 False<br> end<br> else<br> begin<br> FSupportCpuSns.Add(Pointer(True));<br> Result := Format(SFmt,<br> [(iEax and $FFFF0000) shr 16, iEax and $FFFF,<br> (iEcx and $FFFF0000) shr 16, iEcx and $FFFF,<br> (iEdx and $FFFF0000) shr 16, iEdx and $FFFF]);<br> end;<br> end;<br><br> // 获得 CPU OEM 厂商名<br> function GetCnCPUOem: string;<br> var<br> iEax, iEbx, iEcx, iEdx: Integer;<br> begin<br> asm<br> push ebx<br> push ecx<br> push edx<br> mov eax, $0<br> dw $A20F //CPUID<br> mov iEax, eax<br> mov iEbx, ebx<br> mov iEcx, ecx<br> mov iEdx, edx<br> pop edx<br> pop ecx<br> pop ebx<br> end;<br> SetLength(Result, 3 * SizeOf(Integer));<br> CopyMemory(@Result[1], @iEbx, SizeOf(Integer));<br> CopyMemory(@Result[1 + SizeOf(Integer)], @iEdx, SizeOf(Integer));<br> CopyMemory(@Result[1 + 2 * SizeOf(Integer)], @iEcx, SizeOf(Integer));<br> end;<br>begin<br> FCPUCount := 0;<br> FSupportCpuIds.Clear;<br> FSupportCpuSns.Clear;<br> FCPUIds.Clear;<br> FCPUOems.Clear;<br> <br> // 获取 CPU 个数<br> GetSystemInfo(SysInfo);<br> FCPUCount := SysInfo.dwNumberOfProcessors;<br><br> // 获取所有 CPU 的序列号<br> Mask := $1;<br> CurrProc := GetCurrentProcess;<br> if not GetProcessAffinityMask(CurrProc, ProcessAffinityOld, SystemAffinity) then<br> Exit;<br><br> try<br> for I := 0 to FCpuCount - 1 do<br> begin<br> ProcessAffinity := Mask shl I;<br> if not SetProcessAffinityMask(CurrProc, ProcessAffinity) then<br> Break;<br><br> FSupportCpuIds.Add(Pointer(GetCnCpuIdSupport));<br> if FSupportCpuIds[FSupportCpuIds.Count - 1] <> nil then<br> begin<br> FCPUIds.Add(GetCnCPUID);<br> FCPUInfos.Add(GetCnCPUInfoString);<br> FCPUOems.Add(GetCnCPUOem);<br> end<br> else<br> begin<br> FCPUIds.Add('');<br> FCPUInfos.Add('');<br> FCPUOems.Add(''); <br> end;<br> end;<br> finally<br> //恢复默认<br> SetProcessAffinityMask(CurrProc, ProcessAffinityOld);<br> end;<br>end;<br><br>procedure TCnCpuId.SetCPUIdFormat(ACPUIdFormat: TCnCPUIdFormat);<br>begin<br> if FCPUIdFormat <> ACPUIdFormat then<br> begin<br> FCPUIdFormat := ACPUIdFormat;<br> ReadCPUId;<br> end;<br>end;<br><br>// 获得单 CPU 系统 ID<br>function TCnCpuId.GetFirstCPUId: string;<br>begin<br> if FCPUIds.Count > 0 then<br> Result := FCPUIds.Strings[0];<br>end;<br><br>// 得到第几个 CPU 的序列号<br>function TCnCpuId.GetCPUId(Index: Integer): string;<br>begin<br> Result := '';<br> // 保证 FCPUIds 索引的合法性<br> if (Index < 0) or (Index > FCPUIds.Count - 1) then<br> Exit;<br><br> Result := FCPUIds.Strings[Index];<br>end;<br><br>function TCnCpuId.GetAverageCPUUsage: Integer;<br>begin<br> if not FCPUUsageRead then<br> Result := -1<br> else<br> Result := FAverageCPUUsage;<br>end;<br><br>function TCnCpuId.GetCPUUsage(Index: Integer): Integer;<br>begin<br> if not FCPUUsageRead or (Index > FCPUCount - 1) then<br> Result := -1<br> else<br> Result := FCPUUsage[Index];<br>end;<br><br>function TCnCpuId.GetFirstCPUUsage: Integer;<br>begin<br> if FCPUUsageRead and (FCPUCount > 0) then<br> Result := FCPUUsage[0]<br> else<br> Result := -1;<br>end;<br><br>function TCnCpuId.RefreshCPUUsages: Cardinal;<br>var<br> CpuCnt: Cardinal;<br> I: integer;<br> Spt: Pointer;<br> Sbi: TSystemBasicInformation;<br><br> dwType, cbData: Cardinal;<br> hOpen: HKEY;<br> Buffer: Cardinal;<br>begin<br> if Win32Platform = VER_PLATFORM_WIN32_NT then<br> begin<br> for I := 0 to FCPUCount - 1 do // 保存旧值<br> FLastCnt := FCurCnt;<br><br> if NtQuerySystemInformation(SystemBasicInformation, @Sbi, SizeOf(Sbi), nil)<br> <> STATUS_SUCCESS then<br> CpuCnt := 1<br> else<br> CpuCnt := Sbi.NumberProcessors;<br><br> Spt := AllocMem(CpuCnt * (SizeOf(TSystemProcessorTimes) + 4));<br> NtQuerySystemInformation(SystemProcessorTimes, Spt, CpuCnt * (SizeOf(TSystemProcessorTimes) + 4), @Result);<br><br> for I := 0 to CpuCnt - 1 do<br> begin<br> with PSystemProcessorTimes(PChar(Spt) + I * (sizeof(TSystemProcessorTimes) + 4))^ do<br> FCurCnt := IdleTime.QuadPart;<br> <br> // 采样后计算<br> try<br> FCPUUsage := Round((10000000 - (FCurCnt - FLastCnt) / (FTimer.Interval / 1000)) / 10000000 * 100);<br> except<br> FCPUUsage := 0;<br> end;<br> end;<br> FreeMem(spt);<br> end<br> else<br> begin<br> if RegOpenKeyEx(HKEY_DYN_DATA,'PerfStats/StatData', 0, KEY_READ, hOpen) = ERROR_SUCCESS then<br> begin<br> cbData:=sizeof(Cardinal);<br> if RegQueryValueEx(hOpen, 'KERNEL/CPUUsage', nil, @dwType, PBYTE(@Buffer),<br> @cbData) = ERROR_SUCCESS then<br> FCPUUsage[0] := Buffer;<br> RegCloseKey(hOpen);<br> end<br> else<br> FCPUUsage[0] := -1;<br> end;<br><br> FCPUUsageRead := True;<br>end;<br><br>procedure TCnCpuId.CpuUsageTimer(Sender: TObject);<br>var<br> I: Integer;<br>begin<br> RefreshCPUUsages;<br> <br> FAverageCPUUsage := 0;<br> for I := 0 to FCPUCount - 1 do<br> begin<br> if FCPUUsage <> -1 then<br> FAverageCPUUsage := FAverageCPUUsage + FCPUUsage;<br> end;<br><br> if FCPUCount > 0 then<br> FAverageCPUUsage := Round(FAverageCPUUsage / FCPUCount)<br> else<br> FAverageCPUUsage := -1;<br>end;<br><br>function TCnCpuId.GetCPUOem(Index: Integer): string;<br>begin<br> Result := '';<br> // 保证 FCPUIds 索引的合法性<br> if (Index < 0) or (Index > FCPUOems.Count - 1) then<br> Exit;<br><br> Result := FCPUOems.Strings[Index];<br>end;<br><br>function TCnCpuId.GetFirstCPUOem: string;<br>begin<br> if FCPUOems.Count > 0 then<br> Result := FCPUOems.Strings[0];<br>end;<br><br>function TCnCpuId.GetSupportCPUId(Index: Integer): Boolean;<br>begin<br> Result := False;<br> // 保证 FSupportCpuIds 索引的合法性<br> if (Index < 0) or (Index > FSupportCpuIds.Count - 1) then<br> Exit;<br><br> Result := Boolean(FSupportCpuIds[Index]);<br>end;<br><br>function TCnCpuId.GetSupportCPUSn(Index: Integer): Boolean;<br>begin<br> Result := False;<br> // 保证 FSupportCpuIds 索引的合法性<br> if (Index < 0) or (Index > FSupportCpuSns.Count - 1) then<br> Exit;<br><br> Result := Boolean(FSupportCpuSns[Index]);<br>end;<br><br>function TCnCpuId.GetFirstSupportCPUId: Boolean;<br>begin<br> Result := False;<br> if FSupportCpuIds.Count > 0 then<br> Result := Boolean(FSupportCpuIds[0]);<br>end;<br><br>function TCnCpuId.GetFirstSupportCPUSn: Boolean;<br>begin<br> Result := False;<br> if FSupportCpuSns.Count > 0 then<br> Result := Boolean(FSupportCpuSns[0]);<br>end;<br><br>function TCnCpuId.GetCPUInfoString(Index: Integer): string;<br>begin<br> Result := '';<br> if (Index < 0) or (Index > FCPUInfos.Count - 1) then<br> Exit;<br><br> Result := FCPUInfos.Strings[Index];<br>end;<br><br>function TCnCpuId.GetFirstCPUInfoString: string;<br>begin<br> if FCPUInfos.Count > 0 then<br> Result := FCPUInfos[0];<br>end;<br><br>function FindAwardBios(var BiosAddr: PByte): UINT;<br>var<br> ABiosAddr: PByte;<br> szBiosData: array [0..127] of Char;<br> Len: Integer;<br> Loop: Byte;<br>begin<br> Result:= 0;<br> ABiosAddr:= PByte(DWORD(BiosAddr) + $EC71);<br><br> CopyMemory(@szBiosData[0], ABiosAddr, 127);<br> szBiosData[127]:= #0;<br><br> Len:= StrLen(PChar(@szBiosData[0]));<br> if (Len <= 0) or (Len >= 128) then<br> Exit;<br><br> //AWard: 07/08/2002-i845G-ITE8712-JF69VD0CC-00<br> //Phoenix-Award: 03/12/2002-sis645-p4s333<br> if (szBiosData[2] <> '/') or (szBiosData[5] <> '/') then<br> Exit;<br><br> Loop:= 0;<br> while szBiosData[Loop] <> #0 do<br> begin<br> if (szBiosData[Loop] < ' ') or (szBiosData[Loop] >= Chr(127)) then<br> Break;<br> Inc(Loop);<br> end;<br><br> if szBiosData[Loop] = #0 then<br> begin<br> BiosAddr:= ABiosAddr;<br> Result:= Len;<br> end;<br>end;<br><br>function FindAmiBios(var BiosAddr: PByte): UINT;<br>var<br> ABiosAddr: PByte;<br> szBiosData: array [0..127] of Char;<br> Len: Integer;<br> Loop: Byte;<br>begin<br> Result:= 0;<br> ABiosAddr:= PByte(DWORD(BiosAddr) + $F478);<br><br> CopyMemory(@szBiosData[0], ABiosAddr, 127);<br> szBiosData[127]:= #0;<br><br> Len:= StrLen(PChar(@szBiosData[0]));<br> if (Len <= 0) or (Len >= 128) then<br> Exit;<br><br> // Example: "AMI: 51-2300-000000-00101111-030199-"<br> if (szBiosData[2] <> '-') or (szBiosData[7] <> '-') then<br> Exit;<br><br> Loop:= 0;<br> while szBiosData[Loop] <> #0 do<br> begin<br> if (szBiosData[Loop] < ' ') or (szBiosData[Loop] >= Chr(127)) then<br> Break;<br> Inc(Loop);<br> end;<br><br> if szBiosData[Loop] = #0 then<br> begin<br> BiosAddr:= ABiosAddr;<br> Result:= Len;<br> end;<br>end;<br><br>function FindPhoenixBios(var BiosAddr: PByte): UINT;<br>var<br> ABiosAddr: PByte;<br> szBiosData: array [0..127] of Char;<br> Len: Integer;<br> I, Loop: Byte;<br>begin<br> for I := 0 to 2 do<br> begin<br> ABiosAddr:= PByte(DWORD(BiosAddr) + BiosOffset);<br> CopyMemory(@szBiosData[0], ABiosAddr, 127);<br> szBiosData[127]:= #0;<br> Len:= StrLen(PChar(@szBiosData[0]));<br> if (Len <= 0) or (Len >= 128) then<br> Continue;<br><br> // Example: Phoenix "NITELT0.86B.0044.P11.9910111055"<br> if (szBiosData[7] <> '.') or (szBiosData[11] <> '.') then<br> Continue;<br><br> Loop:= 0;<br> while szBiosData[Loop] <> #0 do<br> begin<br> if (szBiosData[Loop] < ' ') or (szBiosData[Loop] >= Chr(127)) then<br> Break;<br> Inc(Loop);<br> end;<br><br> if szBiosData[Loop] = #0 then<br> begin<br> BiosAddr:= ABiosAddr;<br> Result:= Len;<br> Exit;<br> end;<br> end;<br> Result:= 0;<br>end;<br><br>function CnGetBiosID: string;<br>var<br> Size: DWORD;<br> RealAddr: LARGE_INTEGER;<br> Path: PWCHAR;<br> BaseAddr: DWORD;<br> UniString: TUNICODE_STRING;<br> Obj: TOBJECT_ATTRIBUTES;<br> hSection: THandle;<br> PBiosSerial: PByte;<br> uBiosSerialLen: UINT;<br> szSystemInfo: array [0..4095] of Char;<br> ReturnLen: UINT;<br>begin<br> FillChar(szSystemInfo, 4096, 0);<br> ReturnLen:= 0;<br><br> RealAddr.LowPart:= $000F0000;<br> RealAddr.HighPart:= $00000000;<br> Size:= $FFFF;<br> Path:= '/device/physicalmemory';<br> BaseAddr:= 0;<br> UniString.Buffer:= Path;<br> UniString.Length:= $2C;<br> UniString.MaximumLength:= $2E;<br><br> Obj.Attributes:= 64;<br> Obj.Length:= 24;<br> Obj.ObjectName:= @UniString;<br> Obj.RootDirectory:= 0;<br> Obj.SecurityDescriptor:= nil;<br> Obj.SecurityQualityOfService:= nil;<br><br> //调用函数,对物理内存进行映射<br> if (ZwOpenSection(hSection, 4, @Obj) = 0) and<br> (ZwMapViewOfSection(hSection, $FFFFFFFF, @BaseAddr, 0, $FFFF, @RealAddr, @Size, 1, 0, 2) = 0) then<br> begin<br> //执行后会在当前进程的空间开辟一段64k的空间,并把f000:0000到f000:ffff处的内容映射到这里<br> //映射的基址由BaseAddr返回,如果映射不再有用,应该用ZwUnmapViewOfSection断开映射<br> PBiosSerial:= PByte(BaseAddr);<br> uBiosSerialLen:= FindAwardBios(PBiosSerial);<br> if uBiosSerialLen = 0 then<br> begin<br> uBiosSerialLen:= FindAmiBios(PBiosSerial);<br> if uBiosSerialLen = 0 then<br> uBiosSerialLen:= FindPhoenixBios(PBiosSerial);<br> end;<br><br> if uBiosSerialLen <> 0 then<br> begin<br> CopyMemory(Pointer(szSystemInfo + ReturnLen), PBiosSerial, uBiosSerialLen);<br> Inc(ReturnLen, uBiosSerialLen);<br> end;<br> ZwUnmapViewOfSection($FFFFFFFF, Pointer(BaseAddr));<br> end;<br><br> if ReturnLen <> 0 then<br> begin<br> SetLength(Result, ReturnLen);<br> MoveMemory(@Result[1], @szSystemInfo[0], ReturnLen);<br> end;<br>end;<br><br>initialization<br> GetNtNativeAPIs;<br><br>finalization<br> FreeNtNativeAPIs;<br><br>end.