|
If I remembered correctly, the code only works with Intel CPUs. Try google or AMD site to find some code for retrieving CPU serial number.
Best regards,
A. Riazi
|
|
|
|
|
Hi Abbas
I compiled and executed your sample, I recieved a error in the edit box when I chose Partitions from the combo. So I took a look a your source code.
Heres what I discovered:
In QueryPartitions funtion, the call to DeviceIoControl will sometimes fail with the error code ERROR_INSUFFICIENT_BUFFER. This is because the struct DRIVE_LAYOUT_INFORMATION_EX that needs to be passed to DeviceIoControl is variable length, the size of the data returned depends on the number of drives, and partitions.
In addition, some driver implementations will return a partial buffer, they will simply write whatever data they can fit into the buffer. DeviceIoControl will fail with error code ERROR_MORE_DATA in this case.
These conditions can be handled by doing the following:
First change variable dli declaration to:
DRIVE_LAYOUT_INFORMATION_EX* dli = NULL;
Here is the code to insert:
DWORD dwbytes=0;<br />
DWORD dwlastErr = 0;<br />
int i=0;<br />
<br />
do<br />
{<br />
if(NULL != dli)<br />
{<br />
delete[] (char*)dli;<br />
dli = NULL;<br />
}<br />
<br />
DWORD datasize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + i * sizeof(PARTITION_INFORMATION_EX);<br />
dli = (DRIVE_LAYOUT_INFORMATION_EX*)new char[datasize];<br />
if(dli)<br />
{<br />
bResult=DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_LAYOUT_EX,NULL,0,dli, datasize,&dwbytes,(LPOVERLAPPED) NULL);<br />
dwlastErr = GetLastError();<br />
i++;<br />
}<br />
}<br />
while((dwbytes == 0 && dwlastErr == ERROR_INSUFFICIENT_BUFFER) || dwlastErr == ERROR_MORE_DATA);
The code needs to be modified here:
while (hDevice!=INVALID_HANDLE_VALUE)<br />
{<br />
***DELETE OLD CODE HERE***<br />
***INSERT NEW CODE HERE***<br />
<br />
if (bResult)<br />
{<br />
Then at the bottom of the QueryPartitions function add:
if(NULL != dli)<br />
{<br />
delete[] (char*)dli;<br />
dli = NULL;<br />
}
I believe something similar is required for each function where you are calling DeviceIoControl. Additional error handling is required.
Thanks for your articles, I look forward to your future contributions!
-Randor (Dave Delaune)
|
|
|
|
|
Hi A.Riazi, can I call you like that.I'm a student from Viet Nam and I'm doing a project to get system information but it's hard to find document about this topic.I have seen your code but I don't know how it's work .Can you give or introduce me some document about getting system information.
-- modified at 6:34 Tuesday 11th April, 2006
|
|
|
|
|
Hi,
You have two options for getting system informations:
1- WMI
2- Win32 API (like the one that I did).
I suggest you to read Win32 API documentations.
Best regards,
A. Riazi
|
|
|
|
|
I see that you have use assembly code in your source .What does it do?
-- modified at 4:15 Wednesday 12th April, 2006
|
|
|
|
|
The assembly code was written by someone else for getting CPU info.
A. Riazi
|
|
|
|
|
hi mr a. riazi
i need your help
in a smal project can u contact me plz
quraischi@msn.com
hello world
|
|
|
|
|
Can you please include a function to retrieve hard Drive serial number (atleast first drive). It would be very helpful.
Thanks
nomi
knowmi@gmail.com
|
|
|
|
|
i am getting compilation error
CSIDL_WINDOWS etc.
as undeclared identifier.
i read the solution for it posted.but i couldn'g understand that.
can u just explain how and what i have to add breifly.
|
|
|
|
|
At line 286 in SysInfoDefs.cpp you wrote:
ceil(memoryStatus.dwTotalPhys/1024/1024)
It should be:
ceil(memoryStatus.dwTotalPhys/1024.0/1024.0)
if you want the ceil function to have an effect.
The best would be:
ceil(memoryStatus.dwTotalPhys/1048576.0)
One division less
Crayon
|
|
|
|
|
Thanks for your comment.
Best regards,
A. Riazi
|
|
|
|
|
is it possible for a certain drive name (for example "C:\") on which IDE Hard drive. For computers that have more than one harddrive.
Thanks Ugur Basak
|
|
|
|
|
I've modified QueryHDDSmartCommand, i use a variable strDriveName="\\\\.\\c:"
and changed
if ((hSMARTIOCTL = CreateFile(strDriveName, 0,0,0,
CREATE_NEW, 0, 0)) == INVALID_HANDLE_VALUE)
and
if ((hSMARTIOCTL = CreateFile(strDriveName,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,
OPEN_EXISTING,0,NULL)) == INVALID_HANDLE_VALUE)
its working. Thanks anyway, your article is really excellent.
|
|
|
|
|
Hi,
i know it is not that serious but maybe someone will get disturbed by a Detected Memory Leaks message during debugger mode.
It is caused by a missing delete Speed; in the CPUInfo deconstructor. The Speed member is allocated using the new operator.
Greetings,
Juri
|
|
|
|
|
Hi,
Thanks for your comment.
Best regards,
A. Riazi
|
|
|
|
|
Hi!
I like this small app.
I'm wondering if it's possible to also display the OS Language used, User language, keyboard settings etc.
Are there any API's for this?
Thanks!
|
|
|
|
|
You need to add the pack paragma to your code. I noticed that the data in your structures was misaligned when I was modifying your code to retrieve the temperature of the hard drive.
#pragma pack(1)
//---------------------------------------------------------------------
// The following structure defines the structure of a Drive Attribute
//---------------------------------------------------------------------
typedef struct _DRIVEATTRIBUTE {
BYTE bAttrID; // Identifies which attribute
WORD wStatusFlags; // see bit definitions below
BYTE bAttrValue; // Current normalized value
BYTE bWorstValue; // How bad has it ever been?
BYTE bRawValue[6]; // Un-normalized value
BYTE bReserved; // ...
} DRIVEATTRIBUTE, *PDRIVEATTRIBUTE, *LPDRIVEATTRIBUTE;
//---------------------------------------------------------------------
// The following structure defines the structure of a Warranty Threshold
// Obsoleted in ATA4!
//---------------------------------------------------------------------
typedef struct _ATTRTHRESHOLD {
BYTE bAttrID; // Identifies which attribute
BYTE bWarrantyThreshold; // Triggering value
BYTE bReserved[10]; // ...
} ATTRTHRESHOLD, *PATTRTHRESHOLD, *LPATTRTHRESHOLD;
//---------------------------------------------------------------------
// The following struct defines the interesting part of the IDENTIFY
// buffer:
//---------------------------------------------------------------------
typedef struct _IDSECTOR {
USHORT wGenConfig;
USHORT wNumCyls;
USHORT wReserved;
USHORT wNumHeads;
USHORT wBytesPerTrack;
USHORT wBytesPerSector;
USHORT wSectorsPerTrack;
USHORT wVendorUnique[3];
CHAR sSerialNumber[20];
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR sFirmwareRev[8];
CHAR sModelNumber[40];
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG ulCurrentSectorCapacity;
USHORT wMultSectorStuff;
ULONG ulTotalAddressableSectors;
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE bReserved[128];
} IDSECTOR, *PIDSECTOR;
#pragma pack()
*** The following might be useful updates too:
ULONGLONG PrintSmartAttribRawValue(PCHAR szOut, PDRIVEATTRIBUTE attribute)
{
ULONGLONG rawvalue;
BYTE word[3];
int j;
// convert the six individual bytes to a long long (8 byte) integer.
// This is the value that we'll eventually return.
rawvalue = 0;
for (j = 0; j < 6; j++)
{
// This looks a bit roundabout, but is necessary. Don't
// succumb to the temptation to use raw[j]<<(8*j) since under
// the normal rules this will be promoted to the native type.
// On a 32 bit machine this might then overflow.
ULONGLONG temp;
temp = attribute->bRawValue[j];
temp <<= 8*j;
rawvalue |= temp;
}
// convert quantities to three two-byte words
for(j = 0; j < 3; j++)
{
word[j] = attribute->bRawValue[2*j+1];
word[j] <<= 8;
word[j] |= attribute->bRawValue[2*j];
}
// This switch statement is where we handle Raw attributes
// that are stored in an unusual vendor-specific format,
switch (attribute->bAttrID)
{
// Spin-up time
case 3:
szOut += sprintf(szOut, "%d", word[0]);
// if second nonzero then it stores the average spin-up time
if(word[1])
szOut += sprintf(szOut, " (Average %d)", word[1]);
break;
// Power on time
case 9:
szOut += sprintf(szOut, "%I64u", rawvalue); //stored in hours
break;
// Load unload cycles
case 193:
szOut += sprintf(szOut, "%I64u", rawvalue);
break;
// Temperature
case 194:
szOut += sprintf(szOut, "%d", word[0]);
if (!(rawvalue==word[0]))
{
int min = word[1] < word[2]? word[1]: word[2];
int max = word[1] > word[2]? word[1]: word[2];
// The other bytes are in use. Try IBM's model
szOut += sprintf(szOut, " (Lifetime Min/Max %d/%d)", min, max);
}
break;
default:
szOut += sprintf(szOut, "%I64u", rawvalue);
break;
}
// Return the full value
return rawvalue;
}
// Note some attribute names appear redundant because different
// manufacturers use different attribute IDs for an attribute with the
// same name. The variable val should contain a non-zero value if a particular
// attributes has a non-default interpretation.
PCHAR GetSmartAttribName(BYTE id)
{
PCHAR szName = "Unknown_Attribute";
switch(id)
{
case 1: szName = "Raw Read Error Rate"; break;
case 2: szName = "Throughput Performance"; break;
case 3: szName = "Spin Up Time"; break;
case 4: szName = "Start Stop Count"; break;
case 5: szName = "Reallocated Sector Ct"; break;
case 6: szName = "Read Channel Margin"; break;
case 7: szName = "Seek Error Rate"; break;
case 8: szName = "Seek Time Performance"; break;
case 9: szName = "Power On Hours"; break;
case 10: szName = "Spin Retry Count"; break;
case 11: szName = "Calibration Retry Count"; break;
case 12: szName = "Power Cycle Count"; break;
case 13: szName = "Read Soft Error Rate"; break;
case 191: szName = "G-Sense Error Rate"; break;
case 192: szName = "Power-Off Retract Count"; break;
case 193: szName = "Load Cycle Count"; break;
case 194: szName = "Temperature Celsius"; break;
case 195: szName = "Hardware ECC Recovered"; break;
case 196: szName = "Reallocated Event Count"; break;
case 197: szName = "Current Pending Sector"; break;
case 198: szName = "Offline Uncorrectable"; break;
case 199: szName = "UDMA CRC Error Count"; break;
case 200: szName = "Write Error Count"; break;
case 201: szName = "Detected TA Count"; break;
case 202: szName = "TA Increase Count"; break;
case 203: szName = "Run Out Cancel"; break;
case 204: szName = "Shock Count Write Opern"; break;
case 205: szName = "Shock Rate Write Opern"; break;
case 206: szName = "Flying Height"; break;
case 207: szName = "Spin High Current"; break;
case 208: szName = "Spin Buzz"; break;
case 209: szName = "Offline Seek Performnce"; break;
case 220: szName = "Disk Shift"; break;
case 221: szName = "G-Sense Error Rate"; break;
case 222: szName = "Loaded Hours"; break;
case 223: szName = "Load Retry Count"; break;
case 224: szName = "Load Friction"; break;
case 225: szName = "Load Cycle Count"; break;
case 226: szName = "Load-in Time"; break;
case 227: szName = "Torq-amp Count"; break;
case 228: szName = "Power-off Retract Count"; break;
case 230: szName = "Head Amplitude"; break;
case 231: szName = "Temperature Celsius"; break;
case 240: szName = "Head Flying Hours"; break;
case 250: szName = "Read Error Retry Rate"; break;
default: szName = "Unknown Attribute"; break;
}
return szName;
}
/****************************************************************************
*
* DoPrintData
*
* FUNCTION: Display the SMART Attributes and Thresholds
*
****************************************************************************/
CString DoPrintData(PCHAR pAttrBuffer, PCHAR pThrsBuffer, BYTE bDriveNum)
{
int i;
PDRIVEATTRIBUTE pDA;
PATTRTHRESHOLD pAT;
BYTE Attr;
CString Result;
//
// Print the drive number
//
char Temp[512]="";
sprintf(Temp,"\r\nData for Drive Number %d\n", bDriveNum);
Result+=Temp;
//
// Print the revisions of the data structures
//
sprintf(Temp, "Attribute Structure Revision Threshold Structure Revision\r\n");
Result+=Temp;
sprintf(Temp," %d %d\r\n\r\n",
(WORD)pAttrBuffer[0],
(WORD)pThrsBuffer[0]);
Result+=Temp;
//
// Print the header and loop through the structures, printing
// the structures when the attribute ID is known.
//
sprintf(Temp, " -Attribute Name- -Attribute Value- -Threshold Value- -Raw Value-\r\n");
Result+=Temp;
pDA = (PDRIVEATTRIBUTE)&pAttrBuffer[2];
pAT = (PATTRTHRESHOLD)&pThrsBuffer[2];
for (i = 0; i < NUM_ATTRIBUTE_STRUCTS; i++)
{
Attr = pDA->bAttrID;
char szOut[64] = {0};
PrintSmartAttribRawValue(szOut, pDA);
if (Attr)
{
sprintf(Temp,"%2X %-29s%d%20c%d %s\r\n",
pDA->bAttrID,
GetSmartAttribName(pDA->bAttrID),
pDA->bAttrValue,
' ',
pAT->bWarrantyThreshold, szOut);
Result+=Temp;
}
pDA++;
pAT++;
}
return Result;
}
|
|
|
|
|
hi, im getting 102 errors in the file SysInfoDefs.cpp
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(7) : error C2065: 'SENDCMDOUTPARAMS' : undeclared identifier
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(14) : error C2061: syntax error : identifier 'PSENDCMDINPARAMS'
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(22) : error C2065: 'PSENDCMDINPARAMS' : undeclared identifier
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(695) : error C2065: 'DRIVE_LAYOUT_INFORMATION_EX' : undeclared identifier
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(695) : error C2146: syntax error : missing ';' before identifier 'dli'
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(695) : error C2065: 'dli' : undeclared identifier
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(709) : error C2065: 'IOCTL_DISK_GET_DRIVE_LAYOUT_EX' : undeclared identifier
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(718) : error C2228: left of '.PartitionCount' must have class/struct/union type
D:\Programming\game programming\LEARNING\MFC\1\SysInfoDefs.cpp(721) : error C2228: left of '.PartitionCount' must have class/struct/union type
etc...
what could be wrong? thx
|
|
|
|
|
As I said in previous messages, you must have the latest Platform SDK (PSDK) and also must included before MFC header file definitions.
Best regards,
A. Riazi
|
|
|
|
|
hi all,
this is a great app. however, i noticed that for windows xp, the o.s. query returns windows 2000. is there a way to modify the program, so it will return xp as well?
|
|
|
|
|
You need to modify the source codes a little. See the header definitions.
Best regards,
A. Riazi
|
|
|
|
|
amir,
what would the IsWindowsXP function look like. what particular settings would distinguish it???? i know that it is in the windows nt family.
|
|
|
|
|
Hi,
I'm Abbas not Amir! The build number is useful for distinguish the Windows XP OS. I used another article from CP (Author: PJ Naughter) to wrote it.
Best regards,
A. Riazi
|
|
|
|
|
The current code seems to be unable to get centrino cpu speed. I have a 1.5GHz, and the returned CPU speed always varies from 500MHz to 1000MHz. What's scoop? Also, a 1.5GHz centrino is said equivalent to 2.4GHz regular cpu(more or less). How do we formally reflect this in the cpu speed?
|
|
|
|
|
I think it is because centrino cpu's have 'SpeedStep'. E.g. their speed changes depending on load.
|
|
|
|
|