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

  1. /******************************************************************
  2. PhysicalMedia.CPP -- WMI provider class implementation
  3. Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved
  4. ******************************************************************/
  5. #include "Precomp.h"
  6. #include <setupapi.h>
  7. #include <devioctl.h>
  8. #include <ntddscsi.h>
  9. #include <ntdddisk.h>
  10. #include <strsafe.h>
  11. #include "PhysicalMedia.h"
  12. #include <scopeguard.h>
  13. CPhysicalMedia MyPhysicalMediaSettings (
  14. PROVIDER_NAME_PHYSICALMEDIA,
  15. L"root\\cimv2"
  16. ) ;
  17. /*****************************************************************************
  18. *
  19. * FUNCTION : CPhysicalMedia::CPhysicalMedia
  20. *
  21. * DESCRIPTION : Constructor
  22. *
  23. *****************************************************************************/
  24. CPhysicalMedia :: CPhysicalMedia (
  25. LPCWSTR lpwszName,
  26. LPCWSTR lpwszNameSpace
  27. ) : Provider ( lpwszName , lpwszNameSpace )
  28. {
  29. }
  30. /*****************************************************************************
  31. *
  32. * FUNCTION : CPhysicalMedia::~CPhysicalMedia
  33. *
  34. * DESCRIPTION : Destructor
  35. *
  36. *****************************************************************************/
  37. CPhysicalMedia :: ~CPhysicalMedia ()
  38. {
  39. }
  40. /*****************************************************************************
  41. *
  42. * FUNCTION : CPhysicalMedia::EnumerateInstances
  43. *
  44. * DESCRIPTION : Returns all the instances of this class.
  45. *
  46. *****************************************************************************/
  47. HRESULT CPhysicalMedia :: EnumerateInstances (
  48. MethodContext *pMethodContext,
  49. long lFlags
  50. )
  51. {
  52. HRESULT hRes = WBEM_S_NO_ERROR;
  53. hRes = Enumerate ( pMethodContext );
  54. return hRes;
  55. }
  56. /*****************************************************************************
  57. *
  58. * FUNCTION : CPhysicalMedia::GetObject
  59. *
  60. * DESCRIPTION : Find a single instance based on the key properties for the
  61. * class.
  62. *
  63. *****************************************************************************/
  64. HRESULT CPhysicalMedia :: GetObject (
  65. CInstance *pInstance,
  66. long lFlags ,
  67. CFrameworkQuery &Query
  68. )
  69. {
  70. #if NTONLY
  71. HRESULT hRes = WBEM_S_NO_ERROR;
  72. CHString t_DriveName;
  73. if ( pInstance->GetCHString ( TAG, t_DriveName ) )
  74. {
  75. BOOL bFound = FALSE;
  76. int uPos;
  77. //Find the drive number
  78. for ( WCHAR ch = L'0'; ch <= L'9'; ch++ )
  79. {
  80. uPos = t_DriveName.Find ( ch );
  81. if ( uPos != -1 )
  82. {
  83. bFound= TRUE;
  84. break;
  85. }
  86. }
  87. if ( bFound )
  88. {
  89. DWORD dwAccess;
  90. #if NTONLY >= 5
  91. dwAccess = GENERIC_READ | GENERIC_WRITE;
  92. #else
  93. dwAccess = GENERIC_READ;
  94. #endif
  95. int len = t_DriveName.GetLength();
  96. CHString t_DriveNo ( t_DriveName.Right ( len - uPos ));
  97. BYTE bDriveNo = ( BYTE )_wtoi ( (LPCTSTR)t_DriveNo );
  98. SmartCloseHandle hDiskHandle = CreateFile (
  99. t_DriveName.GetBuffer(0),
  100. dwAccess,
  101. FILE_SHARE_READ | FILE_SHARE_WRITE,
  102. NULL,
  103. OPEN_EXISTING,
  104. FILE_ATTRIBUTE_NORMAL,
  105. NULL
  106. ) ;
  107. DWORD dwErr = GetLastError () ;
  108. if ( hDiskHandle != INVALID_HANDLE_VALUE )
  109. {
  110. CHString t_SerialNumber;
  111. hRes = GetSmartVersion ( hDiskHandle, bDriveNo, t_SerialNumber );
  112. if ( SUCCEEDED ( hRes ) && (t_SerialNumber.GetLength() > 0) )
  113. {
  114. pInstance->SetCHString ( SERIALNUMBER, t_SerialNumber );
  115. }
  116. else
  117. {
  118. hRes = GetSCSIVersion(
  119. hDiskHandle,
  120. bDriveNo,
  121. t_SerialNumber);
  122. if(SUCCEEDED(hRes))
  123. {
  124. pInstance->SetCHString(SERIALNUMBER, t_SerialNumber);
  125. }
  126. else
  127. {
  128. hRes = WBEM_E_NOT_FOUND;
  129. }
  130. }
  131. }
  132. else
  133. {
  134. hRes = WBEM_E_NOT_FOUND;
  135. }
  136. }
  137. else
  138. {
  139. hRes = WBEM_E_NOT_FOUND;
  140. }
  141. }
  142. else
  143. {
  144. hRes = WBEM_E_INVALID_PARAMETER;
  145. }
  146. return hRes;
  147. #else
  148. return WBEM_E_NOT_SUPPORTED;
  149. #endif
  150. }
  151. /*****************************************************************************
  152. *
  153. * FUNCTION : CPhysicalMedia::GetObject
  154. *
  155. * DESCRIPTION : Enumerates all the Instances
  156. *
  157. *****************************************************************************/
  158. HRESULT CPhysicalMedia::Enumerate(
  159. MethodContext *pMethodContext
  160. )
  161. {
  162. HRESULT hRes = WBEM_S_NO_ERROR;
  163. HDEVINFO t_DeviceInfo = SetupDiGetClassDevs (
  164. &DiskClassGuid,
  165. NULL,
  166. NULL,
  167. DIGCF_PRESENT | DIGCF_INTERFACEDEVICE
  168. );
  169. if ( t_DeviceInfo == NULL )
  170. {
  171. return WBEM_E_CRITICAL_ERROR ;
  172. }
  173. //
  174. // auto destructor when leaving function scope
  175. //
  176. ON_BLOCK_EXIT ( SetupDiDestroyDeviceInfoList, t_DeviceInfo ) ;
  177. SP_DEVICE_INTERFACE_DATA t_DeviceInterfaceData ;
  178. t_DeviceInterfaceData.cbSize = sizeof ( t_DeviceInterfaceData ) ;
  179. ULONG t_SizeDeviceInterfaceDetail = sizeof ( SP_DEVICE_INTERFACE_DETAIL_DATA ) + ( MAX_PATH * sizeof( WCHAR ) ) ;
  180. PSP_DEVICE_INTERFACE_DETAIL_DATA t_DeviceInterfaceDetail = ( PSP_DEVICE_INTERFACE_DETAIL_DATA ) LocalAlloc ( 0 , t_SizeDeviceInterfaceDetail );
  181. if ( t_DeviceInterfaceDetail == NULL)
  182. {
  183. return WBEM_E_OUT_OF_MEMORY ;
  184. }
  185. //
  186. // auto destructor when leaving function scope
  187. //
  188. ON_BLOCK_EXIT ( LocalFree, t_DeviceInterfaceDetail ) ;
  189. t_DeviceInterfaceDetail->cbSize = sizeof ( SP_DEVICE_INTERFACE_DETAIL_DATA ) ;
  190. ULONG t_Index = 0 ;
  191. while ( true )
  192. {
  193. BOOL t_Status = SetupDiEnumDeviceInterfaces (
  194. t_DeviceInfo ,
  195. NULL ,
  196. & DiskClassGuid ,
  197. t_Index ,
  198. & t_DeviceInterfaceData
  199. ) ;
  200. if ( ! t_Status )
  201. {
  202. break;
  203. }
  204. t_Status = SetupDiGetDeviceInterfaceDetail (
  205. t_DeviceInfo ,
  206. & t_DeviceInterfaceData ,
  207. t_DeviceInterfaceDetail ,
  208. t_SizeDeviceInterfaceDetail ,
  209. NULL ,
  210. NULL
  211. ) ;
  212. if ( ! t_Status )
  213. {
  214. continue ;
  215. }
  216. SmartCloseHandle hDiskHandle = CreateFile (
  217. t_DeviceInterfaceDetail->DevicePath ,
  218. FILE_ANY_ACCESS ,
  219. FILE_SHARE_READ | FILE_SHARE_WRITE ,
  220. NULL,
  221. OPEN_EXISTING,
  222. FILE_ATTRIBUTE_NORMAL,
  223. NULL
  224. ) ;
  225. if ( hDiskHandle != INVALID_HANDLE_VALUE )
  226. {
  227. STORAGE_DEVICE_NUMBER t_DeviceNumber ;
  228. DWORD t_Bytes = 0 ;
  229. BOOL t_Status = DeviceIoControl (
  230. hDiskHandle ,
  231. IOCTL_STORAGE_GET_DEVICE_NUMBER ,
  232. NULL ,
  233. 0 ,
  234. & t_DeviceNumber ,
  235. sizeof ( t_DeviceNumber ),
  236. & t_Bytes ,
  237. NULL
  238. );
  239. if ( t_Status )
  240. {
  241. // Maximum size of integer plus preamble.
  242. wchar_t t_DiskSpec [ MAX_PATH ] ;
  243. StringCchPrintf ( t_DiskSpec , MAX_PATH , L"\\\\.\\PHYSICALDRIVE%lu" , ( DWORD )t_DeviceNumber.DeviceNumber ) ;
  244. CInstancePtr pInstance ( CreateNewInstance ( pMethodContext ) , false ) ;
  245. if ( SUCCEEDED (GetPhysDiskInfoNT ( pInstance, t_DiskSpec , t_DeviceNumber.DeviceNumber ) ) )
  246. {
  247. hRes = pInstance->Commit () ;
  248. }
  249. }
  250. }
  251. t_Index ++ ;
  252. }
  253. return hRes;
  254. }
  255. /*****************************************************************************
  256. *
  257. * FUNCTION : CPhysicalMedia::GetPhysDiskInfoNT
  258. *
  259. * DESCRIPTION : Gets the serial Id
  260. *
  261. *****************************************************************************/
  262. HRESULT CPhysicalMedia::GetPhysDiskInfoNT (
  263. CInstance *pInstance,
  264. LPCWSTR lpwszDiskSpec,
  265. BYTE bIndex
  266. )
  267. {
  268. #ifdef NTONLY
  269. HRESULT hRes = WBEM_E_NOT_FOUND ;
  270. DWORD dwAccess;
  271. #if NTONLY >= 5
  272. dwAccess = GENERIC_READ | GENERIC_WRITE;
  273. #else
  274. dwAccess = GENERIC_READ;
  275. #endif
  276. // Get handle to physical drive
  277. //=============================
  278. pInstance->SetCHString ( TAG , lpwszDiskSpec) ;
  279. SmartCloseHandle hDiskHandle = CreateFile (
  280. lpwszDiskSpec,
  281. dwAccess,
  282. FILE_SHARE_READ | FILE_SHARE_WRITE,
  283. NULL,
  284. OPEN_EXISTING,
  285. FILE_ATTRIBUTE_NORMAL,
  286. NULL
  287. ) ;
  288. if ( hDiskHandle != INVALID_HANDLE_VALUE )
  289. {
  290. CHString t_SerialNumber;
  291. hRes = GetSmartVersion ( hDiskHandle, bIndex, t_SerialNumber );
  292. if ( SUCCEEDED ( hRes ) && (t_SerialNumber.GetLength() > 0))
  293. {
  294. pInstance->SetCHString ( SERIALNUMBER, t_SerialNumber );
  295. }
  296. else
  297. {
  298. hRes = GetSCSIVersion(
  299. hDiskHandle,
  300. bIndex,
  301. t_SerialNumber);
  302. if ( SUCCEEDED ( hRes ) && (t_SerialNumber.GetLength() > 0))
  303. {
  304. pInstance->SetCHString(SERIALNUMBER, t_SerialNumber);
  305. }
  306. }
  307. }
  308. return ( hRes );
  309. #else
  310. return WBEM_E_NOT_SUPPORTED;
  311. #endif
  312. }
  313. /*****************************************************************************
  314. *
  315. * FUNCTION : CPhysicalMedia::GetIdentifyData
  316. *
  317. * DESCRIPTION : Gets the Serial Number
  318. *
  319. *****************************************************************************/
  320. HRESULT CPhysicalMedia::GetIdentifyData( HANDLE hDrive, BYTE bDriveNumber, BYTE bDfpDriveMap, BYTE bIDCmd, CHString &t_SerialNumber )
  321. {
  322. HRESULT hRes = WBEM_S_NO_ERROR;
  323. SENDCMDINPARAMS inputParams;
  324. BYTE outputParams[sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE];
  325. ULONG bytesReturned;
  326. BOOL success = TRUE;
  327. ZeroMemory(&inputParams, sizeof(SENDCMDINPARAMS));
  328. ZeroMemory(&outputParams, sizeof(outputParams));
  329. // Build register structure to enable smart functionality.
  330. inputParams.irDriveRegs.bFeaturesReg = 0;
  331. inputParams.irDriveRegs.bSectorCountReg = 1;
  332. inputParams.irDriveRegs.bSectorNumberReg = 1;
  333. inputParams.irDriveRegs.bCylLowReg = 0;
  334. inputParams.irDriveRegs.bCylHighReg = 0;
  335. inputParams.irDriveRegs.bDriveHeadReg = 0xA0 | (( bDriveNumber & 1) << 4);
  336. inputParams.irDriveRegs.bCommandReg = bIDCmd;
  337. inputParams.bDriveNumber = bDriveNumber;
  338. inputParams.cBufferSize = IDENTIFY_BUFFER_SIZE;
  339. success = DeviceIoControl (hDrive,
  340. SMART_RCV_DRIVE_DATA,
  341. (LPVOID)&inputParams,
  342. sizeof(SENDCMDINPARAMS) - 1,
  343. (LPVOID) &outputParams,
  344. sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE,
  345. &bytesReturned,
  346. NULL);
  347. if ( success )
  348. {
  349. PIDSECTOR pids = (PIDSECTOR) ((PSENDCMDOUTPARAMS)&outputParams)->bBuffer;
  350. ChangeByteOrder( pids->sSerialNumber,
  351. sizeof pids->sSerialNumber);
  352. CHAR sSerialNumber[21];
  353. memset(sSerialNumber, 0, sizeof(sSerialNumber));
  354. memcpy(sSerialNumber, pids->sSerialNumber, sizeof(pids->sSerialNumber));
  355. t_SerialNumber = sSerialNumber;
  356. }
  357. if ( GetLastError() != 0 )
  358. {
  359. hRes = WBEM_E_FAILED;
  360. }
  361. return hRes;
  362. }
  363. /*****************************************************************************
  364. *
  365. * FUNCTION : CPhysicalMedia::EnableSmart
  366. *
  367. * DESCRIPTION : Enables Smart IOCTL
  368. *
  369. *****************************************************************************/
  370. HRESULT CPhysicalMedia::EnableSmart( HANDLE hDrive, BYTE bDriveNum, BYTE & bDfpDriveMap )
  371. {
  372. SENDCMDINPARAMS inputParams;
  373. SENDCMDOUTPARAMS outputParams;
  374. ULONG bytesReturned;
  375. BOOL success = TRUE;
  376. ZeroMemory(&inputParams, sizeof(SENDCMDINPARAMS));
  377. ZeroMemory(&outputParams, sizeof(SENDCMDOUTPARAMS));
  378. //
  379. // Build register structure to enable smart functionality.
  380. //
  381. inputParams.irDriveRegs.bFeaturesReg = ENABLE_SMART;
  382. inputParams.irDriveRegs.bSectorCountReg = 1;
  383. inputParams.irDriveRegs.bSectorNumberReg = 1;
  384. inputParams.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
  385. inputParams.irDriveRegs.bCylHighReg = SMART_CYL_HI;
  386. //set DRV to Master or Slave
  387. inputParams.irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
  388. inputParams.irDriveRegs.bCommandReg = SMART_CMD;
  389. inputParams.bDriveNumber = bDriveNum;
  390. success = DeviceIoControl ( hDrive,
  391. SMART_SEND_DRIVE_COMMAND,
  392. &inputParams,
  393. sizeof(SENDCMDINPARAMS) - 1 ,
  394. &outputParams,
  395. sizeof(SENDCMDOUTPARAMS) - 1,
  396. &bytesReturned,
  397. NULL);
  398. if ( success )
  399. {
  400. bDfpDriveMap |= (1 << bDriveNum);
  401. }
  402. HRESULT hRes = WBEM_S_NO_ERROR;
  403. if ( GetLastError() != ERROR_SUCCESS )
  404. {
  405. hRes = WBEM_E_FAILED;
  406. }
  407. return ( hRes );
  408. }
  409. /*****************************************************************************
  410. *
  411. * FUNCTION : CPhysicalMedia::GetSmartVersion
  412. *
  413. * DESCRIPTION : Gets a Smart Version
  414. *
  415. *****************************************************************************/
  416. HRESULT CPhysicalMedia::GetSmartVersion(
  417. HANDLE Handle,
  418. BYTE bDriveNumber,
  419. CHString &a_SerialNumber
  420. )
  421. {
  422. GETVERSIONINPARAMS versionIn;
  423. ULONG bytesReturned;
  424. HRESULT hRes = WBEM_S_NO_ERROR;
  425. ZeroMemory(&versionIn, sizeof(GETVERSIONINPARAMS));
  426. //
  427. // Send the IOCTL to retrieve the version information.
  428. //
  429. BOOL bSuccess = DeviceIoControl (Handle,
  430. SMART_GET_VERSION,
  431. NULL,
  432. 0,
  433. &versionIn,
  434. sizeof(GETVERSIONINPARAMS),
  435. &bytesReturned,
  436. NULL);
  437. if ( bSuccess )
  438. {
  439. // If there is a IDE device at number "i" issue commands
  440. // to the device.
  441. //
  442. if (versionIn.bIDEDeviceMap >> bDriveNumber & 1)
  443. {
  444. //
  445. // Try to enable SMART so we can tell if a drive supports it.
  446. // Ignore ATAPI devices.
  447. //
  448. if (!(versionIn.bIDEDeviceMap >> bDriveNumber & 0x10))
  449. {
  450. BYTE bDfpDriveMap;
  451. hRes = EnableSmart( Handle, bDriveNumber, bDfpDriveMap );
  452. if ( SUCCEEDED ( hRes ) )
  453. {
  454. BYTE bIDCmd;
  455. bIDCmd = (versionIn.bIDEDeviceMap >> bDriveNumber & 0x10) ? IDE_ATAPI_ID : IDE_ID_FUNCTION;
  456. hRes = GetIdentifyData( Handle, bDriveNumber, bDfpDriveMap, bIDCmd, a_SerialNumber );
  457. if ( GetLastError () != ERROR_SUCCESS )
  458. {
  459. hRes = WBEM_E_FAILED;
  460. }
  461. }
  462. }
  463. }
  464. }
  465. return hRes;
  466. }
  467. /*****************************************************************************
  468. *
  469. * FUNCTION : CPhysicalMedia::GetSCSIVersion
  470. *
  471. * DESCRIPTION : Gets a Smart Version
  472. *
  473. *****************************************************************************/
  474. HRESULT CPhysicalMedia::GetSCSIVersion(
  475. HANDLE h,
  476. BYTE bDriveNumber,
  477. CHString &a_SerialNumber)
  478. {
  479. HRESULT hr = WBEM_S_NO_ERROR;
  480. PSTORAGE_DEVICE_DESCRIPTOR psdd = NULL;
  481. STORAGE_PROPERTY_QUERY spq;
  482. ULONG ulBytesReturned = 0L;
  483. spq.PropertyId = StorageDeviceProperty;
  484. spq.QueryType = PropertyStandardQuery;
  485. spq.AdditionalParameters[0] = 0;
  486. try
  487. {
  488. psdd = (PSTORAGE_DEVICE_DESCRIPTOR) new BYTE[sizeof(STORAGE_DEVICE_DESCRIPTOR) + 2048];
  489. if(psdd)
  490. {
  491. ZeroMemory(psdd, sizeof(STORAGE_DEVICE_DESCRIPTOR) + 2048);
  492. // Send the IOCTL to retrieve the serial number information.
  493. BOOL fSuccess = DeviceIoControl(
  494. h,
  495. IOCTL_STORAGE_QUERY_PROPERTY,
  496. &spq,
  497. sizeof(STORAGE_PROPERTY_QUERY),
  498. psdd,
  499. sizeof(STORAGE_DEVICE_DESCRIPTOR) + 2046,
  500. &ulBytesReturned,
  501. NULL);
  502. if(fSuccess)
  503. {
  504. if(ulBytesReturned > 0 && psdd->SerialNumberOffset != 0 && psdd->SerialNumberOffset != -1)
  505. {
  506. LPBYTE lpBaseAddres = (LPBYTE) psdd;
  507. LPBYTE lpSerialNumber = lpBaseAddres + psdd->SerialNumberOffset;
  508. if(*lpSerialNumber)
  509. {
  510. a_SerialNumber = (LPSTR)lpSerialNumber;
  511. }
  512. }
  513. }
  514. else
  515. {
  516. hr = WinErrorToWBEMhResult(::GetLastError());
  517. }
  518. delete psdd;
  519. psdd = NULL;
  520. }
  521. else
  522. {
  523. hr = WBEM_E_OUT_OF_MEMORY;
  524. }
  525. }
  526. catch(...)
  527. {
  528. if(psdd)
  529. {
  530. delete psdd;
  531. psdd = NULL;
  532. }
  533. }
  534. return hr;
  535. }
  536. /*****************************************************************************
  537. *
  538. * FUNCTION : CPhysicalMedia::ChangeByteOrder
  539. *
  540. * DESCRIPTION : Changes the byte order for extracting the Serial Number
  541. * for Smart IOCTL
  542. *
  543. *****************************************************************************/
  544. void CPhysicalMedia::ChangeByteOrder(char *szString, USHORT uscStrSize)
  545. {
  546. USHORT i;
  547. char temp;
  548. for (i = 0; i < uscStrSize; i+=2)
  549. {
  550. temp = szString[i];
  551. szString[i] = szString[i+1];
  552. szString[i+1] = temp;
  553. }
  554. }