System info
От: Thinker  
Дата: 27.03.03 10:03
Оценка:
Здравствуй Уважаемый All.

Возникла острая потребность в сборе информации о железке
(проц,винт, память и прочая лабуда)

Подскажите есть ли соответствующие компоненты или ткните носом на нужные функции API.

Буду рад хорошим советам и правильным посыланиям



With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re: System info
От: serg_p Украина  
Дата: 27.03.03 10:09
Оценка:
WMI — то что Вам нужно.
Re[2]: System info
От: Thinker  
Дата: 27.03.03 10:43
Оценка:
Здравствуйте, serg_p, Вы писали:

SP>WMI — то что Вам нужно.


Я дико извиняюсь а что это такое и с чем его едят ???

With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[3]: System info
От: VVV Россия  
Дата: 27.03.03 11:48
Оценка:
Здравствуйте, Thinker, Вы писали:

T>Здравствуйте, serg_p, Вы писали:


SP>>WMI — то что Вам нужно.


T>Я дико извиняюсь а что это такое и с чем его едят ???


T>With best regards, Thinker


Сделай поиск по сайту по слову winmgmts.
Re[3]: System info
От: serg_p Украина  
Дата: 27.03.03 12:08
Оценка:
T>Я дико извиняюсь а что это такое и с чем его едят ???

WMI(Windows Management Instrumentation) — технология, позволяющая получать практически любую(очень много информацию о системе и управлять ей, например получать уведомления о создании процессов, о подключении пользователей, получать некоторые характеристики "железа", работать с файловой системой и т. д.
Вот ссылка в MSDN:
ms-help://MS.VSCC/MS.MSDNVS/wmisdk/wmistart_5kth.htm

Добраться до WMI можно как через скрипт так и через COM, вот примеры использования на VBScript:
http://www.rsdn.ru/Forum/?mid=197594
Автор: serg_p
Дата: 18.02.03

http://www.rsdn.ru/Forum/?mid=206021
Автор: serg_p
Дата: 03.03.03
Re[2]: System info
От: payglobal  
Дата: 28.03.03 05:35
Оценка:
Здравствуйте, serg_p, Вы писали:

SP>WMI — то что Вам нужно.


как показывает практика WMI — иногда не то, что нужно
1) сервис WMI может быть остановлен
2) в стандартной поставке Win9x/ME его нет

... и последнее — некоторые запросы выполняются убийственно медленно, захватывая при этом уйму ресурсов

совет — посмотри на codeguru или codeproject.

а если что конкретно нужно будет — спрашивай. это уже проходил
... << RSDN@Home 1.0 beta 6a >>
Re[3]: System info
От: serg_p Украина  
Дата: 28.03.03 07:18
Оценка:
P>как показывает практика WMI — иногда не то, что нужно
Не всегда — но очень часто именно то что нужно.

P>1) сервис WMI может быть остановлен

и компьютер можно из розетки выключить.

P>2) в стандартной поставке Win9x/ME его нет

Это не повод что-бы не изучать WMI — Windows 9x/ME скоро вымрут как динозавры. И потом инсталлировать WMI на эти Windows'ы не составляет никаких проблем.

P>... и последнее — некоторые запросы выполняются убийственно медленно, захватывая при этом уйму ресурсов

Да, но зато при помощи WMI можно производить мониторинг/управление удаленным компьютером по аналогии с локальным.
И опять — же нельзя забывать то, что к нему (к WMI)можно добраться в том числе из script'a, что очень часто бывает полезно — за пару минут получать желаемый результат.
Re[4]: System info
От: payglobal  
Дата: 28.03.03 07:37
Оценка:
Здравствуйте, serg_p, Вы писали:

ну это смотря для чего тебе хард нужен. наверняка для того, чтобы привязку софта сделать.
... << RSDN@Home 1.0 beta 6a >>
Re[5]: System info
От: Thinker  
Дата: 31.03.03 07:47
Оценка:
Здравствуйте, payglobal, Вы писали:

P>Здравствуйте, serg_p, Вы писали:


P>ну это смотря для чего тебе хард нужен. наверняка для того, чтобы привязку софта сделать.


P>



Нет привязку софта я делать не буду ! я хочу контролшировать непосредственно
конфигурацию тачек в сети и отслеживать любые изменения ! а для этого нужно прочитать
всю системную инфу о жезелке !

Я залез в MSDN нашел некоторые функции типа WIN32Proceccor и прочее но не знаю как их юзать в
CBuilder

Если не тяжело дайте пару примеров.

With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[6]: System info
От: serg_p Украина  
Дата: 31.03.03 08:34
Оценка:
T> я хочу контролшировать непосредственно конфигурацию тачек в сети и отслеживать любые

А какие Windows'ы на тачках стоят?
Re[6]: System info
От: payglobal  
Дата: 31.03.03 09:09
Оценка: 8 (1)
Здравствуйте, Thinker, Вы писали:

сразу извиняюсь — это куски из проекта.
все не публикую ...

будут вопросы — пиши

Это хидер
#define SYSCPUSPEED_REPEAT 10
namespace pay {
    class CSysCPUInfo :  public ISysInfo  {
    public:
        enum enumProcessorManufacturer {
            Unknown = 0, AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta
        };
        enum enumCPUFeatures {
            MMX_FEATURE                            = 0x00000001,
            MMX_PLUS_FEATURE                    = 0x00000002,
            SSE_FEATURE                            = 0x00000004,
            SSE2_FEATURE                        = 0x00000008,
            AMD_3DNOW_FEATURE                = 0x00000010,
            AMD_3DNOW_PLUS_FEATURE        = 0x00000020,
            IA64_FEATURE                            = 0x00000040,
            MP_CAPABLE                            = 0x00000080,
            HYPERTHREAD_FEATURE            = 0x00000100,
            SERIALNUMBER_FEATURE            = 0x00000200,
            APIC_FEATURE                            = 0x00000400,
            SSE_FP_FEATURE                        = 0x00000800,
            SSE_MMX_FEATURE                    = 0x00001000,
            CMOV_FEATURE                        = 0x00002000,
            MTRR_FEATURE                        = 0x00004000,
            L1CACHE_FEATURE                    = 0x00008000,
            L2CACHE_FEATURE                    = 0x00010000,
            L3CACHE_FEATURE                    = 0x00020000,
            ACPI_FEATURE                            = 0x00040000,
            THERMALMONITOR_FEATURE        = 0x00080000,
            TEMPSENSEDIODE_FEATURE        = 0x00100000,
            FREQUENCYID_FEATURE                = 0x00200000,
            VOLTAGEID_FREQUENCY            = 0x00400000
        };
        typedef struct tagCPUPowerManagement {
            bool HasVoltageID;
            bool HasFrequencyID;
            bool HasTempSenseDiode;
        } CPUPowerManagement;
        typedef struct tagCPUExtendedFeatures {
            bool Has3DNow;
            bool Has3DNowPlus;
            bool SupportsMP;
            bool HasMMXPlus;
            bool HasSSEMMX;
            bool SupportsHyperthreading;
            int LogicalProcessorsPerPhysical;
            int APIC_ID;
            CPUPowerManagement PowerManagement;
        } CPUExtendedFeatures;    
        typedef struct tagCPUFeatures {
            bool HasFPU;
            bool HasTSC;
            bool HasMMX;
            bool HasSSE;
            bool HasSSEFP;
            bool HasSSE2;
            bool HasIA64;
            bool HasAPIC;
            bool HasCMOV;
            bool HasMTRR;
            bool HasACPI;
            bool HasSerial;
            bool HasThermal;
            int L1CacheSize;
            int L2CacheSize;
            int L3CacheSize;
            CPUExtendedFeatures ExtendedFeatures;
        } CPUFeatures;
        typedef struct _CPUID {
            int dwProcessorUsage;
            TCHAR  szSerialNumber[30];
        } CPUID, PCPUID;
        typedef struct _CPUINFO {
            DWORD dwNumProcessors;
            DWORD dwMhz;
            DWORD dwPageSize;
            DWORD dwChipManufacturer;
            DWORD dwType;
            DWORD dwFamily;
            DWORD dwModel;
            DWORD dwRevision;
            DWORD dwExtendedFamily;
            DWORD dwExtendedModel;
            DWORD dwCPUFeatures;
            CPUFeatures Features;
            TCHAR  szProcessorArchitecture[MAX_PATH];
            TCHAR  szProcessorName[MAX_PATH];
            TCHAR  szVendorName[MAX_PATH];
            vector<CPUID>   idCPU;
        } CPUINFO, *PCPUINFO;

        void getInfo();
        string getSysInfoName();
        EnumSysInfo getSysInfoNum();
        /**
            получить исчерпывающую информацию о процессоре
        */
        static BOOL getCPUInfo( CPUINFO &);
        /**
            получить информацию о производителе процессора
        */
        static string getProcessorVendor();
        /**
            получить информацию о тактовой частоте на процессоре
        */
        static DWORD getProcessorSpeed();
        /**
            получить уникальный фабричный номер процессора
            Параметры 
                [input] dwProcNum - номер запрашиваемого процессора ( 0 - первый проц )
        */
        static string getProcessorID( DWORD dwProcNum = 0 );
        /**
            получить информацию о загрузке процессора dwProcNum
        */
        static DWORD getProcessorUsage( DWORD dwProcNum = 0 );
        /**
            количество процессоров
        */
        static DWORD getNumProcessors();
        /**
            архитектура процессора
        */
        static string getProcessorArchitecture();
        /**
            
        */
        static string getProcessorLevel();
        /**

        */
        static DWORD getProcessorPageSize();
        /**
            возращает строку с названием фирмы-производителя процессора
            
        */
        static string GetVendorID (enumProcessorManufacturer dwChipManufacturer);
        /**
           проверяет - можно ли получить CPU ID
        */
        static BOOL checkCPUID();
//        static BOOL getCPUID(CPUINFO &cpuinfo);
        void getInfoAsXML(ISysXMLInfo & );
        static DWORD getProcessorType();
        static DWORD getProcessorFamily();
        static DWORD getProcessorModel();
        static DWORD getProcessorStepping();
        static string getProcessorIdentifier();
        static string getProcessorSerialNumber(DWORD dwNum);
        static DWORD getLogicalProcessorsPerPhysical ();
        static DWORD getProcessorCacheXSize (DWORD dwCacheID);
        static BOOL checkCPUSupportFeature(enumCPUFeatures Feature);
        static BOOL getCPUFeatures(DWORD &dwFeature);
        static DWORD getProcessorExtendedFamily();
        static DWORD getProcessorExtendedModel();
        static DWORD getProcessorFeatures();
        static DWORD getProcessorRevision();
        static string getProcessorManufacturer( enumProcessorManufacturer ChipManufacturer);
    private:
        static CPUINFO m_cpuinfo;
//        static CPUFeatures Features;
        static void getProcessorArchitectureAndLevel();
        static BOOL m_bChecked;
        static TCHAR *ssCPUVendors[];
    };
}


а это код

#include <tchar.h>

#include <process.h>
#include <Aclapi.h>
// #include "ntdll.h"
#include "SysOSInfo.h"
#include "SysCPUInfo.h"

#define STORE_TLBCACHE_INFO(x,y)        x = (x < y) ? y : x
#define VENDOR_STRING_LENGTH            (12 + 1)
#define CHIPNAME_STRING_LENGTH            (48 + 1)
#define SERIALNUMBER_STRING_LENGTH    (29 + 1)
#define TLBCACHE_INFO_UNITS                (15)
#define CLASSICAL_CPU_FREQ_LOOP        10000000
#define I16TO32(x, y)                            (((DWORD) x << 16) + y)
#define I32TO64(x, y)                            (((__int64) x << 32) + y)

#define RDTSC_INSTRUCTION                    _asm _emit 0x0f _asm _emit 0x31
#ifdef CPUID_AWARE_COMPILER
    #define CPUID_INSTRUCTION                cpuid
#else
    #define CPUID_INSTRUCTION                _asm _emit 0x0f _asm _emit 0xa2
#endif

typedef LONG    NTSTATUS;

typedef struct _SYSTEM_PROCESSOR_TIMES {//Information Class 8
    LARGE_INTEGER IdleTime;
    LARGE_INTEGER KernelTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER DpcTime;
    LARGE_INTEGER InterruptTime;
    ULONG InterruptCount;
}SYSTEM_PROCESSOR_TIMES,*PSYSTEM_PROCESSOR_TIMES;

typedef    void (*DELAY_FUNC)(unsigned int uiMS);

pay::CSysCPUInfo::CPUINFO pay::CSysCPUInfo::m_cpuinfo; // = {0,0,0,0,0,0,0,0};
BOOL pay::CSysCPUInfo::m_bChecked = FALSE;

TCHAR *pay::CSysCPUInfo::ssCPUVendors[] = {
    "Unknown Manufacturer",
    "Advanced Micro Devices",
    "Intel Corporation",
    "National Semiconductor",
    "United Microelectronics Corp.",
    "Cyrix Corp., VIA Inc.",
    "NexGen Inc., Advanced Micro Devices",
    "IDT\\Centaur, Via Inc.",
    "Rise",
    "Transmeta"
};

int getProcessorSignature() {
    int CPUSignature,APICID;
    // Use assembly to detect CPUID information...
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
                ; we must push/pop the registers <<CPUID>> writes to, as the
                ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                ; these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                ; <<CPUID>> 
                ; eax = 1 
                ;             eax: CPU ID -   bits 31..16 - unused, 
                ;                                  bits 15..12 - type, 
                ;                                  bits 11..8 - family, 
                ;                                  bits 7..4 - model, 
                ;                                  bits 3..0 - mask revision
                ;              ebx:    31..24 - default APIC ID, 
                ;                       23..16 - logical processsor ID, 
                ;                       15..8 - CFLUSH chunk size , 
                ;                       7..0 - brand ID
                ;              edx: CPU feature flags
                mov eax,1
                CPUID_INSTRUCTION
                mov CPUSignature, eax
                mov APICID, ebx
                
#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    } __except (1) {
        // A generic catch-all just to be sure...
        return 0;
    }
    return I16TO32(APICID,CPUSignature);
}
DWORD pay::CSysCPUInfo::getProcessorCacheXSize(DWORD dwCacheID) {
    // Return the chosen cache size.
    if (!m_bChecked)
        m_bChecked = getCPUInfo(m_cpuinfo);

    switch (dwCacheID) {
        case L1CACHE_FEATURE:
            return m_cpuinfo.Features.L1CacheSize;

        case L2CACHE_FEATURE:
            return m_cpuinfo.Features.L2CacheSize;

        case L3CACHE_FEATURE:
            return m_cpuinfo.Features.L3CacheSize;
    }

    // The user did something strange just return and error.
    return -1;
}

BOOL pay::CSysCPUInfo::checkCPUSupportFeature(enumCPUFeatures dwFeature) {
    BOOL bHasFeature = FALSE;
//    DWORD dwFeature = (DWORD)Feature;
    if ( !m_bChecked )
        m_bChecked = getCPUInfo(m_cpuinfo);
    
    // Check for MMX instructions.
    if (((dwFeature & MMX_FEATURE) != 0) && m_cpuinfo.Features.HasMMX) bHasFeature = TRUE;

    // Check for MMX+ instructions.
    if (((dwFeature & MMX_PLUS_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.HasMMXPlus) bHasFeature = TRUE;

    // Check for SSE FP instructions.
    if (((dwFeature & SSE_FEATURE) != 0) && m_cpuinfo.Features.HasSSE) bHasFeature = TRUE;

    // Check for SSE FP instructions.
    if (((dwFeature & SSE_FP_FEATURE) != 0) && m_cpuinfo.Features.HasSSEFP) bHasFeature = TRUE;

    // Check for SSE MMX instructions.
    if (((dwFeature & SSE_MMX_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.HasSSEMMX) bHasFeature = TRUE;

    // Check for SSE2 instructions.
    if (((dwFeature & SSE2_FEATURE) != 0) && m_cpuinfo.Features.HasSSE2) bHasFeature = TRUE;

    // Check for 3DNow! instructions.
    if (((dwFeature & AMD_3DNOW_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.Has3DNow) bHasFeature = TRUE;

    // Check for 3DNow+ instructions.
    if (((dwFeature & AMD_3DNOW_PLUS_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.Has3DNowPlus) bHasFeature = TRUE;

    // Check for IA64 instructions.
    if (((dwFeature & IA64_FEATURE) != 0) && m_cpuinfo.Features.HasIA64) bHasFeature = TRUE;

    // Check for MP capable.
    if (((dwFeature & MP_CAPABLE) != 0) && m_cpuinfo.Features.ExtendedFeatures.SupportsMP) bHasFeature = TRUE;

    // Check for a serial number for the processor.
    if (((dwFeature & SERIALNUMBER_FEATURE) != 0) && m_cpuinfo.Features.HasSerial) bHasFeature = TRUE;

    // Check for a local APIC in the processor.
    if (((dwFeature & APIC_FEATURE) != 0) && m_cpuinfo.Features.HasAPIC) bHasFeature = TRUE;

    // Check for CMOV instructions.
    if (((dwFeature & CMOV_FEATURE) != 0) && m_cpuinfo.Features.HasCMOV) bHasFeature = TRUE;

    // Check for MTRR instructions.
    if (((dwFeature & MTRR_FEATURE) != 0) && m_cpuinfo.Features.HasMTRR) bHasFeature = TRUE;

    // Check for L1 cache size.
    if (((dwFeature & L1CACHE_FEATURE) != 0) && (m_cpuinfo.Features.L1CacheSize != -1)) bHasFeature = TRUE;

    // Check for L2 cache size.
    if (((dwFeature & L2CACHE_FEATURE) != 0) && (m_cpuinfo.Features.L2CacheSize != -1)) bHasFeature = TRUE;

    // Check for L3 cache size.
    if (((dwFeature & L3CACHE_FEATURE) != 0) && (m_cpuinfo.Features.L3CacheSize != -1)) bHasFeature = TRUE;

    // Check for ACPI capability.
    if (((dwFeature & ACPI_FEATURE) != 0) && m_cpuinfo.Features.HasACPI) bHasFeature = TRUE;

    // Check for thermal monitor support.
    if (((dwFeature & THERMALMONITOR_FEATURE) != 0) && m_cpuinfo.Features.HasThermal) bHasFeature = TRUE;

    // Check for temperature sensing diode support.
    if (((dwFeature & TEMPSENSEDIODE_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode) bHasFeature = TRUE;

    // Check for frequency ID support.
    if (((dwFeature & FREQUENCYID_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasFrequencyID) bHasFeature = TRUE;

    // Check for voltage ID support.
    if (((dwFeature & VOLTAGEID_FREQUENCY) != 0) && m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasVoltageID) bHasFeature = TRUE;

    return bHasFeature;
}
bool RetrieveCPUExtendedLevelSupport (int CPULevelToCheck,  pay::CSysCPUInfo::CPUINFO &cpu ) {
    int MaxCPUExtendedLevel = 0;

    // The extended CPUID is supported by various vendors starting with the following CPU models: 
    //
    //        Manufacturer & Chip Name            |        Family         Model        Revision
    //
    //        AMD K6, K6-2                            |           5           6            x        
    //        Cyrix GXm, Cyrix III "Joshua"        |           5           4            x
    //        IDT C6-2                                |           5           8            x
    //        VIA Cyrix III                            |           6           5            x
    //        Transmeta Crusoe                    |           5           x            x
    //        Intel Pentium 4                        |           f           x            x
    //

    // We check to see if a supported processor is present...
    if (cpu.dwChipManufacturer == pay::CSysCPUInfo::AMD) {
        if (cpu.dwFamily < 5) return false;
        if ((cpu.dwFamily == 5) && (cpu.dwModel < 6)) return false;
    } 
    else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Cyrix) {
        if (cpu.dwFamily < 5) return false;
        if ((cpu.dwFamily == 5) && (cpu.dwModel < 4)) return false;
        if ((cpu.dwFamily == 6) && (cpu.dwModel < 5)) return false;
    } 
    else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::IDT) {
        if (cpu.dwFamily < 5) return false;
        if ((cpu.dwFamily == 5) && (cpu.dwModel < 8)) return false;
    } 
    else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Transmeta) {
        if (cpu.dwFamily < 5) return false;
    } 
    else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Intel) {
        if (cpu.dwFamily < 0xf) return false;
    }

    // Use assembly to detect CPUID information...
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
                ; we must push/pop the registers <<CPUID>> writes to, as the
                ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                ; these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                ; <<CPUID>> 
                ; eax = 0x80000000 --> eax: maximum supported extended level
                mov eax,0x80000000
                CPUID_INSTRUCTION
                mov MaxCPUExtendedLevel, eax

#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        return false;
    }

    // Now we have to check the level wanted vs level returned...
    int nLevelWanted = (CPULevelToCheck & 0x7FFFFFFF);
    int nLevelReturn = (MaxCPUExtendedLevel & 0x7FFFFFFF);

    // Check to see if the level provided is supported...
    if (nLevelWanted > nLevelReturn) return false;

    return true;
}
bool RetrieveExtendedCPUFeatures( pay::CSysCPUInfo::CPUINFO &cpu ) {
    int CPUExtendedFeatures = 0;

    // Check that we are not using an Intel processor as it does not support this.
    if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Intel) return false;

    // Check to see if what we are about to do is supported...
    if (!RetrieveCPUExtendedLevelSupport (0x80000001,cpu)) return false;

    // Use assembly to detect CPUID information...
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
            ; we must push/pop the registers <<CPUID>> writes to, as the
                ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                ; these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                ; <<CPUID>> 
                ; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
                ;                       ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
                ;                       edx: CPU feature flags
                mov eax,0x80000001
                CPUID_INSTRUCTION
                mov CPUExtendedFeatures, edx

#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        return false;
    }

    // Retrieve the extended features of CPU present.
    cpu.Features.ExtendedFeatures.Has3DNow =        ((CPUExtendedFeatures & 0x80000000) != 0);    // 3DNow Present --> Bit 31.
    cpu.Features.ExtendedFeatures.Has3DNowPlus =    ((CPUExtendedFeatures & 0x40000000) != 0);    // 3DNow+ Present -- > Bit 30.
    cpu.Features.ExtendedFeatures.HasSSEMMX =    ((CPUExtendedFeatures & 0x00400000) != 0);    // SSE MMX Present --> Bit 22.
    cpu.Features.ExtendedFeatures.SupportsMP =        ((CPUExtendedFeatures & 0x00080000) != 0);    // MP Capable -- > Bit 19.

    // Retrieve AMD specific extended features.
    if (cpu.dwChipManufacturer == pay::CSysCPUInfo::AMD) {
        cpu.Features.ExtendedFeatures.HasMMXPlus =    ((CPUExtendedFeatures &    0x00400000) != 0);    // AMD specific: MMX-SSE --> Bit 22
    }

    // Retrieve Cyrix specific extended features.
    if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Cyrix) {
        cpu.Features.ExtendedFeatures.HasMMXPlus =    ((CPUExtendedFeatures &    0x01000000) != 0);    // Cyrix specific: Extended MMX --> Bit 24
    }

    return true;
}
bool RetrieveExtendedCPUIdentity (pay::CSysCPUInfo::CPUINFO &cpu) {
    int ProcessorNameStartPos = 0;
    int CPUExtendedIdentity[12];

    // Check to see if what we are about to do is supported...
    if (!RetrieveCPUExtendedLevelSupport (0x80000002,cpu)) return false;
    if (!RetrieveCPUExtendedLevelSupport (0x80000003,cpu)) return false;
    if (!RetrieveCPUExtendedLevelSupport (0x80000004,cpu)) return false;

    // Use assembly to detect CPUID information...
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
            ; we must push/pop the registers <<CPUID>> writes to, as the
                ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                ; these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                ; <<CPUID>> 
                ; eax = 0x80000002 --> eax, ebx, ecx, edx: get processor name string (part 1)
                mov eax,0x80000002
                CPUID_INSTRUCTION
                mov CPUExtendedIdentity[0 * TYPE int], eax
                mov CPUExtendedIdentity[1 * TYPE int], ebx
                mov CPUExtendedIdentity[2 * TYPE int], ecx
                mov CPUExtendedIdentity[3 * TYPE int], edx

                ; <<CPUID>> 
                ; eax = 0x80000003 --> eax, ebx, ecx, edx: get processor name string (part 2)
                mov eax,0x80000003
                CPUID_INSTRUCTION
                mov CPUExtendedIdentity[4 * TYPE int], eax
                mov CPUExtendedIdentity[5 * TYPE int], ebx
                mov CPUExtendedIdentity[6 * TYPE int], ecx
                mov CPUExtendedIdentity[7 * TYPE int], edx

                ; <<CPUID>> 
                ; eax = 0x80000004 --> eax, ebx, ecx, edx: get processor name string (part 3)
                mov eax,0x80000004
                CPUID_INSTRUCTION
                mov CPUExtendedIdentity[8 * TYPE int], eax
                mov CPUExtendedIdentity[9 * TYPE int], ebx
                mov CPUExtendedIdentity[10 * TYPE int], ecx
                mov CPUExtendedIdentity[11 * TYPE int], edx

#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        return false;
    }

    // Process the returned information.
    memcpy (cpu.szProcessorName, &(CPUExtendedIdentity[0]), sizeof (int));
    memcpy (&(cpu.szProcessorName[4]), &(CPUExtendedIdentity[1]), sizeof (int));
    memcpy (&(cpu.szProcessorName[8]), &(CPUExtendedIdentity[2]), sizeof (int));
    memcpy (&(cpu.szProcessorName[12]), &(CPUExtendedIdentity[3]), sizeof (int));
    memcpy (&(cpu.szProcessorName[16]), &(CPUExtendedIdentity[4]), sizeof (int));
    memcpy (&(cpu.szProcessorName[20]), &(CPUExtendedIdentity[5]), sizeof (int));
    memcpy (&(cpu.szProcessorName[24]), &(CPUExtendedIdentity[6]), sizeof (int));
    memcpy (&(cpu.szProcessorName[28]), &(CPUExtendedIdentity[7]), sizeof (int));
    memcpy (&(cpu.szProcessorName[32]), &(CPUExtendedIdentity[8]), sizeof (int));
    memcpy (&(cpu.szProcessorName[36]), &(CPUExtendedIdentity[9]), sizeof (int));
    memcpy (&(cpu.szProcessorName[40]), &(CPUExtendedIdentity[10]), sizeof (int));
    memcpy (&(cpu.szProcessorName[44]), &(CPUExtendedIdentity[11]), sizeof (int));
    cpu.szProcessorName[48] = '\0';

    // Because some manufacturers (<cough>Intel</cough>) have leading white space - we have to post-process the name.
    if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Intel) {
        for (int nCounter = 0; nCounter < CHIPNAME_STRING_LENGTH; nCounter ++) {
            // There will either be NULL (\0) or spaces ( ) as the leading characters.
            if ((cpu.szProcessorName[nCounter] != '\0') && (cpu.szProcessorName[nCounter] != ' ')) {
                // We have found the starting position of the name.
                ProcessorNameStartPos = nCounter;

                // Terminate the loop.
                break;
            }
        }

        // Check to see if there is any white space at the start.
        if (ProcessorNameStartPos == 0) return true;

        // Now move the name forward so that there is no white space.
        memmove (cpu.szProcessorName, &(cpu.szProcessorName[ProcessorNameStartPos]), (CHIPNAME_STRING_LENGTH - ProcessorNameStartPos));
    }

    return true;
}
bool RetrieveCPUCacheDetails(pay::CSysCPUInfo::CPUINFO &cpu) {
    bool bRes = true;
    int L1Cache[4] = { 0, 0, 0, 0 };
    int L2Cache[4] = { 0, 0, 0, 0 };
    // Check to see if what we are about to do is supported...
    if (RetrieveCPUExtendedLevelSupport (0x80000005,cpu)) {
        // Use assembly to retrieve the L1 cache information ...
        __try {
            _asm {
#ifdef CPUID_AWARE_COMPILER
                ; we must push/pop the registers <<CPUID>> writes to, as the
                    ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                    ; these registers to change.
                    push eax
                    push ebx
                    push ecx
                    push edx
#endif
                    ; <<CPUID>>
                    ; eax = 0x80000005 --> eax: L1 cache information - Part 1 of 4.
                    ;                       ebx: L1 cache information - Part 2 of 4.
                    ;                       edx: L1 cache information - Part 3 of 4.
                    ;                        ecx: L1 cache information - Part 4 of 4.
                    mov eax, 0x80000005
                    CPUID_INSTRUCTION
                    mov L1Cache[0 * TYPE int], eax
                    mov L1Cache[1 * TYPE int], ebx
                    mov L1Cache[2 * TYPE int], ecx
                    mov L1Cache[3 * TYPE int], edx

#ifdef CPUID_AWARE_COMPILER
                    pop edx
                    pop ecx
                    pop ebx
                    pop eax
#endif
            }
        }

        // A generic catch-all just to be sure...
        __except (1) {
            return false;
        }

        // Save the L1 data cache size (in KB) from ecx: bits 31..24 as well as data cache size from edx: bits 31..24.
        cpu.Features.L1CacheSize = ((L1Cache[2] & 0xFF000000) >> 24);
        cpu.Features.L1CacheSize += ((L1Cache[3] & 0xFF000000) >> 24);
    } else {
        // Store -1 to indicate the cache could not be queried.
        cpu.Features.L1CacheSize = -1;
    }

    // Check to see if what we are about to do is supported...
    if (RetrieveCPUExtendedLevelSupport (0x80000006,cpu)) {
        // Use assembly to retrieve the L2 cache information ...
        __try {
            _asm {
#ifdef CPUID_AWARE_COMPILER
                ; we must push/pop the registers <<CPUID>> writes to, as the
                    ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                    ; these registers to change.
                    push eax
                    push ebx
                    push ecx
                    push edx
#endif
                    ; <<CPUID>>
                    ; eax = 0x80000006 --> eax: L2 cache information - Part 1 of 4.
                    ;                       ebx: L2 cache information - Part 2 of 4.
                    ;                       edx: L2 cache information - Part 3 of 4.
                    ;                        ecx: L2 cache information - Part 4 of 4.
                    mov eax, 0x80000006
                    CPUID_INSTRUCTION
                    mov L2Cache[0 * TYPE int], eax
                    mov L2Cache[1 * TYPE int], ebx
                    mov L2Cache[2 * TYPE int], ecx
                    mov L2Cache[3 * TYPE int], edx

#ifdef CPUID_AWARE_COMPILER
                    pop edx
                    pop ecx
                    pop ebx
                    pop eax
#endif            
            }
        }

        // A generic catch-all just to be sure...
        __except (1) {
            return false;
        }

        // Save the L2 unified cache size (in KB) from ecx: bits 31..16.
        cpu.Features.L2CacheSize = ((L2Cache[2] & 0xFFFF0000) >> 16);
    } else {
        // Store -1 to indicate the cache could not be queried.
        cpu.Features.L2CacheSize = -1;
    }

    // Define L3 as being not present as we cannot test for it.
    cpu.Features.L3CacheSize = -1;
    // Return failure if we cannot detect either cache with this method.
    bRes = ((cpu.Features.L1CacheSize == -1) && (cpu.Features.L2CacheSize == -1)) ? false : true;
    if (!bRes) {
        int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1, L2Unified = -1, L3Unified = -1;
        int TLBCacheData[4] = { 0, 0, 0, 0 };
        int TLBPassCounter = 0;
        int TLBCacheUnit = 0;

        do {
            // Use assembly to retrieve the L2 cache information ...
            __try {
                _asm {
    #ifdef CPUID_AWARE_COMPILER
                    ; we must push/pop the registers <<CPUID>> writes to, as the
                        ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                        ; these registers to change.
                        push eax
                        push ebx
                        push ecx
                        push edx
    #endif
                        ; <<CPUID>>
                        ; eax = 2 --> eax: TLB and cache information - Part 1 of 4.
                        ;              ebx: TLB and cache information - Part 2 of 4.
                        ;              ecx: TLB and cache information - Part 3 of 4.
                        ;              edx: TLB and cache information - Part 4 of 4.
                        mov eax, 2
                        CPUID_INSTRUCTION
                        mov TLBCacheData[0 * TYPE int], eax
                        mov TLBCacheData[1 * TYPE int], ebx
                        mov TLBCacheData[2 * TYPE int], ecx
                        mov TLBCacheData[3 * TYPE int], edx

    #ifdef CPUID_AWARE_COMPILER
                        pop edx
                        pop ecx
                        pop ebx
                        pop eax
    #endif
                }
            }

            // A generic catch-all just to be sure...
            __except (1) {
                return false;
            }

            int bob = ((TLBCacheData[0] & 0x00FF0000) >> 16);

            // Process the returned TLB and cache information.
            for (int nCounter = 0; nCounter < TLBCACHE_INFO_UNITS; nCounter ++) {

                // First of all - decide which unit we are dealing with.
                switch (nCounter) {

                    // eax: bits 8..15 : bits 16..23 : bits 24..31
                    case 0: TLBCacheUnit = ((TLBCacheData[0] & 0x0000FF00) >> 8); break;
                    case 1: TLBCacheUnit = ((TLBCacheData[0] & 0x00FF0000) >> 16); break;
                    case 2: TLBCacheUnit = ((TLBCacheData[0] & 0xFF000000) >> 24); break;

                        // ebx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
                    case 3: TLBCacheUnit = ((TLBCacheData[1] & 0x000000FF) >> 0); break;
                    case 4: TLBCacheUnit = ((TLBCacheData[1] & 0x0000FF00) >> 8); break;
                    case 5: TLBCacheUnit = ((TLBCacheData[1] & 0x00FF0000) >> 16); break;
                    case 6: TLBCacheUnit = ((TLBCacheData[1] & 0xFF000000) >> 24); break;

                        // ecx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
                    case 7: TLBCacheUnit = ((TLBCacheData[2] & 0x000000FF) >> 0); break;
                    case 8: TLBCacheUnit = ((TLBCacheData[2] & 0x0000FF00) >> 8); break;
                    case 9: TLBCacheUnit = ((TLBCacheData[2] & 0x00FF0000) >> 16); break;
                    case 10: TLBCacheUnit = ((TLBCacheData[2] & 0xFF000000) >> 24); break;

                        // edx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
                    case 11: TLBCacheUnit = ((TLBCacheData[3] & 0x000000FF) >> 0); break;
                    case 12: TLBCacheUnit = ((TLBCacheData[3] & 0x0000FF00) >> 8); break;
                    case 13: TLBCacheUnit = ((TLBCacheData[3] & 0x00FF0000) >> 16); break;
                    case 14: TLBCacheUnit = ((TLBCacheData[3] & 0xFF000000) >> 24); break;

                        // Default case - an error has occured.
                    default: return false;
                }

                // Now process the resulting unit to see what it means....
                switch (TLBCacheUnit) {
                    case 0x00: break;
                    case 0x01: STORE_TLBCACHE_INFO (TLBCode, 4); break;
                    case 0x02: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
                    case 0x03: STORE_TLBCACHE_INFO (TLBData, 4); break;
                    case 0x04: STORE_TLBCACHE_INFO (TLBData, 4096); break;
                    case 0x06: STORE_TLBCACHE_INFO (L1Code, 8); break;
                    case 0x08: STORE_TLBCACHE_INFO (L1Code, 16); break;
                    case 0x0a: STORE_TLBCACHE_INFO (L1Data, 8); break;
                    case 0x0c: STORE_TLBCACHE_INFO (L1Data, 16); break;
                    case 0x10: STORE_TLBCACHE_INFO (L1Data, 16); break;            // <-- FIXME: IA-64 Only
                    case 0x15: STORE_TLBCACHE_INFO (L1Code, 16); break;            // <-- FIXME: IA-64 Only
                    case 0x1a: STORE_TLBCACHE_INFO (L2Unified, 96); break;        // <-- FIXME: IA-64 Only
                    case 0x22: STORE_TLBCACHE_INFO (L3Unified, 512); break;
                    case 0x23: STORE_TLBCACHE_INFO (L3Unified, 1024); break;
                    case 0x25: STORE_TLBCACHE_INFO (L3Unified, 2048); break;
                    case 0x29: STORE_TLBCACHE_INFO (L3Unified, 4096); break;
                    case 0x39: STORE_TLBCACHE_INFO (L2Unified, 128); break;
                    case 0x3c: STORE_TLBCACHE_INFO (L2Unified, 256); break;
                    case 0x40: STORE_TLBCACHE_INFO (L2Unified, 0); break;        // <-- FIXME: No integrated L2 cache (P6 core) or L3 cache (P4 core).
                    case 0x41: STORE_TLBCACHE_INFO (L2Unified, 128); break;
                    case 0x42: STORE_TLBCACHE_INFO (L2Unified, 256); break;
                    case 0x43: STORE_TLBCACHE_INFO (L2Unified, 512); break;
                    case 0x44: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
                    case 0x45: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
                    case 0x50: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
                    case 0x51: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
                    case 0x52: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
                    case 0x5b: STORE_TLBCACHE_INFO (TLBData, 4096); break;
                    case 0x5c: STORE_TLBCACHE_INFO (TLBData, 4096); break;
                    case 0x5d: STORE_TLBCACHE_INFO (TLBData, 4096); break;
                    case 0x66: STORE_TLBCACHE_INFO (L1Data, 8); break;
                    case 0x67: STORE_TLBCACHE_INFO (L1Data, 16); break;
                    case 0x68: STORE_TLBCACHE_INFO (L1Data, 32); break;
                    case 0x70: STORE_TLBCACHE_INFO (L1Trace, 12); break;
                    case 0x71: STORE_TLBCACHE_INFO (L1Trace, 16); break;
                    case 0x72: STORE_TLBCACHE_INFO (L1Trace, 32); break;
                    case 0x77: STORE_TLBCACHE_INFO (L1Code, 16); break;            // <-- FIXME: IA-64 Only
                    case 0x79: STORE_TLBCACHE_INFO (L2Unified, 128); break;
                    case 0x7a: STORE_TLBCACHE_INFO (L2Unified, 256); break;
                    case 0x7b: STORE_TLBCACHE_INFO (L2Unified, 512); break;
                    case 0x7c: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
                    case 0x7e: STORE_TLBCACHE_INFO (L2Unified, 256); break;
                    case 0x81: STORE_TLBCACHE_INFO (L2Unified, 128); break;
                    case 0x82: STORE_TLBCACHE_INFO (L2Unified, 256); break;
                    case 0x83: STORE_TLBCACHE_INFO (L2Unified, 512); break;
                    case 0x84: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
                    case 0x85: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
                    case 0x88: STORE_TLBCACHE_INFO (L3Unified, 2048); break;    // <-- FIXME: IA-64 Only
                    case 0x89: STORE_TLBCACHE_INFO (L3Unified, 4096); break;    // <-- FIXME: IA-64 Only
                    case 0x8a: STORE_TLBCACHE_INFO (L3Unified, 8192); break;    // <-- FIXME: IA-64 Only
                    case 0x8d: STORE_TLBCACHE_INFO (L3Unified, 3096); break;    // <-- FIXME: IA-64 Only
                    case 0x90: STORE_TLBCACHE_INFO (TLBCode, 262144); break;    // <-- FIXME: IA-64 Only
                    case 0x96: STORE_TLBCACHE_INFO (TLBCode, 262144); break;    // <-- FIXME: IA-64 Only
                    case 0x9b: STORE_TLBCACHE_INFO (TLBCode, 262144); break;    // <-- FIXME: IA-64 Only

                        // Default case - an error has occured.
                    default: return false;
                }
            }

            // Increment the TLB pass counter.
            TLBPassCounter ++;

        } while ((TLBCacheData[0] & 0x000000FF) > TLBPassCounter);

        // Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
        if ((L1Code == -1) && (L1Data == -1) && (L1Trace == -1)) cpu.Features.L1CacheSize = -1;
        else if ((L1Code == -1) && (L1Data == -1) && (L1Trace != -1)) cpu.Features.L1CacheSize = L1Trace;
        else if ((L1Code != -1) && (L1Data == -1)) cpu.Features.L1CacheSize = L1Code;
        else if ((L1Code == -1) && (L1Data != -1)) cpu.Features.L1CacheSize = L1Data;
        else if ((L1Code != -1) && (L1Data != -1)) cpu.Features.L1CacheSize = L1Code + L1Data;
        else cpu.Features.L1CacheSize = -1;

        // Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
        if (L2Unified == -1) cpu.Features.L2CacheSize = -1;
        else cpu.Features.L2CacheSize = L2Unified;

        // Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
        if (L3Unified == -1) cpu.Features.L3CacheSize = -1;
        else cpu.Features.L3CacheSize = L3Unified;
    }
    return true;
}
bool getCPUPowerManagement( pay::CSysCPUInfo::CPUINFO &cpu ) {    
    int CPUPowerManagement = 0;

    // Check to see if what we are about to do is supported...
    if (!RetrieveCPUExtendedLevelSupport (0x80000007, cpu)) {
        cpu.Features.ExtendedFeatures.PowerManagement.HasFrequencyID = false;
        cpu.Features.ExtendedFeatures.PowerManagement.HasVoltageID = false;
        cpu.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = false;
        return false;
    }

    // Use assembly to detect CPUID information...
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
            ; we must push/pop the registers <<CPUID>> writes to, as the
                ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                ; these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                ; <<CPUID>> 
                ; eax = 0x80000007 --> edx: get processor power management
                mov eax,0x80000007
                CPUID_INSTRUCTION
                mov CPUPowerManagement, edx

#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        return false;
    }

    // Check for the power management capabilities of the CPU.
    cpu.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode =    ((CPUPowerManagement & 0x00000001) != 0);
    cpu.Features.ExtendedFeatures.PowerManagement.HasFrequencyID       =    ((CPUPowerManagement & 0x00000002) != 0);
    cpu.Features.ExtendedFeatures.PowerManagement.HasVoltageID           =    ((CPUPowerManagement & 0x00000004) != 0);

    return true;
}
DWORD pay::CSysCPUInfo::getLogicalProcessorsPerPhysical () {
    // Return the logical processors per physical.
    if ( !m_bChecked )
        m_bChecked = getCPUInfo(m_cpuinfo);
    return m_cpuinfo.Features.ExtendedFeatures.LogicalProcessorsPerPhysical;
}
DWORD pay::CSysCPUInfo::getProcessorFeatures() {
    int CPUFeatures = 0;
    int CPUAdvanced = 0;
    DWORD dwFeature = 0;

    // Use assembly to detect CPUID information...
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
                // we must push/pop the registers <<CPUID>> writes to, as the
                // optimiser doesn't know about <<CPUID>>, and so doesn't expect
                // these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                // <<CPUID>> 
                // eax = 1 --> eax: CPU ID -  bits 31..16 - unused, 
                //                                      bits 15..12 - type, 
                //                                      bits 11..8 - family, 
                //                                      bits 7..4 - model, 
                //                                      bits 3..0 - mask revision
                //                    ebx: 31..24 - default APIC ID, 
                //                          23..16 - logical processsor ID, 
                //                          15..8 - CFLUSH chunk size 
                //                          7..0 - brand ID
                //              edx: CPU feature flags
                mov eax,1
                CPUID_INSTRUCTION
                mov CPUAdvanced, ebx
                mov CPUFeatures, edx

#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    } __except (1) {
        // A generic catch-all just to be sure...
        return dwFeature;
    }

    dwFeature = I16TO32(CPUAdvanced,CPUFeatures);
    return dwFeature;
}
DWORD pay::CSysCPUInfo::getProcessorStepping() {
    return getProcessorRevision();
}
DWORD pay::CSysCPUInfo::getProcessorExtendedFamily() {
    if ( m_bChecked )
        return m_cpuinfo.dwExtendedFamily;

    int CPUSignature = getProcessorSignature();
    return ((CPUSignature & 0x0FF00000) >> 20);
}
DWORD pay::CSysCPUInfo::getProcessorExtendedModel() {
    if ( m_bChecked )
        return m_cpuinfo.dwExtendedModel;

    int CPUSignature = getProcessorSignature();
    return ((CPUSignature & 0x000F0000) >> 16);
}
DWORD pay::CSysCPUInfo::getProcessorRevision() {
    if ( m_bChecked )
        return m_cpuinfo.dwRevision;

    int CPUSignature = getProcessorSignature();
    return ((CPUSignature & 0x0000000F) >> 0);
}
DWORD pay::CSysCPUInfo::getProcessorType() {
    if ( m_bChecked )
        return m_cpuinfo.dwType;

    int CPUSignature = getProcessorSignature();
    return ((CPUSignature & 0x0000F000) >> 12);    // Bits 15..12 Used
}
DWORD pay::CSysCPUInfo::getProcessorFamily() {
    // Return the family of the CPU present.
    if ( m_bChecked )
        return m_cpuinfo.dwFamily;

    int CPUSignature = getProcessorSignature();
    return ((CPUSignature & 0x00000F00) >> 8);        // Bits 11..8 Used
}
DWORD pay::CSysCPUInfo::getProcessorModel() {
    // Return the model of CPU present.
    if ( m_bChecked )
        return m_cpuinfo.dwModel;

    int CPUSignature = getProcessorSignature();
    return ((CPUSignature & 0x000000F0) >> 4);        // Bits 7..4 Used
}
unsigned __stdcall _getProcessorSerialNumber(void *ipSerialNumber) {
    // Use assembly to detect CPUID information...
    int SerialNumber[3];
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
                ; we must push/pop the registers <<CPUID>> writes to, as the
                ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
                ; these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                ; <<CPUID>>
                ; eax = 3 -->  ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!?
                ;                    ecx: middle 32 bits are the processor signature bits
                ;                    edx: bottom 32 bits are the processor signature bits
                mov eax, 3
                CPUID_INSTRUCTION
                mov SerialNumber[0 * TYPE int], ebx
                mov SerialNumber[1 * TYPE int], ecx
                mov SerialNumber[2 * TYPE int], edx

#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    } __except (1) {
        // A generic catch-all just to be sure...
        SerialNumber[0] = 0;
        SerialNumber[1] = 0;
        SerialNumber[2] = 0;
    }
    memcpy(ipSerialNumber,SerialNumber,sizeof(SerialNumber));
    return 0;
}
string pay::CSysCPUInfo::getProcessorSerialNumber(DWORD dwNum) {
    string sRes;

    if ( m_bChecked ) {
        if (m_cpuinfo.Features.HasSerial) 
            sRes = m_cpuinfo.idCPU[dwNum].szSerialNumber;
    } else {
        DWORD dwCPUFeatures = getProcessorFeatures();
        // Retrieve the features of CPU present.
        BOOL HasSerial =    ((dwCPUFeatures & 0x00040000) != 0);        // Serial Present --> Bit 18
        if ( HasSerial ) {

            // Check to see if the processor supports the processor serial number.
            int SerialNumber[3];

            HANDLE hThread;
            // Create the thread.
            hThread = (HANDLE)::_beginthreadex( NULL, 0, &_getProcessorSerialNumber, NULL, CREATE_SUSPENDED, (unsigned *)SerialNumber );
            // Wait until second thread has terminated. If you comment out the line  below, Counter will not be correct because the thread has not
            // terminated, and Counter most likely has not been incremented to  1000000 yet.
            BOOL isNT;
            isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
            DWORD dwThreadAffinityMask = 1;
            if ( isNT )
                dwThreadAffinityMask <<= dwNum;
            if ( !::SetThreadAffinityMask(hThread,dwThreadAffinityMask) ) {
                ::ResumeThread(hThread);
                ::WaitForSingleObject( hThread, INFINITE );
            }
            // Destroy the thread object.
            CloseHandle( hThread );

            if ( ( SerialNumber[0] != 0 ) ||  ( SerialNumber[1] != 0 ) || ( SerialNumber[2] != 0 ) ) {
                TCHAR  szRes[30];
                // Process the returned information.
                sprintf (szRes, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x",
                    ((SerialNumber[0] & 0xff000000) >> 24),
                    ((SerialNumber[0] & 0x00ff0000) >> 16),
                    ((SerialNumber[0] & 0x0000ff00) >> 8),
                    ((SerialNumber[0] & 0x000000ff) >> 0),
                    ((SerialNumber[1] & 0xff000000) >> 24),
                    ((SerialNumber[1] & 0x00ff0000) >> 16),
                    ((SerialNumber[1] & 0x0000ff00) >> 8),
                    ((SerialNumber[1] & 0x000000ff) >> 0),
                    ((SerialNumber[2] & 0xff000000) >> 24),
                    ((SerialNumber[2] & 0x00ff0000) >> 16),
                    ((SerialNumber[2] & 0x0000ff00) >> 8),
                    ((SerialNumber[2] & 0x000000ff) >> 0));
                
                sRes = szRes;
            }
        }
    }
    return sRes;
}
_int64 __cdecl getCyclesDifference (DELAY_FUNC DelayFunction, unsigned int uiParameter) {
    unsigned int edx1, eax1;
    unsigned int edx2, eax2;

    // Calculate the frequency of the CPU instructions.
    __try {
        _asm {
                push uiParameter        ; push parameter param
                mov ebx, DelayFunction    ; store func in ebx

                RDTSC_INSTRUCTION

                mov esi, eax            ; esi = eax
                mov edi, edx            ; edi = edx

                call ebx                    ; call the delay functions

                RDTSC_INSTRUCTION

                pop ebx

                mov edx2, edx            ; edx2 = edx
                mov eax2, eax            ; eax2 = eax

                mov edx1, edi            ; edx2 = edi
                mov eax1, esi            ; eax2 = esi
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        return -1;
    }

    return (I32TO64 (edx2, eax2) - I32TO64 (edx1, eax1));
}
void DelayNoOverhead (unsigned int uiMS)
{
    LARGE_INTEGER Frequency, StartCounter, EndCounter;
    __int64 x;

    // Get the frequency of the high performance counter.
    if (!QueryPerformanceFrequency (&Frequency)) return;
    x = Frequency.QuadPart / 1000 * uiMS;

    // Get the starting position of the counter.
    ::QueryPerformanceCounter (&StartCounter);

    do {
        // Get the ending position of the counter.    
        ::QueryPerformanceCounter (&EndCounter);
    } while (EndCounter.QuadPart - StartCounter.QuadPart < x);
}
void DelayOverhead (unsigned int uiMS) {
    LARGE_INTEGER Frequency, StartCounter, EndCounter;
    __int64 x;

    // Get the frequency of the high performance counter.
    if (!QueryPerformanceFrequency (&Frequency)) return;
    x = Frequency.QuadPart / 1000 * uiMS;

    // Get the starting position of the counter.
    ::QueryPerformanceCounter (&StartCounter);

    do {
        // Get the ending position of the counter.    
        QueryPerformanceCounter (&EndCounter);
    } while (EndCounter.QuadPart - StartCounter.QuadPart == x);
}
BOOL pay::CSysCPUInfo::checkCPUID () {
    int CPUIDPresent = 0;

#ifdef _WIN32 

    // Use SEH to determine CPUID presence
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
            ; we must push/pop the registers <<CPUID>> writes to, as the
            ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
            ; these registers to change.
            push eax
            push ebx
            push ecx
            push edx
#endif
            ; <<CPUID>> 
            mov eax, 0
            CPUID_INSTRUCTION

#ifdef CPUID_AWARE_COMPILER
            pop edx
            pop ecx
            pop ebx
            pop eax
#endif
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        // Stop the class from trying to use CPUID again!
        CPUIDPresent = FALSE;
        return FALSE;
    }
#else
    // The "right" way, which doesn't work under certain Windows versions
    __try {
        _asm {
            pushfd                                ; save EFLAGS to stack.
            pop     eax                          ; store EFLAGS in eax.
            mov    edx, eax                    ; save in ebx for testing later.
            xor     eax, 0200000h            ; switch bit 21.
            push    eax                          ; copy "changed" value to stack.
            popfd                                 ; save "changed" eax to EFLAGS.
            pushfd
            pop     eax
            xor     eax, edx                    ; See if bit changeable.
            jnz     short cpuid_present    ; if so, mark 
            mov     eax, -1                    ; CPUID not present - disable its usage
            jmp     no_features

cpuid_present:
            mov        eax, 0                ; CPUID capable CPU - enable its usage.

no_features:
            mov     CPUIDPresent, eax    ; Save the value in eax to a variable.
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        // Stop the class from trying to use CPUID again!
        CPUIDPresent = FALSE;
        return FALSE;
    }

#endif

    // Return true to indicate support or false to indicate lack.
    return (CPUIDPresent == 0) ? TRUE : FALSE;
}
DWORD pay::CSysCPUInfo::getProcessorSpeed() {
    if (m_bChecked)     
        return m_cpuinfo.dwMhz;
    HKEY hKey;
    // Get the processor speed info.
    DWORD data = 0;
    BOOL isNT;
    isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );

    if ( isNT ) {
        if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) ) {
            DWORD dataSize = sizeof(DWORD);
            ::RegQueryValueEx (hKey, _T("~MHz"), NULL, NULL,(LPBYTE)&data, &dataSize);
            // Make sure to close the reg key
            RegCloseKey (hKey);
        }
    } else {
        unsigned int uiRepetitions = SYSCPUSPEED_REPEAT;
        unsigned int uiMSecPerRepetition = 50;
        __int64    i64Total = 0, i64Overhead = 0;

        for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) {
            i64Total += getCyclesDifference (DelayNoOverhead, uiMSecPerRepetition);
            i64Overhead += getCyclesDifference (DelayOverhead, uiMSecPerRepetition);
        }

        // Calculate the MHz speed.
        i64Total -= i64Overhead;
        i64Total /= uiRepetitions;
        i64Total /= uiMSecPerRepetition;
        i64Total /= 1000;

        // Save the CPU speed.
        data = (DWORD) i64Total;
    }

    DWORD NF[] = {0, 20, 33, 50, 60, 66, 80, 90, 100};
    DWORD Freq, RF, Hi, Lo;
    RF = 0;
    DWORD dwData;
    Freq = data % 100;
    for (int i = 0; i < 8; i++ ) {
        if ( Freq < NF[i] ) {
        Hi = i;
        Lo = i-1;
        if ( ( NF[Hi] - Freq ) > ( Freq - NF[Lo] ) )
            RF = NF[Lo]-Freq;
        else
            RF = NF[Hi]-Freq;
        break;
        }
    }
    dwData = data+RF;

    return data;
}
DWORD pay::CSysCPUInfo::getNumProcessors() {
    SYSTEM_INFO siSysInfo;
    // Get the hardware information
    // Copy the hardware information to the SYSTEM_INFO structure. 
    if ( !m_bChecked ) {
        ::GetSystemInfo(&siSysInfo);
        return siSysInfo.dwNumberOfProcessors;
    }
    return m_cpuinfo.dwNumProcessors;
}
DWORD pay::CSysCPUInfo::getProcessorPageSize() {
    if ( !m_bChecked ) {
        SYSTEM_INFO siSysInfo;
        ::GetSystemInfo(&siSysInfo);
        return siSysInfo.dwPageSize;
    }
    return m_cpuinfo.dwPageSize;
}
BOOL _getProcessorVendor( TCHAR *szVendorName ) {
    int CPUVendor[3];

    // Use assembly to detect CPUID information...
    __try {
        _asm {
#ifdef CPUID_AWARE_COMPILER
                ; we must push/pop the registers <<CPUID>> writes to, as the optimiser doesn't know about <<CPUID>>, 
                ; and so doesn't expect these registers to change.
                push eax
                push ebx
                push ecx
                push edx
#endif
                ; <<CPUID>>
                ; eax = 0 --> eax: maximum value of CPUID instruction.
                ;              ebx: part 1 of 3; CPU signature.
                ;              edx: part 2 of 3; CPU signature.
                ;              ecx: part 3 of 3; CPU signature.
                mov eax, 0
                CPUID_INSTRUCTION
                mov CPUVendor[0 * TYPE int], ebx
                mov CPUVendor[1 * TYPE int], edx
                mov CPUVendor[2 * TYPE int], ecx

#ifdef CPUID_AWARE_COMPILER
                pop edx
                pop ecx
                pop ebx
                pop eax
#endif
        }
    }

    // A generic catch-all just to be sure...
    __except (1) {
        return FALSE;
    }

    // Process the returned information.
    memcpy (   szVendorName,      &(CPUVendor[0]), sizeof (int));
    memcpy (&(szVendorName[4]), &(CPUVendor[1]), sizeof (int));
    memcpy (&(szVendorName[8]), &(CPUVendor[2]), sizeof (int));
    szVendorName[12] = '\0';

    return true;
}
string pay::CSysCPUInfo::getProcessorVendor() {
    string sRes;
    if ( m_bChecked ) {
        sRes = m_cpuinfo.szVendorName;
    } else {
        TCHAR szVendorName[15];
        ::memset(szVendorName,0,sizeof(szVendorName));
        BOOL isNT;
        isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
        if ( isNT ) {
            // get the info from the registry
            HKEY hKey;
            if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) ) {
                DWORD dataSize = 15;
                RegQueryValueEx (hKey, _T("VendorIdentifier"), NULL, NULL,(LPBYTE)szVendorName, &dataSize);
//                    sRes = szVendorName;
                // Make sure to close the reg key
                RegCloseKey (hKey);
            }
        } else {
            _getProcessorVendor(szVendorName);
        }
        sRes = szVendorName;
    }
    return sRes;
}
bool _getProcessorIdentifier(TCHAR *szCPUName) {
    bool bRes = true;
    TCHAR CPUName[47];
    __try {
        __asm {
            PUSH    EAX
            PUSH    EBP
            PUSH    EBX
            PUSH    ECX
            PUSH    EDI
            PUSH    EDX
            PUSH    ESI

            MOV     EAX, 0x80000002
            CPUID_INSTRUCTION

            MOV     DWORD PTR [CPUName], EAX
            MOV     DWORD PTR [CPUName + 4], EBX
            MOV     DWORD PTR [CPUName + 8], ECX
            MOV     DWORD PTR [CPUName + 12], EDX

            MOV     EAX, 0x80000003
            CPUID_INSTRUCTION

            MOV     DWORD PTR [CPUName + 16], EAX
            MOV     DWORD PTR [CPUName + 20], EBX
            MOV     DWORD PTR [CPUName + 24], ECX
            MOV     DWORD PTR [CPUName + 28], EDX

            MOV     EAX, 0x80000004
            CPUID_INSTRUCTION

            MOV     DWORD PTR [CPUName + 32], EAX
            MOV     DWORD PTR [CPUName + 36], EBX
            MOV     DWORD PTR [CPUName + 40], ECX
            MOV     DWORD PTR [CPUName + 44], EDX

            POP     ESI
            POP     EDX
            POP     EDI
            POP     ECX
            POP     EBX
            POP     EBP
            POP     EAX
        }
        memcpy(szCPUName,CPUName,sizeof(CPUName));
    } __except ( 1 ) {
        bRes = false;
    }
    return bRes;
}
string pay::CSysCPUInfo::getProcessorIdentifier() {
    string sRes;
    TCHAR vendorData[47];
    DWORD dataSize = 47;
    BOOL isNT;
    isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
    if ( isNT ) {
        // get the info from the registry
        HKEY hKey;
        if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) ) {
            if ( !::RegQueryValueEx (hKey, _T("Identifier"), NULL, NULL,(LPBYTE)vendorData, &dataSize) )
                sRes = vendorData;
            // Make sure to close the reg key
            RegCloseKey (hKey);
        }
    } else {
        TCHAR CPUName[47];
        bool bRes = _getProcessorIdentifier(CPUName);
        if (bRes) {
            sRes = CPUName;
        } else {
            sprintf( vendorData,"%s Family %d Model %d Stepping %d",getProcessorVendor().c_str(),getProcessorFamily(),getProcessorModel(),getProcessorRevision());
            sRes = vendorData;
        }
    }
    return sRes;
}
DWORD pay::CSysCPUInfo::getProcessorUsage( DWORD dwProcNum ) {
    DWORD dwRes = 0;
    BOOL isNT;
    isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
    if ( !isNT ) {
        HKEY hKey;
        DWORD dwBuff;
        if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("PerfStats\\StartStat"), 0, KEY_QUERY_VALUE, &hKey) ) {
            DWORD dataSize = sizeof(dwBuff);
            DWORD dataType = sizeof(dwBuff);
            if ( !::RegQueryValueEx (hKey, TEXT("KERNEL\\CPUUsage"), NULL, &dataType, (LPBYTE)&dwBuff, &dataSize) ) {
                if ( dataType == REG_DWORD ) 
                    dwRes = dwBuff;
            }
            // Make sure to close the reg key
            RegCloseKey (hKey);
        }
    } else {
        SYSTEM_PROCESSOR_TIMES *CPUNTUsage;
        HMODULE NTDLL_DLL;
        NTSTATUS    (__cdecl *ZwQuerySystemInformation)( UINT SystemInformationClass,
            PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ) = NULL;
        NTDLL_DLL = GetModuleHandle(_T("NTDLL.DLL"));
        if ( NTDLL_DLL != 0 ) {
            (FARPROC&)ZwQuerySystemInformation = ::GetProcAddress(NTDLL_DLL,"ZwQuerySystemInformation");
            ULONG size = sizeof(SYSTEM_PROCESSOR_TIMES)*getNumProcessors();
            CPUNTUsage = (SYSTEM_PROCESSOR_TIMES *)malloc(size);
            if (CPUNTUsage) {
                ZwQuerySystemInformation(8,CPUNTUsage,size,NULL);

                LARGE_INTEGER numer1,numer2;
                numer1 = (LARGE_INTEGER)((
                (pt->DpcTime -oldtime->DpcTime.QuadPart) +
                (pt->IdleTime.QuadPart - oldtime->IdleTime.QuadPart) +
                (pt->InterruptTime.QuadPart - oldtime->InterruptTime.QuadPart) +
                (pt->KernelTime.QuadPart - oldtime->KernelTime.QuadPart) +
                (pt->UserTime.QuadPart - oldtime->UserTime.QuadPart))/1000);
                Sleep(1000);
                ZwQuerySystemInformation(8,CPUNTUsage,size,NULL);

                numer2  = (LONGLONG)((
                (pt->DpcTime.QuadPart - oldtime->DpcTime.QuadPart) +
                (pt->InterruptTime.QuadPart - oldtime->InterruptTime.QuadPart) +
                (pt->KernelTime.QuadPart - oldtime->KernelTime.QuadPart) +
                (pt->UserTime.QuadPart - oldtime->UserTime.QuadPart))/1000);

                dwRes = CPUNTUsage[dwProcNum].DpcTime;
                dwRes = (DWORD)(deno*100/numer);

                free(CPUNTUsage);

                dwRes = 
            }
        }
    }
    return dwRes;
}
string pay::CSysCPUInfo::getProcessorManufacturer( enumProcessorManufacturer ChipManufacturer) {
//    DWORD dwChipManufacturer = m_cpuinfo.dwChipManufacturer;
    string sRes = ssCPUVendors[((ChipManufacturer>9)?0:ChipManufacturer)];
    return sRes;
}
bool checkSSEFP(){
    // Attempt to __try some SSE FP instructions.
    __try {
        // Perform: orps xmm0, xmm0
        _asm {
            _emit 0x0f
            _emit 0x56
            _emit 0xc0    
        }
    } __except (1) {
        // A generic catch-all just to be sure...
        // bad instruction - processor or OS cannot handle SSE FP.
        return  false;
    }
    // SSE FP capable processor.
    return true;
}
string getCPUIdentity( pay::CSysCPUInfo::CPUINFO &cpu ) {
    string sRes;
    // Start by decided which manufacturer we are using....
    switch (cpu.dwChipManufacturer) {
        case pay::CSysCPUInfo::Intel:
            // Check the family / model / revision to determine the CPU ID.
            switch (cpu.dwFamily) {
                case 3:
                        sRes = _T("Newer i80386 family"); 
                    break;
                case 4:
                    switch (cpu.dwModel) {
                        case 0: sRes = _T("i80486DX-25/33"); break;
                        case 1: sRes = _T("i80486DX-50"); break;
                        case 2: sRes =  _T("i80486SX"); break;
                        case 3: sRes =  _T ("i80486DX2"); break;
                        case 4: sRes =  _T ("i80486SL"); break;
                        case 5: sRes =  _T ("i80486SX2"); break;
                        case 7: sRes =  _T ("i80486DX2 WriteBack"); break;
                        case 8: sRes =  _T ("i80486DX4"); break;
                        case 9: sRes =  _T ("i80486DX4 WriteBack"); break;
                        default: sRes =  _T ("Unknown 80486 family"); return false;
                    }
                    break;
                case 5:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("Pentium P5 A-Step (0,80µm)"); break;
                        case 1: sRes =  _T ("Pentium P5 (0,50µm)"); break;
                        case 2: sRes =  _T ("Pentium P54C (0,50µm)"); break;
                        case 3: sRes =  _T ("Pentium P24T OverDrive"); break;
                        case 4: sRes =  _T ("Pentium MMX P55C (0,28µm)"); break;
                        case 5: sRes =  _T ("DX4"); break;
                        case 6: sRes =  _T ("Pentium P5"); break;
                        case 7: sRes =  _T ("Pentium P54C (0,35µm)"); break;
                        case 8: sRes =  _T ("Pentium MMX (mobile) P55C Tillamook (0.25µm)"); break;
                        default: sRes =  _T ("Unknown Pentium® family"); return false;
                    }
                    break;
                case 6:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("Pentium Pro P6 A-Step (0.50 µm)"); break;
                        case 1: sRes =  _T ("Pentium Pro P6 (0.35 µm)"); break;
                        case 3: 
                            if ( cpu.Features.L2CacheSize == 333 )
                                sRes =  _T ("Pentium® II P6T (0.25 µm)"); 
                            else
                                sRes =  _T ("Pentium® II Klamath (0.35 µm)"); 
                            if (cpu.dwType == 1)
                                sRes.append(" OverDrive");
                            break;
                        case 4: sRes =  _T ("Pentium® II P55CT (P54 OverDrive)"); break;
                        case 5: 
                            if ( cpu.Features.L2CacheSize <= 512 )
                                if ( cpu.Features.L2CacheSize == 0 )
                                    sRes = _T ("Celeron Covington (0,25µm)");
                                else
                                    sRes = _T ("Pentium® II Deschutes (0.25 µm)"); 
                            else
                                sRes = _T ("Pentium® II Xeon Deschutes (0.25 µm)");
                            break;
                        case 6: 
                            if ( cpu.Features.L2CacheSize < 256 )
                                sRes =  _T ("Celeron A Mendocino (0.25 µm)");
                            else
                                sRes =  _T ("Pentium® II PE (mobile) Dixon (0.25 µm)");
                            break;
                        case 7: 
                            if ( cpu.Features.L2CacheSize <= 512 )
                                sRes =  _T ("Pentium® III Katmai (0.25 µm)");
                            else
                                sRes =  _T ("Pentium® III Tanner (0.25 µm)");
                            break;
                        case 8: sRes =  _T ("Pentium® III Coppermine (0.18 µm) With 256 KB On-Die L2 Cache "); break;
                        case 0xa: sRes =  _T ("Pentium® III (0.18 µm) With 1 Or 2 MB On-Die L2 Cache "); break;
                        case 0xb: sRes =  _T ("Pentium® III (0.13 µm) With 256 Or 512 KB On-Die L2 Cache "); break;
                        default: sRes =  _T ("Unknown P6 family"); return false;
                    }
                    break;
                case 7:
                case 8: {
                    DWORD dwBrand;
                    dwBrand = (cpu.dwCPUFeatures >> 16 ) & 0x00FF;
                    switch (dwBrand) {
                        case 1: sRes =  _T ("Celeron"); break;
                        case 3: sRes =  _T ("Pentium® II Xeon"); break;
                        case 4: sRes =  _T ("Pentium® IV"); break;
                        default:
                            if ( cpu.Features.L2CacheSize <= 1024 )
                                sRes =  _T ("Pentium® III");
                            else
                                sRes =  _T ("Pentium® III Xeon");
                            break;
                    }
                    // sRes =  _T ("Intel Merced (IA-64)");
                    }
                    break;
                case 0xa:
                    sRes =  _T ("Pentium® II Xeon");
                    break;
                case 0xf:
                    // Check the extended family bits...
                    switch (cpu.dwExtendedFamily) {
                        case 0:
                            switch (cpu.dwModel) {
                                case 0: sRes =  _T ("Pentium® IV (0.18 µm)"); break;
                                case 1: sRes =  _T ("Pentium® IV (0.18 µm)"); break;
                                case 2: sRes =  _T ("Pentium® IV (0.13 µm)"); break;
                                default: sRes =  _T ("Unknown Pentium 4 family"); return false;
                            }
                            break;
                        case 1:
                                sRes =  _T ("Intel McKinley (IA-64)");
                            break;
                }
                break;
            default:
                sRes =  _T ("Unknown Intel family");
                return false;
            }
            break;

        case pay::CSysCPUInfo::AMD:
            // Check the family / model / revision to determine the CPU ID.
            switch (cpu.dwFamily) {
                case 4:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("Am486DX P4"); break;
                        case 3: sRes =  _T ("80486DX2 P24"); break;
                        case 7: sRes =  _T ("80486DX2 P24 WriteBack"); break;
                        case 8: sRes =  _T ("80486DX4 P24C"); break;
                        case 9: sRes =  _T ("80486DX4 P24C WriteBack"); break;
                        case 0xe: sRes =  _T ("Am5x86 X5"); break;
                        case 0xf: sRes =  _T ("Am5x86WB X5"); break;
                        default: sRes =  _T ("Unknown 80486 family"); return false;
                    }
                    break;
                case 5:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("K5 SSA5 (PR75, PR90, PR100) (0.50-0.35 µm)"); break;
                        case 1: sRes =  _T ("K5-5k86 (PR120, PR133) (0.35 µm)"); break;
                        case 2: sRes =  _T ("5k86 (PR166)"); break;
                        case 3: sRes =  _T ("5k86 (PR200)"); break;
                        case 6: sRes =  _T ("K6 (0.30 µm)"); break;
                        case 7: sRes =  _T ("K6 Little Foot (0.25 µm)"); break;
                        case 8: sRes =  _T ("K6-II Chomper (0.25 µm)"); break;
                        case 9: sRes =  _T ("K6-III Slarptooth (0.25 µm)"); break;
                        case 0xd: sRes =  _T ("K6-2+ or K6-III+ (0.18 µm)"); break;
                        default: sRes =  _T ("Unknown 80586 family"); return false;
                    }
                    break;
                case 6:
                    switch (cpu.dwModel) {
                        case 1: sRes =  _T ("Athlon™ (0.25 µm)"); break;
                        case 2: sRes =  _T ("Athlon™ (0.18 µm)"); break;
                        case 3: sRes =  _T ("Duron™ (SF core)"); break;
                        case 4: sRes =  _T ("Athlon™ (Thunderbird core)"); break;
                        case 6: sRes =  _T ("Athlon™ (Palomino core)"); break;
                        case 7: sRes =  _T ("Duron™ (Morgan core)"); break;
                        case 8: 
                            if (cpu.Features.ExtendedFeatures.SupportsMP)
                                sRes =  _T ("Athlon™ MP (Thoroughbred core)"); 
                            else 
                                sRes =  _T ("Athlon™ XP (Thoroughbred core)");
                            break;
                        default: sRes =  _T ("Unknown K7 family"); 
                            return false;
                    }
                    break;
                default:
                    sRes =  _T ("Unknown AMD family");
                    return false;
            }
            break;

        case pay::CSysCPUInfo::Transmeta:
            switch (cpu.dwFamily) {    
                case 5:
                    switch (cpu.dwModel) {
                        case 4: sRes =  _T ("Crusoe TM3x00 and TM5x00"); 
                            break;
                        default: sRes =  _T ("Unknown Crusoe family"); 
                            return false;
                    }
                    break;
                default:
                    sRes =  _T ("Unknown Transmeta family");
                    return false;
            }
            break;

        case pay::CSysCPUInfo::Rise:
            switch (cpu.dwFamily) {    
                case 5:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("mP6 (0.25 µm)"); break;
                        case 2: sRes =  _T ("mP6 (0.18 µm)"); break;
                        default: sRes =  _T ("Unknown Rise family"); return false;
                    }
                break;
            default:
                sRes =  _T ("Unknown Rise family");
                return false;
            }
            break;

        case pay::CSysCPUInfo::UMC:
            switch (cpu.dwFamily) {    
                case 4:
                    switch (cpu.dwModel) {
                        case 1: sRes =  _T ("U5D"); break;
                        case 2: sRes =  _T ("U5S"); break;
                        case 3: sRes =  _T ("U486DX2"); break;
                        case 4: sRes =  _T ("U486SX2"); break;
                        default: sRes =  _T ("Unknown UMC family"); return false;
                    }
                    break;
                default:
                    sRes =  _T ("Unknown UMC family");
                    return false;
            }
            break;

        case pay::CSysCPUInfo::IDT:
            switch (cpu.dwFamily) {    
                case 5:
                    switch (cpu.dwModel) {
                        case 4: sRes =  _T ("WinChip C6 (0.35 µm)"); break;
                        case 8: sRes =  _T ("WinChip C2 2x W2x (0.35-0.25 µm)"); break;
                        case 9: sRes =  _T ("WinChip C3 W3 (0.25 µm)"); break;
                        default: sRes =  _T ("Unknown IDT\\Centaur family"); return false;
                    }
                    break;
                case 6:
                    switch (cpu.dwModel) {
                        case 6: sRes =  _T ("VIA Cyrix III - Samuel"); break;
                        default: sRes =  _T ("Unknown IDT\\Centaur family"); return false;
                    }
                    break;
                default:
                    sRes =  _T ("Unknown IDT\\Centaur family");
                    return false;
            }
            break;

        case pay::CSysCPUInfo::Cyrix:
            switch (cpu.dwFamily) {    
                case 4:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("Cx486SLC/DLC or Cx486S or Cx486DX/DX2/DX4"); break;
                        case 4: sRes =  _T ("MediaGX GX, GXm"); break;
                        case 9: sRes =  _T ("5x86"); break;
                        default: sRes =  _T ("Unknown Cx5x86 family"); return false;
                    }
                    break;
                case 5:
                    switch (cpu.dwModel) {
                        case 2: sRes =  _T ("Cx6x86 M1 (0.65 µm) or M1L (0.35 µm)"); break;
                        case 4: sRes =  _T ("MediaGX GXm"); break;
                        default: sRes =  _T ("Unknown Cx6x86 family"); return false;
                    }
                    break;
                case 6:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("6x86MX"); break;
                        case 5: sRes =  _T ("Cyrix M2 Core"); break;
                        case 6: sRes =  _T ("WinChip C5A Core"); break;
                        case 7: sRes =  _T ("WinChip C5B\\C5C Core"); break;
                        case 8: sRes =  _T ("WinChip C5C-T Core"); break;
                        default: sRes =  _T ("Unknown 6x86MX\\Cyrix III family"); return false;
                    }
                    break;
                default:
                    sRes =  _T ("Unknown Cyrix family");
                    return false;
            }
            break;

        case pay::CSysCPUInfo::NexGen:
            switch (cpu.dwFamily) {    
                case 5:
                    switch (cpu.dwModel) {
                        case 0: sRes =  _T ("Nx586 or Nx586FPU (0.50-0.44 µm)"); break;
                        case 6: sRes =  _T ("Nx686 HA (0,50µm)"); break;
                        default: sRes =  _T ("Unknown NexGen family"); return false;
                    }
                    break;
                default:
                    sRes =  _T ("Unknown NexGen family");
                    return false;
            }
            break;

        case pay::CSysCPUInfo::NSC:
            sRes =  _T ("Cx486SLC \\ DLC \\ Cx486S A-Step");
            break;

        default:
            // We cannot identify the processor.
            sRes =  _T ("Unknown family");
            return false;
    }

    return sRes;
}
string pay::CSysCPUInfo::getSysInfoName() {
    return string(SYSINFO_CPU_PATH);
}
pay::EnumSysInfo pay::CSysCPUInfo::getSysInfoNum() {
    return pay::siCPU;
}
void pay::CSysCPUInfo::getInfo() {
    if (!m_bChecked)     
        m_bChecked = getCPUInfo(m_cpuinfo);
}
void pay::CSysCPUInfo::getInfoAsXML(ISysXMLInfo &xmlInfo) {
    if (!m_bChecked) 
        m_bChecked = getCPUInfo(m_cpuinfo);

    // get SYSINFO_CPU_PATH
    TiXmlElement *xmlCategory = xmlInfo.getCategory(SYSINFO_CPU_PATH);

    if (m_cpuinfo.dwNumProcessors) 
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_NUMPROC,m_cpuinfo.dwNumProcessors);
    if (m_cpuinfo.dwMhz) 
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_MHZ,m_cpuinfo.dwMhz);
    if (m_cpuinfo.dwPageSize) 
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_PAGESIZE,m_cpuinfo.dwPageSize);
    if (m_cpuinfo.szProcessorName[0]) 
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_VENDOR,m_cpuinfo.szVendorName);
    if (m_cpuinfo.szProcessorArchitecture[0]) 
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_ARCHITECTURE,m_cpuinfo.szProcessorArchitecture);
    if (m_cpuinfo.szProcessorName[0]) 
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_PROCESSORNAME,m_cpuinfo.szProcessorName);
    
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_CHIPMANUFACTURER,getProcessorManufacturer((enumProcessorManufacturer)m_cpuinfo.dwChipManufacturer).c_str());
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_TYPE,m_cpuinfo.dwType);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FAMILY,m_cpuinfo.dwFamily);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_REVISION,m_cpuinfo.dwRevision);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_MODEL,m_cpuinfo.dwModel);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_TYPE,m_cpuinfo.dwType);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_EXTENDEDFAMILY,m_cpuinfo.dwExtendedFamily);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_EXTENDEDMODEL,m_cpuinfo.dwExtendedModel);
    
    xmlCategory = xmlInfo.getCategory(SYSINFO_CPU_FEATURES_PATH);

    TCHAR *ssSupport[] = {"Not Supported","Supported"};
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_FPU,ssSupport[m_cpuinfo.Features.HasFPU]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_TSC,ssSupport[m_cpuinfo.Features.HasTSC]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_MMX,ssSupport[m_cpuinfo.Features.HasMMX]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSE,ssSupport[m_cpuinfo.Features.HasSSE]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSEFP,ssSupport[m_cpuinfo.Features.HasSSEFP]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSE2,ssSupport[m_cpuinfo.Features.HasSSE2]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_IA64,ssSupport[m_cpuinfo.Features.HasIA64]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_APIC,ssSupport[m_cpuinfo.Features.HasAPIC]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_CMOV,ssSupport[m_cpuinfo.Features.HasCMOV]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_MTRR,ssSupport[m_cpuinfo.Features.HasMTRR]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_ACPI,ssSupport[m_cpuinfo.Features.HasACPI]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SERIAL,ssSupport[m_cpuinfo.Features.HasSerial]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_THERMAL,ssSupport[m_cpuinfo.Features.HasThermal]);
    if (m_cpuinfo.Features.L1CacheSize != -1)
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_L1CACHESIZE,(DWORD)m_cpuinfo.Features.L1CacheSize);
    if (m_cpuinfo.Features.L2CacheSize != -1)
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_L2CACHESIZE,(DWORD)m_cpuinfo.Features.L2CacheSize);
    if (m_cpuinfo.Features.L3CacheSize != -1)
        xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_L3CACHESIZE,(DWORD)m_cpuinfo.Features.L3CacheSize);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_3DNOW,ssSupport[m_cpuinfo.Features.ExtendedFeatures.Has3DNow]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_3DNOW,ssSupport[m_cpuinfo.Features.ExtendedFeatures.Has3DNowPlus]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SUPPORTSMP,ssSupport[m_cpuinfo.Features.ExtendedFeatures.SupportsMP]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_MMXPLUS,ssSupport[m_cpuinfo.Features.ExtendedFeatures.HasMMXPlus]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSEMMX,ssSupport[m_cpuinfo.Features.ExtendedFeatures.HasSSEMMX]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SUPPORTSHYPERTHREADING,ssSupport[m_cpuinfo.Features.ExtendedFeatures.SupportsHyperthreading]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_LOGICALPROCESSORSPERPHYSICAL,(DWORD)m_cpuinfo.Features.ExtendedFeatures.LogicalProcessorsPerPhysical);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_VOLTAGEID,ssSupport[m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasVoltageID]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_FREQUENCYID,ssSupport[m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasFrequencyID]);
    xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_TEMPSENSEDIODE,ssSupport[m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode]);

    xmlInfo.deleteCategory(SYSINFO_CPU_PROCESSORID_PATH);
    DWORD i = 0;
//    if (m_cpuinfo.Features.HasSerial)
        for (vector<CPUID>::iterator it = m_cpuinfo.idCPU.begin(); it != m_cpuinfo.idCPU.end(); it++ ) {
            xmlCategory = xmlInfo.getCategory(SYSINFO_CPU_PROCESSORID_PATH,true);
            xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_NUM,++i);
            if ( (*it).dwProcessorUsage != -1 )
                xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_USAGE,(DWORD)((*it).dwProcessorUsage));
            if ( (*it).szSerialNumber[0] )
                xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_ID,(*it).szSerialNumber);
        }
}
BOOL pay::CSysCPUInfo::getCPUInfo( pay::CSysCPUInfo::CPUINFO &cpu ) {
    if ( m_bChecked ) {
        memcpy(&cpu,&m_cpuinfo,sizeof(pay::CSysCPUInfo::CPUINFO));
        cpu.idCPU.clear();
        for (vector<CPUID>::iterator it = m_cpuinfo.idCPU.begin(); it != m_cpuinfo.idCPU.end(); it++ )
            cpu.idCPU.push_back(*it);    
        return TRUE;
    }
    // get processor vendor
    strncpy(cpu.szVendorName,getProcessorVendor().c_str(),sizeof(cpu.szVendorName));
    // Attempt to retrieve the manufacturer from the vendor string.
    if        (strcmp (cpu.szVendorName, "GenuineIntel") == 0)       cpu.dwChipManufacturer = Intel;                // Intel Corp.
    else if (strcmp (cpu.szVendorName, "UMC UMC UMC ") == 0)    cpu.dwChipManufacturer = UMC;                    // United Microelectronics Corp.
    else if (strcmp (cpu.szVendorName, "AuthenticAMD") == 0)        cpu.dwChipManufacturer = AMD;                    // Advanced Micro Devices
    else if (strcmp (cpu.szVendorName, "AMD ISBETTER") == 0)    cpu.dwChipManufacturer = AMD;                    // Advanced Micro Devices (1994)
    else if (strcmp (cpu.szVendorName, "CyrixInstead") == 0)        cpu.dwChipManufacturer = Cyrix;                // Cyrix Corp., VIA Inc.
    else if (strcmp (cpu.szVendorName, "NexGenDriven") == 0)        cpu.dwChipManufacturer = NexGen;                // NexGen Inc. (now AMD)
    else if (strcmp (cpu.szVendorName, "CentaurHauls") == 0)        cpu.dwChipManufacturer = IDT;                  // IDT/Centaur (now VIA)
    else if (strcmp (cpu.szVendorName, "RiseRiseRise") == 0)        cpu.dwChipManufacturer = Rise;                    // Rise
    else if (strcmp (cpu.szVendorName, "GenuineTMx86") == 0)        cpu.dwChipManufacturer = Transmeta;            // Transmeta
    else if (strcmp (cpu.szVendorName, "TransmetaCPU") == 0)    cpu.dwChipManufacturer = Transmeta;            // Transmeta
    else if (strcmp (cpu.szVendorName, "Geode By NSC") == 0)        cpu.dwChipManufacturer = NSC;                    // National Semiconductor
    else                                                                                cpu.dwChipManufacturer = Unknown;           // Unknown manufacturer

    // get processor speed
    cpu.dwMhz = getProcessorSpeed();
    // get number of processors
    cpu.dwNumProcessors = getNumProcessors();
    // get processor page size
    cpu.dwPageSize = getProcessorPageSize();
    // get processor identifier
    strncpy(cpu.szProcessorArchitecture,getProcessorIdentifier().c_str(),sizeof(cpu.szProcessorArchitecture));
    // Retrieve the family of CPU present.
    int CPUSignature = getProcessorSignature();
    cpu.dwExtendedFamily =        ((CPUSignature & 0x0FF00000) >> 20);    // Bits 27..20 Used
    cpu.dwExtendedModel =        ((CPUSignature & 0x000F0000) >> 16);    // Bits 19..16 Used
    cpu.dwType =                        ((CPUSignature & 0x0000F000) >> 12);    // Bits 15..12 Used
    cpu.dwFamily =                    ((CPUSignature & 0x00000F00) >> 8);        // Bits 11..8 Used
    cpu.dwModel =                    ((CPUSignature & 0x000000F0) >> 4);        // Bits 7..4 Used
    cpu.dwRevision =                    ((CPUSignature & 0x0000000F) >> 0);        // Bits 3..0 Used

    cpu.dwCPUFeatures = getProcessorFeatures();
    // Retrieve the features of CPU present.
    cpu.Features.HasFPU =            ((cpu.dwCPUFeatures & 0x00000001) != 0);        // FPU Present --> Bit 0
    cpu.Features.HasTSC =            ((cpu.dwCPUFeatures & 0x00000010) != 0);        // TSC Present --> Bit 4
    cpu.Features.HasAPIC =        ((cpu.dwCPUFeatures & 0x00000200) != 0);        // APIC Present --> Bit 9
    cpu.Features.HasMTRR =        ((cpu.dwCPUFeatures & 0x00001000) != 0);        // MTRR Present --> Bit 12
    cpu.Features.HasCMOV =        ((cpu.dwCPUFeatures & 0x00008000) != 0);        // CMOV Present --> Bit 15
    cpu.Features.HasSerial =        ((cpu.dwCPUFeatures & 0x00040000) != 0);        // Serial Present --> Bit 18
    cpu.Features.HasACPI =        ((cpu.dwCPUFeatures & 0x00400000) != 0);        // ACPI Capable --> Bit 22
    cpu.Features.HasMMX =        ((cpu.dwCPUFeatures & 0x00800000) != 0);        // MMX Present --> Bit 23
    cpu.Features.HasSSE =            ((cpu.dwCPUFeatures & 0x02000000) != 0);        // SSE Present --> Bit 25
    cpu.Features.HasSSE2 =        ((cpu.dwCPUFeatures & 0x04000000) != 0);        // SSE2 Present --> Bit 26
    cpu.Features.HasThermal =    ((cpu.dwCPUFeatures & 0x20000000) != 0);        // Thermal Monitor Present --> Bit 29
    cpu.Features.HasIA64 =        ((cpu.dwCPUFeatures & 0x40000000) != 0);        // IA64 Present --> Bit 30


    // Retrieve extended SSE capabilities if SSE is available.
    if (cpu.Features.HasSSE) 
        cpu.Features.HasSSEFP = checkSSEFP();
    else
        cpu.Features.HasSSEFP = false;
    // Retrieve Intel specific extended features.
    if (cpu.dwChipManufacturer == Intel) {
        cpu.Features.ExtendedFeatures.SupportsHyperthreading = ((cpu.dwCPUFeatures &    0x10000000) != 0);    // Intel specific: Hyperthreading --> Bit 28
        cpu.Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (cpu.Features.ExtendedFeatures.SupportsHyperthreading) ? ((cpu.dwCPUFeatures & 0x00FF0000) >> 16) : 1;
        if ((cpu.Features.ExtendedFeatures.SupportsHyperthreading) && (cpu.Features.HasAPIC)){
            // Retrieve APIC information if there is one present.
            cpu.Features.ExtendedFeatures.APIC_ID = ((cpu.dwCPUFeatures & 0xFF000000) >> 24);
        }
    }

    // Retrieve the CPU details.

//    RetrieveCPUFeatures(cpu);

    // Attempt to retrieve cache information.
    RetrieveCPUCacheDetails(cpu);

    // Retrieve the extended CPU details.
    RetrieveExtendedCPUIdentity (cpu);

    RetrieveExtendedCPUFeatures (cpu);

    strncpy(cpu.szProcessorName,getCPUIdentity(cpu).c_str(),sizeof(cpu.szProcessorName));
    
//    if (cpu.Features.HasSerial)
        for (DWORD i = 0; i < cpu.dwNumProcessors; i++) {
            CPUID cpuid;
            cpuid.szSerialNumber[0] = 0;
            cpuid.dwProcessorUsage = -1;
            // Now attempt to retrieve the serial number (if possible).
            memcpy(cpuid.szSerialNumber,getProcessorSerialNumber(i).c_str(),sizeof(cpuid.szSerialNumber));
            cpu.idCPU.push_back(cpuid);
        }

    return TRUE;
}
... << RSDN@Home 1.0 beta 6a >>
Re[6]: System info
От: payglobal  
Дата: 31.03.03 09:59
Оценка:
Здравствуйте, Thinker, Вы писали:

T> Нет привязку софта я делать не буду ! я хочу контролшировать непосредственно

T> конфигурацию тачек в сети и отслеживать любые изменения ! а для этого нужно прочитать
T> всю системную инфу о жезелке !

Вот идишь, — КОНТРОЛИРОВАТЬ — а какой контроль, если любой баклан с адмнными правами может твой WMI остановить
... << RSDN@Home 1.0 beta 6a >>
Re[7]: System info
От: serg_p Украина  
Дата: 31.03.03 10:01
Оценка:
P>Вот идишь, — КОНТРОЛИРОВАТЬ — а какой контроль, если любой баклан с адмнными правами может твой WMI остановить

Так ведь пароль администратора нато и даден что-бы только ОН его и знал.
Re[6]: System info
От: payglobal  
Дата: 31.03.03 10:02
Оценка:
Здравствуйте, Thinker, Вы писали:

T> Нет привязку софта я делать не буду ! я хочу контролшировать непосредственно

T> конфигурацию тачек в сети и отслеживать любые изменения ! а для этого нужно прочитать
T> всю системную инфу о жезелке !

Кстати, у меня схожая задача, правда мы контролируем ВСЕ, не только железо.

написал я классы, которые инфу собирают. проблема — как сравнить.
я собираю в результирующтий XML. а вот сравнить два XML — вот проблема
... << RSDN@Home 1.0 beta 6a >>
Re[8]: System info
От: payglobal  
Дата: 31.03.03 10:09
Оценка:
Здравствуйте, serg_p, Вы писали:

P>>Вот идишь, — КОНТРОЛИРОВАТЬ — а какой контроль, если любой баклан с адмнными правами может твой WMI остановить


SP>Так ведь пароль администратора нато и даден что-бы только ОН его и знал.


( мы тоже так раньше считали ((( )

это в теории — практика ужасней.
из практики — завод. 1500 компов. никакой админ не набегается софт переставлять
увы, реальность
... << RSDN@Home 1.0 beta 6a >>
Re[7]: System info
От: Thinker  
Дата: 31.03.03 15:23
Оценка:
Здравствуйте, payglobal, Вы писали:

P>Здравствуйте, Thinker, Вы писали:


T>> Нет привязку софта я делать не буду ! я хочу контролшировать непосредственно

T>> конфигурацию тачек в сети и отслеживать любые изменения ! а для этого нужно прочитать
T>> всю системную инфу о жезелке !

P>Кстати, у меня схожая задача, правда мы контролируем ВСЕ, не только железо.


P>написал я классы, которые инфу собирают. проблема — как сравнить.

P>я собираю в результирующтий XML. а вот сравнить два XML — вот проблема

P>

Вечер добрый уважаемы Payglobal и Serg_p !!
===============================================

Пишу к Вам по скольку остальное прогрессивное программерство промолчало !!
-----------------------------------------------------------------------------

Итак перейду к главному !

1. на счет кол-ва компом на зводе и бегатни с установкой софта — согласен на все 105 %
но это можно порешить. (Нопомню еще более конкретно в чем задача: каждый год у на сна предприятии происходит инвентаризация. Так вот поскольку народу много и большая текучка а народ стал не в меру умный я решил сделать следующее: пишу прогу которая максимально собирает инфу о коме и во время очередной инвентаризации коммиссия в состав которой входит мой специалист
проходит по местам запущает прогу печатает результат на бамаге и ставятся подписи моего спеца
чуловека который работает за компом. В результате получаем полный отчет о компе который потом
пишем в необходимую базу для дальнейшего учета)

и хай умные люди отключают WMI и прочее.
а вааще хотелось бы получать инфу не через WMI.
Если у вас имеются соображения или кое что готовое с радостью приму сеф дар !!


With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[7]: System info
От: Thinker  
Дата: 31.03.03 15:24
Оценка:
Здравствуйте, payglobal, Вы писали:

P>Здравствуйте, Thinker, Вы писали:


T>> Нет привязку софта я делать не буду ! я хочу контролшировать непосредственно

T>> конфигурацию тачек в сети и отслеживать любые изменения ! а для этого нужно прочитать
T>> всю системную инфу о жезелке !

P>Кстати, у меня схожая задача, правда мы контролируем ВСЕ, не только железо.


P>написал я классы, которые инфу собирают. проблема — как сравнить.

P>я собираю в результирующтий XML. а вот сравнить два XML — вот проблема

P>

Вечер добрый уважаемы Payglobal и Serg_p !!
===============================================

Пишу к Вам по скольку остальное прогрессивное программерство промолчало !!
-----------------------------------------------------------------------------

Итак перейду к главному !

1. на счет кол-ва компом на зводе и бегатни с установкой софта — согласен на все 105 %
но это можно порешить. (Нопомню еще более конкретно в чем задача: каждый год у на сна предприятии происходит инвентаризация. Так вот поскольку народу много и большая текучка а народ стал не в меру умный я решил сделать следующее: пишу прогу которая максимально собирает инфу о коме и во время очередной инвентаризации коммиссия в состав которой входит мой специалист
проходит по местам запущает прогу печатает результат на бамаге и ставятся подписи моего спеца
чуловека который работает за компом. В результате получаем полный отчет о компе который потом
пишем в необходимую базу для дальнейшего учета)

а потом в дальгейшем при каких либо апгрейдах и прочих делах спец будет запускать прогу (если конечно не смогу сдалать все красиво и будем сравнивать с начальным вариантом)

и еще а представьте себе картину когда в вашем подчинении находится порядка 1700-2100 компов
территориально разбросанных на расстояние до 200 км но соединенных в 1 сетку. Это же просто праздник какой-то получить по ним статистику и сделать любой отчет и анализ железа который стоит.

и хай умные люди отключают WMI и прочее.
а вааще хотелось бы получать инфу не через WMI.
Если у вас имеются соображения или кое что готовое с радостью приму сеф дар !!


With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[8]: System info
От: payglobal  
Дата: 01.04.03 05:58
Оценка:
Здравствуйте, Thinker, Вы писали:

T>и хай умные люди отключают WMI и прочее.

T>а вааще хотелось бы получать инфу не через WMI.
T>Если у вас имеются соображения или кое что готовое с радостью приму сеф дар !!

Признаю, что для предложенной Вами методики инвентаризации действительно больше подходит WMI

а лучше всего — воспользоваться уже написанным софтом (бесплатным)
посмотри на www.softkey.info subj для поиска — инвентаризация.
около месяца-двух был большой обзор

[печатается на правах рекламы ]
у нас другая задача — мы пишем комплекс контроля информационной политики предприятия.
реализуется это через активный аудит, который собирает "агент" с рабочей станции, причем делает это невидимо для пользователя.
кроме того, система позволяет настраивать рабочие станции путем разрешения или запрещения работы с ресурсами ( файлы, каталоги, интернет, внешние устройства и т.п. )

С уважением ...
... << RSDN@Home 1.0 beta 6a >>
Re[9]: System info
От: Thinker  
Дата: 02.04.03 07:56
Оценка:
Здравствуйте, payglobal, Вы писали:

P>Здравствуйте, Thinker, Вы писали:


T>>и хай умные люди отключают WMI и прочее.

T>>а вааще хотелось бы получать инфу не через WMI.
T>>Если у вас имеются соображения или кое что готовое с радостью приму сеф дар !!

P>Признаю, что для предложенной Вами методики инвентаризации действительно больше подходит WMI


P>а лучше всего — воспользоваться уже написанным софтом (бесплатным)

P>посмотри на www.softkey.info subj для поиска — инвентаризация.
P>около месяца-двух был большой обзор

День добрый Payglobal.

А не будете ли тогда так любезные поделиться примерами кода (если конечно не жалко)

а на счет писанного софта ?
если так рассуждать то через пару сотен лет программисты вааще вымрут и ничего писать не будут
а будут тока злобные хакеры и прочая нечесть которая не строит а ломает !

With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[10]: System info
От: payglobal  
Дата: 03.04.03 05:47
Оценка:
Здравствуйте, Thinker, Вы писали:

T> День добрый Payglobal.


T> А не будете ли тогда так любезные поделиться примерами кода (если конечно не жалко)


примерами кода — жалко, но поделюсь
но толко в ответ на конкретные вопросы

T> а на счет писанного софта ?

T> если так рассуждать то через пару сотен лет программисты вааще вымрут и ничего писать не будут
T> а будут тока злобные хакеры и прочая нечесть которая не строит а ломает !

Но Вы же не переписываете заново ОС, офис, и т.п. ... не смущает?

T> With best regards, Thinker
... << RSDN@Home 1.0 beta 6a >>
Re[11]: System info
От: Thinker  
Дата: 03.04.03 06:18
Оценка:
Здравствуйте, payglobal, Вы писали:


P>примерами кода — жалко, но поделюсь

P>но толко в ответ на конкретные вопросы

Мне не много нужно !

только самое главное — готовые процедуры определения

тип и частотат проца
название и ёмкость винта
кол-во ОЗУ
тип мамки
тип видюка
тип сетевухи
н ув приципе и все !
остальные данные буду колотить руками

(только без WMI)

P>Но Вы же не переписываете заново ОС, офис, и т.п. ... не смущает?


Ну а как же не безизвестных Линус Товалд с его новой операционкой !

да и вааще ! в нашей стране да и в вашей пока будут существовать такие законы о
программном обеспечении порядка не будет )) для них а для нас всегда рай

With best regards, Thinker


P.S. Да вот вспомнил наковырял кучу прог которые определяют конфигурацию железа и пропустил их
через TDUMP от Borland — много интересного узнал как чего определять но вот все равно
не все там есть ! Абыдно да ?
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[12]: System info
От: payglobal  
Дата: 03.04.03 06:58
Оценка:
Здравствуйте, Thinker, Вы писали:
T> только самое главное — готовые процедуры определения
у меня библиотека. и специально для тебя ее переписывать не буду. уж извини

T> тип и частотат проца

T> название и ёмкость винта
T> кол-во ОЗУ
T> тип мамки
это пока не знаю как ((( т.е. пока не начинал копать
T> тип видюка
T> тип сетевухи

с чего начнем? у меня есть еще и основная работа (((

Попробуй Sandra SiSoft
... << RSDN@Home 1.0 beta 6a >>
Re[12]: System info
От: serg_p Украина  
Дата: 03.04.03 07:08
Оценка:
Может все-таки WMI?

тип и частотат проца — Win32_Processor
кол-во ОЗУ — Win32_PhysicalMemory
тип мамки — Win32_MotherboardDevice
тип видюка — Win32_VideoController
тип сетевухи — Win32_NetworkAdapter
Re[13]: System info
От: payglobal  
Дата: 03.04.03 07:23
Оценка:
Здравствуйте, serg_p, Вы писали:

SP>Может все-таки WMI?


SP>тип и частотат проца — Win32_Processor

SP>кол-во ОЗУ — Win32_PhysicalMemory
SP>тип мамки — Win32_MotherboardDevice
SP>тип видюка — Win32_VideoController
SP>тип сетевухи — Win32_NetworkAdapter

теперь и я согласен.
говорю — для тех целей, что ему надо — достаточно WMI — а главное гемора меньше
... << RSDN@Home 1.0 beta 6a >>
Re[14]: System info
От: Thinker  
Дата: 03.04.03 08:19
Оценка:
Здравствуйте, payglobal, Вы писали:

Здравствуйте, serg_p, Вы писали:

P>теперь и я согласен.

P>говорю — для тех целей, что ему надо — достаточно WMI — а главное гемора меньше


Я про согласен что это может быть лучше и меньше гемора но есть 2 но

1 — на мелкософтоском сайте лежит WMI v 1.1 для тачек с виндо от 2000 и выше

2 — а как же тады работаю всякие там AIDA32, SiSoft Sandra и прочая софта ??



With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[13]: System info
От: Thinker  
Дата: 03.04.03 08:22
Оценка:
Здравствуйте, payglobal, Вы писали:


P>с чего начнем? у меня есть еще и основная работа (((


Прости брат ! больше не буду отвлекать !

P>Попробуй Sandra SiSoft


ну и на кой Х она мне надо если мне нужно свою спецфическое ???


With best regards, Thinker
With best regards, Thinker.

<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Re[15]: System info
От: serg_p Украина  
Дата: 03.04.03 08:25
Оценка:
T> 1 — на мелкософтоском сайте лежит WMI v 1.1 для тачек с виндо от 2000 и выше

Я же выслал Вам ссылку на WMI для Windows 9x.!!!
Re[14]: System info
От: payglobal  
Дата: 03.04.03 09:44
Оценка:
Здравствуйте, Thinker, Вы писали:

T>Здравствуйте, payglobal, Вы писали:


T>

P>>с чего начнем? у меня есть еще и основная работа (((

T> Прости брат ! больше не буду отвлекать !


Не обижайся, брат, — я просто говорил, что переделывать правда нет времени.
а библиотека потянет за собой другие библиотеки из проекта ((

Давай так — переходи на мыло payglobal@yahoo.com или аську 78911328
и давай с конкретными вопросами по порядку. буду выдирать, давать с комментариям
... << RSDN@Home 1.0 beta 6a >>
Re[8]: System info
От: Drakosha13  
Дата: 02.04.08 10:00
Оценка:
Здравствуйте, serg_p, Вы писали:

P>>Вот идишь, — КОНТРОЛИРОВАТЬ — а какой контроль, если любой баклан с адмнными правами может твой WMI остановить


_>Так ведь пароль администратора нато и даден что-бы только ОН его и знал.


пароль администратора, да и любого другого пользователя в Windows XP снимается за 5 мин
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.