Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

676 lines
17 KiB

/******************************************************************
PhysicalMedia.CPP -- WMI provider class implementation
Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved
******************************************************************/
#include "Precomp.h"
#include <setupapi.h>
#include <devioctl.h>
#include <ntddscsi.h>
#include <ntdddisk.h>
#include <strsafe.h>
#include "PhysicalMedia.h"
#include <scopeguard.h>
CPhysicalMedia MyPhysicalMediaSettings (
PROVIDER_NAME_PHYSICALMEDIA,
L"root\\cimv2"
) ;
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::CPhysicalMedia
*
* DESCRIPTION : Constructor
*
*****************************************************************************/
CPhysicalMedia :: CPhysicalMedia (
LPCWSTR lpwszName,
LPCWSTR lpwszNameSpace
) : Provider ( lpwszName , lpwszNameSpace )
{
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::~CPhysicalMedia
*
* DESCRIPTION : Destructor
*
*****************************************************************************/
CPhysicalMedia :: ~CPhysicalMedia ()
{
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::EnumerateInstances
*
* DESCRIPTION : Returns all the instances of this class.
*
*****************************************************************************/
HRESULT CPhysicalMedia :: EnumerateInstances (
MethodContext *pMethodContext,
long lFlags
)
{
HRESULT hRes = WBEM_S_NO_ERROR;
hRes = Enumerate ( pMethodContext );
return hRes;
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::GetObject
*
* DESCRIPTION : Find a single instance based on the key properties for the
* class.
*
*****************************************************************************/
HRESULT CPhysicalMedia :: GetObject (
CInstance *pInstance,
long lFlags ,
CFrameworkQuery &Query
)
{
#if NTONLY
HRESULT hRes = WBEM_S_NO_ERROR;
CHString t_DriveName;
if ( pInstance->GetCHString ( TAG, t_DriveName ) )
{
BOOL bFound = FALSE;
int uPos;
//Find the drive number
for ( WCHAR ch = L'0'; ch <= L'9'; ch++ )
{
uPos = t_DriveName.Find ( ch );
if ( uPos != -1 )
{
bFound= TRUE;
break;
}
}
if ( bFound )
{
DWORD dwAccess;
#if NTONLY >= 5
dwAccess = GENERIC_READ | GENERIC_WRITE;
#else
dwAccess = GENERIC_READ;
#endif
int len = t_DriveName.GetLength();
CHString t_DriveNo ( t_DriveName.Right ( len - uPos ));
BYTE bDriveNo = ( BYTE )_wtoi ( (LPCTSTR)t_DriveNo );
SmartCloseHandle hDiskHandle = CreateFile (
t_DriveName.GetBuffer(0),
dwAccess,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
) ;
DWORD dwErr = GetLastError () ;
if ( hDiskHandle != INVALID_HANDLE_VALUE )
{
CHString t_SerialNumber;
hRes = GetSmartVersion ( hDiskHandle, bDriveNo, t_SerialNumber );
if ( SUCCEEDED ( hRes ) && (t_SerialNumber.GetLength() > 0) )
{
pInstance->SetCHString ( SERIALNUMBER, t_SerialNumber );
}
else
{
hRes = GetSCSIVersion(
hDiskHandle,
bDriveNo,
t_SerialNumber);
if(SUCCEEDED(hRes))
{
pInstance->SetCHString(SERIALNUMBER, t_SerialNumber);
}
else
{
hRes = WBEM_E_NOT_FOUND;
}
}
}
else
{
hRes = WBEM_E_NOT_FOUND;
}
}
else
{
hRes = WBEM_E_NOT_FOUND;
}
}
else
{
hRes = WBEM_E_INVALID_PARAMETER;
}
return hRes;
#else
return WBEM_E_NOT_SUPPORTED;
#endif
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::GetObject
*
* DESCRIPTION : Enumerates all the Instances
*
*****************************************************************************/
HRESULT CPhysicalMedia::Enumerate(
MethodContext *pMethodContext
)
{
HRESULT hRes = WBEM_S_NO_ERROR;
HDEVINFO t_DeviceInfo = SetupDiGetClassDevs (
&DiskClassGuid,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE
);
if ( t_DeviceInfo == NULL )
{
return WBEM_E_CRITICAL_ERROR ;
}
//
// auto destructor when leaving function scope
//
ON_BLOCK_EXIT ( SetupDiDestroyDeviceInfoList, t_DeviceInfo ) ;
SP_DEVICE_INTERFACE_DATA t_DeviceInterfaceData ;
t_DeviceInterfaceData.cbSize = sizeof ( t_DeviceInterfaceData ) ;
ULONG t_SizeDeviceInterfaceDetail = sizeof ( SP_DEVICE_INTERFACE_DETAIL_DATA ) + ( MAX_PATH * sizeof( WCHAR ) ) ;
PSP_DEVICE_INTERFACE_DETAIL_DATA t_DeviceInterfaceDetail = ( PSP_DEVICE_INTERFACE_DETAIL_DATA ) LocalAlloc ( 0 , t_SizeDeviceInterfaceDetail );
if ( t_DeviceInterfaceDetail == NULL)
{
return WBEM_E_OUT_OF_MEMORY ;
}
//
// auto destructor when leaving function scope
//
ON_BLOCK_EXIT ( LocalFree, t_DeviceInterfaceDetail ) ;
t_DeviceInterfaceDetail->cbSize = sizeof ( SP_DEVICE_INTERFACE_DETAIL_DATA ) ;
ULONG t_Index = 0 ;
while ( true )
{
BOOL t_Status = SetupDiEnumDeviceInterfaces (
t_DeviceInfo ,
NULL ,
& DiskClassGuid ,
t_Index ,
& t_DeviceInterfaceData
) ;
if ( ! t_Status )
{
break;
}
t_Status = SetupDiGetDeviceInterfaceDetail (
t_DeviceInfo ,
& t_DeviceInterfaceData ,
t_DeviceInterfaceDetail ,
t_SizeDeviceInterfaceDetail ,
NULL ,
NULL
) ;
if ( ! t_Status )
{
continue ;
}
SmartCloseHandle hDiskHandle = CreateFile (
t_DeviceInterfaceDetail->DevicePath ,
FILE_ANY_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
) ;
if ( hDiskHandle != INVALID_HANDLE_VALUE )
{
STORAGE_DEVICE_NUMBER t_DeviceNumber ;
DWORD t_Bytes = 0 ;
BOOL t_Status = DeviceIoControl (
hDiskHandle ,
IOCTL_STORAGE_GET_DEVICE_NUMBER ,
NULL ,
0 ,
& t_DeviceNumber ,
sizeof ( t_DeviceNumber ),
& t_Bytes ,
NULL
);
if ( t_Status )
{
// Maximum size of integer plus preamble.
wchar_t t_DiskSpec [ MAX_PATH ] ;
StringCchPrintf ( t_DiskSpec , MAX_PATH , L"\\\\.\\PHYSICALDRIVE%lu" , ( DWORD )t_DeviceNumber.DeviceNumber ) ;
CInstancePtr pInstance ( CreateNewInstance ( pMethodContext ) , false ) ;
if ( SUCCEEDED (GetPhysDiskInfoNT ( pInstance, t_DiskSpec , t_DeviceNumber.DeviceNumber ) ) )
{
hRes = pInstance->Commit () ;
}
}
}
t_Index ++ ;
}
return hRes;
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::GetPhysDiskInfoNT
*
* DESCRIPTION : Gets the serial Id
*
*****************************************************************************/
HRESULT CPhysicalMedia::GetPhysDiskInfoNT (
CInstance *pInstance,
LPCWSTR lpwszDiskSpec,
BYTE bIndex
)
{
#ifdef NTONLY
HRESULT hRes = WBEM_E_NOT_FOUND ;
DWORD dwAccess;
#if NTONLY >= 5
dwAccess = GENERIC_READ | GENERIC_WRITE;
#else
dwAccess = GENERIC_READ;
#endif
// Get handle to physical drive
//=============================
pInstance->SetCHString ( TAG , lpwszDiskSpec) ;
SmartCloseHandle hDiskHandle = CreateFile (
lpwszDiskSpec,
dwAccess,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
) ;
if ( hDiskHandle != INVALID_HANDLE_VALUE )
{
CHString t_SerialNumber;
hRes = GetSmartVersion ( hDiskHandle, bIndex, t_SerialNumber );
if ( SUCCEEDED ( hRes ) && (t_SerialNumber.GetLength() > 0))
{
pInstance->SetCHString ( SERIALNUMBER, t_SerialNumber );
}
else
{
hRes = GetSCSIVersion(
hDiskHandle,
bIndex,
t_SerialNumber);
if ( SUCCEEDED ( hRes ) && (t_SerialNumber.GetLength() > 0))
{
pInstance->SetCHString(SERIALNUMBER, t_SerialNumber);
}
}
}
return ( hRes );
#else
return WBEM_E_NOT_SUPPORTED;
#endif
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::GetIdentifyData
*
* DESCRIPTION : Gets the Serial Number
*
*****************************************************************************/
HRESULT CPhysicalMedia::GetIdentifyData( HANDLE hDrive, BYTE bDriveNumber, BYTE bDfpDriveMap, BYTE bIDCmd, CHString &t_SerialNumber )
{
HRESULT hRes = WBEM_S_NO_ERROR;
SENDCMDINPARAMS inputParams;
BYTE outputParams[sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE];
ULONG bytesReturned;
BOOL success = TRUE;
ZeroMemory(&inputParams, sizeof(SENDCMDINPARAMS));
ZeroMemory(&outputParams, sizeof(outputParams));
// Build register structure to enable smart functionality.
inputParams.irDriveRegs.bFeaturesReg = 0;
inputParams.irDriveRegs.bSectorCountReg = 1;
inputParams.irDriveRegs.bSectorNumberReg = 1;
inputParams.irDriveRegs.bCylLowReg = 0;
inputParams.irDriveRegs.bCylHighReg = 0;
inputParams.irDriveRegs.bDriveHeadReg = 0xA0 | (( bDriveNumber & 1) << 4);
inputParams.irDriveRegs.bCommandReg = bIDCmd;
inputParams.bDriveNumber = bDriveNumber;
inputParams.cBufferSize = IDENTIFY_BUFFER_SIZE;
success = DeviceIoControl (hDrive,
SMART_RCV_DRIVE_DATA,
(LPVOID)&inputParams,
sizeof(SENDCMDINPARAMS) - 1,
(LPVOID) &outputParams,
sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE,
&bytesReturned,
NULL);
if ( success )
{
PIDSECTOR pids = (PIDSECTOR) ((PSENDCMDOUTPARAMS)&outputParams)->bBuffer;
ChangeByteOrder( pids->sSerialNumber,
sizeof pids->sSerialNumber);
CHAR sSerialNumber[21];
memset(sSerialNumber, 0, sizeof(sSerialNumber));
memcpy(sSerialNumber, pids->sSerialNumber, sizeof(pids->sSerialNumber));
t_SerialNumber = sSerialNumber;
}
if ( GetLastError() != 0 )
{
hRes = WBEM_E_FAILED;
}
return hRes;
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::EnableSmart
*
* DESCRIPTION : Enables Smart IOCTL
*
*****************************************************************************/
HRESULT CPhysicalMedia::EnableSmart( HANDLE hDrive, BYTE bDriveNum, BYTE & bDfpDriveMap )
{
SENDCMDINPARAMS inputParams;
SENDCMDOUTPARAMS outputParams;
ULONG bytesReturned;
BOOL success = TRUE;
ZeroMemory(&inputParams, sizeof(SENDCMDINPARAMS));
ZeroMemory(&outputParams, sizeof(SENDCMDOUTPARAMS));
//
// Build register structure to enable smart functionality.
//
inputParams.irDriveRegs.bFeaturesReg = ENABLE_SMART;
inputParams.irDriveRegs.bSectorCountReg = 1;
inputParams.irDriveRegs.bSectorNumberReg = 1;
inputParams.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
inputParams.irDriveRegs.bCylHighReg = SMART_CYL_HI;
//set DRV to Master or Slave
inputParams.irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
inputParams.irDriveRegs.bCommandReg = SMART_CMD;
inputParams.bDriveNumber = bDriveNum;
success = DeviceIoControl ( hDrive,
SMART_SEND_DRIVE_COMMAND,
&inputParams,
sizeof(SENDCMDINPARAMS) - 1 ,
&outputParams,
sizeof(SENDCMDOUTPARAMS) - 1,
&bytesReturned,
NULL);
if ( success )
{
bDfpDriveMap |= (1 << bDriveNum);
}
HRESULT hRes = WBEM_S_NO_ERROR;
if ( GetLastError() != ERROR_SUCCESS )
{
hRes = WBEM_E_FAILED;
}
return ( hRes );
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::GetSmartVersion
*
* DESCRIPTION : Gets a Smart Version
*
*****************************************************************************/
HRESULT CPhysicalMedia::GetSmartVersion(
HANDLE Handle,
BYTE bDriveNumber,
CHString &a_SerialNumber
)
{
GETVERSIONINPARAMS versionIn;
ULONG bytesReturned;
HRESULT hRes = WBEM_S_NO_ERROR;
ZeroMemory(&versionIn, sizeof(GETVERSIONINPARAMS));
//
// Send the IOCTL to retrieve the version information.
//
BOOL bSuccess = DeviceIoControl (Handle,
SMART_GET_VERSION,
NULL,
0,
&versionIn,
sizeof(GETVERSIONINPARAMS),
&bytesReturned,
NULL);
if ( bSuccess )
{
// If there is a IDE device at number "i" issue commands
// to the device.
//
if (versionIn.bIDEDeviceMap >> bDriveNumber & 1)
{
//
// Try to enable SMART so we can tell if a drive supports it.
// Ignore ATAPI devices.
//
if (!(versionIn.bIDEDeviceMap >> bDriveNumber & 0x10))
{
BYTE bDfpDriveMap;
hRes = EnableSmart( Handle, bDriveNumber, bDfpDriveMap );
if ( SUCCEEDED ( hRes ) )
{
BYTE bIDCmd;
bIDCmd = (versionIn.bIDEDeviceMap >> bDriveNumber & 0x10) ? IDE_ATAPI_ID : IDE_ID_FUNCTION;
hRes = GetIdentifyData( Handle, bDriveNumber, bDfpDriveMap, bIDCmd, a_SerialNumber );
if ( GetLastError () != ERROR_SUCCESS )
{
hRes = WBEM_E_FAILED;
}
}
}
}
}
return hRes;
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::GetSCSIVersion
*
* DESCRIPTION : Gets a Smart Version
*
*****************************************************************************/
HRESULT CPhysicalMedia::GetSCSIVersion(
HANDLE h,
BYTE bDriveNumber,
CHString &a_SerialNumber)
{
HRESULT hr = WBEM_S_NO_ERROR;
PSTORAGE_DEVICE_DESCRIPTOR psdd = NULL;
STORAGE_PROPERTY_QUERY spq;
ULONG ulBytesReturned = 0L;
spq.PropertyId = StorageDeviceProperty;
spq.QueryType = PropertyStandardQuery;
spq.AdditionalParameters[0] = 0;
try
{
psdd = (PSTORAGE_DEVICE_DESCRIPTOR) new BYTE[sizeof(STORAGE_DEVICE_DESCRIPTOR) + 2048];
if(psdd)
{
ZeroMemory(psdd, sizeof(STORAGE_DEVICE_DESCRIPTOR) + 2048);
// Send the IOCTL to retrieve the serial number information.
BOOL fSuccess = DeviceIoControl(
h,
IOCTL_STORAGE_QUERY_PROPERTY,
&spq,
sizeof(STORAGE_PROPERTY_QUERY),
psdd,
sizeof(STORAGE_DEVICE_DESCRIPTOR) + 2046,
&ulBytesReturned,
NULL);
if(fSuccess)
{
if(ulBytesReturned > 0 && psdd->SerialNumberOffset != 0 && psdd->SerialNumberOffset != -1)
{
LPBYTE lpBaseAddres = (LPBYTE) psdd;
LPBYTE lpSerialNumber = lpBaseAddres + psdd->SerialNumberOffset;
if(*lpSerialNumber)
{
a_SerialNumber = (LPSTR)lpSerialNumber;
}
}
}
else
{
hr = WinErrorToWBEMhResult(::GetLastError());
}
delete psdd;
psdd = NULL;
}
else
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
catch(...)
{
if(psdd)
{
delete psdd;
psdd = NULL;
}
}
return hr;
}
/*****************************************************************************
*
* FUNCTION : CPhysicalMedia::ChangeByteOrder
*
* DESCRIPTION : Changes the byte order for extracting the Serial Number
* for Smart IOCTL
*
*****************************************************************************/
void CPhysicalMedia::ChangeByteOrder(char *szString, USHORT uscStrSize)
{
USHORT i;
char temp;
for (i = 0; i < uscStrSize; i+=2)
{
temp = szString[i];
szString[i] = szString[i+1];
szString[i+1] = temp;
}
}