S
Sin Jeong-hun
Below is the code in Managed C++. It was originally written in C, and
posted somewhere around the Internet (I forgot where I copied this
code), and I changed it into Managed C++. This code returnes the
serial string like "WD-WC1234567" of the hard disk where C drive is
on.
Now, I would like to change this code into C#, but there are so many
API's, structures and macroes. I've searched the Internet for
equivalent C# code but I couldn't find a working one. Is there any
existing C# equivalent code, or do I need to stick to this MC++ code?
Thank you.
static String^ GetHddSerial()
{
String^ test=System::String::Empty;
LPCWSTR damn=L"\\\\.\\c:";
HANDLE hPhysicalDriveIOCTL = CreateFile(damn, GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
NULL);
if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
DWORD dwBytesReturned = 0;
//Get Physical Drive Information
VOLUME_DISK_EXTENTS vdExtents;
ZeroMemory(&vdExtents, sizeof(vdExtents));
if(!DeviceIoControl(hPhysicalDriveIOCTL,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0,
&vdExtents, sizeof(vdExtents), &dwBytesReturned, NULL))
{
CloseHandle(hPhysicalDriveIOCTL);
throw gcnew System::ApplicationException("Error volumes that
span multiple disks are not supported");
}
//Get SMART version information
GETVERSIONINPARAMS gvopVersionParams;
ZeroMemory(&gvopVersionParams, sizeof(gvopVersionParams));
if(!DeviceIoControl(hPhysicalDriveIOCTL, SMART_GET_VERSION,
NULL, 0,
&gvopVersionParams, sizeof(gvopVersionParams),
&dwBytesReturned, NULL))
{
CloseHandle(hPhysicalDriveIOCTL);
throw gcnew System::ApplicationException("Error cannot get
SMART version information from device");
}
if(gvopVersionParams.bIDEDeviceMap > 0)
{
//Setup SMART request
SENDCMDINPARAMS InParams = {
IDENTIFY_BUFFER_SIZE, { 0, 1, 1, 0, 0,
((vdExtents.Extents[0].DiskNumber & 1) ? 0xB0 : 0xA0),
((gvopVersionParams.bIDEDeviceMap >>
vdExtents.Extents[0].DiskNumber & 0x10) ? ATAPI_ID_CMD : ID_CMD) },
(BYTE)vdExtents.Extents[0].DiskNumber
};
DWORD dwBufSize = sizeof(SENDCMDOUTPARAMS) +
IDENTIFY_BUFFER_SIZE;
PSENDCMDOUTPARAMS pbtIDOutCmd = (PSENDCMDOUTPARAMS) new
BYTE[dwBufSize];
ZeroMemory(pbtIDOutCmd, dwBufSize);
//Get SMART information
if(DeviceIoControl(hPhysicalDriveIOCTL, SMART_RCV_DRIVE_DATA,
&InParams, sizeof(SENDCMDINPARAMS),
pbtIDOutCmd, dwBufSize, &dwBytesReturned, NULL))
{
//Little Endian To Big Endian
USHORT *pIDSector = (USHORT*)pbtIDOutCmd->bBuffer;
for(int nShort = 10; nShort < 21; nShort++)
pIDSector[nShort] = (((pIDSector[nShort] & 0x00FF) << 8) +
((pIDSector[nShort] & 0xFF00) >> 8));
//Get Drive Serial Number
LPSTR lpszSerialNumber1 = new CHAR[21];
ZeroMemory(lpszSerialNumber1, 21);
RtlCopyMemory(lpszSerialNumber1, &pIDSector[10], 20);
//Remove those horrible spaces caused because of endianess
//and print out the serial
LPSTR lpszSerialNumber2 = lpszSerialNumber1;
while(*lpszSerialNumber2 == ' ') lpszSerialNumber2++;
test= gcnew System::String(lpszSerialNumber2);
delete lpszSerialNumber1;
}
delete pbtIDOutCmd;
}
else
{
CloseHandle(hPhysicalDriveIOCTL);
throw gcnew System::ApplicationException("Unknown error");
}
CloseHandle (hPhysicalDriveIOCTL);
}
return test;
}
posted somewhere around the Internet (I forgot where I copied this
code), and I changed it into Managed C++. This code returnes the
serial string like "WD-WC1234567" of the hard disk where C drive is
on.
Now, I would like to change this code into C#, but there are so many
API's, structures and macroes. I've searched the Internet for
equivalent C# code but I couldn't find a working one. Is there any
existing C# equivalent code, or do I need to stick to this MC++ code?
Thank you.
static String^ GetHddSerial()
{
String^ test=System::String::Empty;
LPCWSTR damn=L"\\\\.\\c:";
HANDLE hPhysicalDriveIOCTL = CreateFile(damn, GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
NULL);
if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
DWORD dwBytesReturned = 0;
//Get Physical Drive Information
VOLUME_DISK_EXTENTS vdExtents;
ZeroMemory(&vdExtents, sizeof(vdExtents));
if(!DeviceIoControl(hPhysicalDriveIOCTL,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0,
&vdExtents, sizeof(vdExtents), &dwBytesReturned, NULL))
{
CloseHandle(hPhysicalDriveIOCTL);
throw gcnew System::ApplicationException("Error volumes that
span multiple disks are not supported");
}
//Get SMART version information
GETVERSIONINPARAMS gvopVersionParams;
ZeroMemory(&gvopVersionParams, sizeof(gvopVersionParams));
if(!DeviceIoControl(hPhysicalDriveIOCTL, SMART_GET_VERSION,
NULL, 0,
&gvopVersionParams, sizeof(gvopVersionParams),
&dwBytesReturned, NULL))
{
CloseHandle(hPhysicalDriveIOCTL);
throw gcnew System::ApplicationException("Error cannot get
SMART version information from device");
}
if(gvopVersionParams.bIDEDeviceMap > 0)
{
//Setup SMART request
SENDCMDINPARAMS InParams = {
IDENTIFY_BUFFER_SIZE, { 0, 1, 1, 0, 0,
((vdExtents.Extents[0].DiskNumber & 1) ? 0xB0 : 0xA0),
((gvopVersionParams.bIDEDeviceMap >>
vdExtents.Extents[0].DiskNumber & 0x10) ? ATAPI_ID_CMD : ID_CMD) },
(BYTE)vdExtents.Extents[0].DiskNumber
};
DWORD dwBufSize = sizeof(SENDCMDOUTPARAMS) +
IDENTIFY_BUFFER_SIZE;
PSENDCMDOUTPARAMS pbtIDOutCmd = (PSENDCMDOUTPARAMS) new
BYTE[dwBufSize];
ZeroMemory(pbtIDOutCmd, dwBufSize);
//Get SMART information
if(DeviceIoControl(hPhysicalDriveIOCTL, SMART_RCV_DRIVE_DATA,
&InParams, sizeof(SENDCMDINPARAMS),
pbtIDOutCmd, dwBufSize, &dwBytesReturned, NULL))
{
//Little Endian To Big Endian
USHORT *pIDSector = (USHORT*)pbtIDOutCmd->bBuffer;
for(int nShort = 10; nShort < 21; nShort++)
pIDSector[nShort] = (((pIDSector[nShort] & 0x00FF) << 8) +
((pIDSector[nShort] & 0xFF00) >> 8));
//Get Drive Serial Number
LPSTR lpszSerialNumber1 = new CHAR[21];
ZeroMemory(lpszSerialNumber1, 21);
RtlCopyMemory(lpszSerialNumber1, &pIDSector[10], 20);
//Remove those horrible spaces caused because of endianess
//and print out the serial
LPSTR lpszSerialNumber2 = lpszSerialNumber1;
while(*lpszSerialNumber2 == ' ') lpszSerialNumber2++;
test= gcnew System::String(lpszSerialNumber2);
delete lpszSerialNumber1;
}
delete pbtIDOutCmd;
}
else
{
CloseHandle(hPhysicalDriveIOCTL);
throw gcnew System::ApplicationException("Unknown error");
}
CloseHandle (hPhysicalDriveIOCTL);
}
return test;
}