Source code of Windows XP (NT5)
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.

3190 lines
71 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CPhysicalDisk.cpp
  7. //
  8. // Description:
  9. // This file contains the definition of the CPhysicalDisk
  10. // class.
  11. //
  12. // The class CPhysicalDisk represents a cluster manageable
  13. // device. It implements the IClusCfgManagedResourceInfo interface.
  14. //
  15. // Documentation:
  16. //
  17. // Header File:
  18. // CPhysicalDisk.h
  19. //
  20. // Maintained By:
  21. // Galen Barbee (GalenB) 23-FEB-2000
  22. //
  23. //////////////////////////////////////////////////////////////////////////////
  24. //////////////////////////////////////////////////////////////////////////////
  25. // Include Files
  26. //////////////////////////////////////////////////////////////////////////////
  27. #include "pch.h"
  28. #include "CPhysicalDisk.h"
  29. #include "CClusCfgPartitionInfo.h"
  30. #include <devioctl.h>
  31. #include <ntddstor.h>
  32. #include <ntddscsi.h>
  33. #include <ClusDisk.h>
  34. //////////////////////////////////////////////////////////////////////////////
  35. // Constant Definitions
  36. //////////////////////////////////////////////////////////////////////////////
  37. DEFINE_THISCLASS( "CPhysicalDisk" );
  38. //*************************************************************************//
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CPhysicalDisk class
  41. /////////////////////////////////////////////////////////////////////////////
  42. //////////////////////////////////////////////////////////////////////////////
  43. //++
  44. //
  45. // CPhysicalDisk::S_HrCreateInstance
  46. //
  47. // Description:
  48. // Create a CPhysicalDisk instance.
  49. //
  50. // Arguments:
  51. // None.
  52. //
  53. // Return Values:
  54. // Pointer to CPhysicalDisk instance.
  55. //
  56. //--
  57. //////////////////////////////////////////////////////////////////////////////
  58. HRESULT
  59. CPhysicalDisk::S_HrCreateInstance( IUnknown ** ppunkOut )
  60. {
  61. TraceFunc( "" );
  62. HRESULT hr;
  63. CPhysicalDisk * lpccs = NULL;
  64. if ( ppunkOut == NULL )
  65. {
  66. hr = THR( E_POINTER );
  67. goto Cleanup;
  68. } // if:
  69. lpccs = new CPhysicalDisk();
  70. if ( lpccs == NULL )
  71. {
  72. hr = THR( E_OUTOFMEMORY );
  73. goto Cleanup;
  74. } // if: error allocating object
  75. hr = THR( lpccs->HrInit() );
  76. if ( FAILED( hr ) )
  77. {
  78. goto Cleanup;
  79. } // if: HrInit() failed
  80. hr = THR( lpccs->TypeSafeQI( IUnknown, ppunkOut ) );
  81. Cleanup:
  82. if ( FAILED( hr ) )
  83. {
  84. LogMsg( L"[SRV] CPhysicalDisk::S_HrCreateInstance() failed. (hr = %#08x)", hr );
  85. } // if:
  86. if ( lpccs != NULL )
  87. {
  88. lpccs->Release();
  89. } // if:
  90. HRETURN( hr );
  91. } //*** CPhysicalDisk::S_HrCreateInstance
  92. //////////////////////////////////////////////////////////////////////////////
  93. //++
  94. //
  95. // CPhysicalDisk::CPhysicalDisk
  96. //
  97. // Description:
  98. // Constructor of the CPhysicalDisk class. This initializes
  99. // the m_cRef variable to 1 instead of 0 to account of possible
  100. // QueryInterface failure in DllGetClassObject.
  101. //
  102. // Arguments:
  103. // None.
  104. //
  105. // Return Value:
  106. // None.
  107. //
  108. // Remarks:
  109. // None.
  110. //
  111. //--
  112. //////////////////////////////////////////////////////////////////////////////
  113. CPhysicalDisk::CPhysicalDisk( void )
  114. : m_cRef( 1 )
  115. {
  116. TraceFunc( "" );
  117. // Increment the count of components in memory so the DLL hosting this
  118. // object cannot be unloaded.
  119. InterlockedIncrement( &g_cObjects );
  120. Assert( m_pIWbemServices == NULL );
  121. Assert( m_bstrName == NULL );
  122. Assert( m_bstrDeviceID == NULL );
  123. Assert( m_bstrDescription == NULL );
  124. Assert( m_idxNextPartition == 0 );
  125. Assert( m_ulSCSIBus == 0 );
  126. Assert( m_ulSCSITid == 0 );
  127. Assert( m_ulSCSIPort == 0 );
  128. Assert( m_ulSCSILun == 0 );
  129. Assert( m_idxEnumPartitionNext == 0 );
  130. Assert( m_prgPartitions == NULL );
  131. Assert( m_lcid == 0 );
  132. Assert( m_picccCallback == NULL );
  133. Assert( m_dwSignature == 0 );
  134. Assert( m_bstrFriendlyName == NULL );
  135. Assert( m_bstrFirmwareSerialNumber == NULL );
  136. Assert( !m_fIsManaged );
  137. Assert( m_cPartitions == 0 );
  138. TraceFuncExit();
  139. } //*** CPhysicalDisk::CPhysicalDisk
  140. //////////////////////////////////////////////////////////////////////////////
  141. //++
  142. //
  143. // CPhysicalDisk::~CPhysicalDisk
  144. //
  145. // Description:
  146. // Desstructor of the CPhysicalDisk class.
  147. //
  148. // Arguments:
  149. // None.
  150. //
  151. // Return Value:
  152. // None.
  153. //
  154. // Remarks:
  155. // None.
  156. //
  157. //--
  158. //////////////////////////////////////////////////////////////////////////////
  159. CPhysicalDisk::~CPhysicalDisk( void )
  160. {
  161. TraceFunc( "" );
  162. ULONG idx;
  163. TraceSysFreeString( m_bstrName );
  164. TraceSysFreeString( m_bstrDeviceID );
  165. TraceSysFreeString( m_bstrDescription );
  166. TraceSysFreeString( m_bstrFriendlyName );
  167. TraceSysFreeString( m_bstrFirmwareSerialNumber );
  168. for ( idx = 0; idx < m_idxNextPartition; idx++ )
  169. {
  170. ((*m_prgPartitions)[ idx ])->Release();
  171. } // for:
  172. TraceFree( m_prgPartitions );
  173. if ( m_pIWbemServices != NULL )
  174. {
  175. m_pIWbemServices->Release();
  176. } // if:
  177. if ( m_picccCallback != NULL )
  178. {
  179. m_picccCallback->Release();
  180. } // if:
  181. // There's going to be one less component in memory. Decrement component count.
  182. InterlockedDecrement( &g_cObjects );
  183. TraceFuncExit();
  184. } //*** CPhysicalDisk::~CPhysicalDisk
  185. //*************************************************************************//
  186. /////////////////////////////////////////////////////////////////////////////
  187. // CPhysicalDisk -- IUknkown interface.
  188. /////////////////////////////////////////////////////////////////////////////
  189. //////////////////////////////////////////////////////////////////////////////
  190. //++
  191. //
  192. // STDMETHODIMP_( ULONG )
  193. // CPhysicalDisk:: [IUNKNOWN] AddRef
  194. //
  195. // Description:
  196. // Increment the reference count of this object by one.
  197. //
  198. // Arguments:
  199. // None.
  200. //
  201. // Return Value:
  202. // The new reference count.
  203. //
  204. // Remarks:
  205. // None.
  206. //
  207. //--
  208. //////////////////////////////////////////////////////////////////////////////
  209. STDMETHODIMP_( ULONG )
  210. CPhysicalDisk::AddRef( void )
  211. {
  212. TraceFunc( "[IUnknown]" );
  213. InterlockedIncrement( & m_cRef );
  214. RETURN( m_cRef );
  215. } //*** CPhysicalDisk::AddRef
  216. //////////////////////////////////////////////////////////////////////////////
  217. //++
  218. //
  219. // STDMETHODIMP_( ULONG )
  220. // CPhysicalDisk:: [IUNKNOWN] Release
  221. //
  222. // Description:
  223. // Decrement the reference count of this object by one.
  224. //
  225. // Arguments:
  226. // None.
  227. //
  228. // Return Value:
  229. // The new reference count.
  230. //
  231. // Remarks:
  232. // None.
  233. //
  234. //--
  235. //////////////////////////////////////////////////////////////////////////////
  236. STDMETHODIMP_( ULONG )
  237. CPhysicalDisk::Release( void )
  238. {
  239. TraceFunc( "[IUnknown]" );
  240. LONG cRef;
  241. cRef = InterlockedDecrement( &m_cRef );
  242. if ( cRef == 0 )
  243. {
  244. TraceDo( delete this );
  245. } // if: reference count equal to zero
  246. RETURN( cRef );
  247. } //*** CPhysicalDisk::Release
  248. //////////////////////////////////////////////////////////////////////////////
  249. //++
  250. //
  251. // CPhysicalDisk:: [INKNOWN] QueryInterface
  252. //
  253. // Description:
  254. // Query this object for the passed in interface.
  255. //
  256. // Arguments:
  257. // IN REFIID riid,
  258. // Id of interface requested.
  259. //
  260. // OUT void ** ppv
  261. // Pointer to the requested interface.
  262. //
  263. // Return Value:
  264. // S_OK
  265. // If the interface is available on this object.
  266. //
  267. // E_NOINTERFACE
  268. // If the interface is not available.
  269. //
  270. // Remarks:
  271. // None.
  272. //
  273. //--
  274. //////////////////////////////////////////////////////////////////////////////
  275. STDMETHODIMP
  276. CPhysicalDisk::QueryInterface( REFIID riid, void ** ppv )
  277. {
  278. TraceQIFunc( riid, ppv );
  279. HRESULT hr = E_NOINTERFACE;
  280. if ( IsEqualIID( riid, IID_IUnknown ) )
  281. {
  282. *ppv = static_cast< IClusCfgManagedResourceInfo * >( this );
  283. hr = S_OK;
  284. } // if: IUnknown
  285. else if ( IsEqualIID( riid, IID_IClusCfgManagedResourceInfo ) )
  286. {
  287. *ppv = TraceInterface( __THISCLASS__, IClusCfgManagedResourceInfo, this, 0 );
  288. hr = S_OK;
  289. } // else if:
  290. else if ( IsEqualIID( riid, IID_IClusCfgWbemServices ) )
  291. {
  292. *ppv = TraceInterface( __THISCLASS__, IClusCfgWbemServices, this, 0 );
  293. hr = S_OK;
  294. } // else if:
  295. else if ( IsEqualIID( riid, IID_IClusCfgSetWbemObject ) )
  296. {
  297. *ppv = TraceInterface( __THISCLASS__, IClusCfgSetWbemObject, this, 0 );
  298. hr = S_OK;
  299. } // else if:
  300. else if ( IsEqualIID( riid, IID_IEnumClusCfgPartitions ) )
  301. {
  302. *ppv = TraceInterface( __THISCLASS__, IEnumClusCfgPartitions, this, 0 );
  303. hr = S_OK;
  304. } // else if:
  305. else if ( IsEqualIID( riid, IID_IClusCfgPhysicalDiskProperties ) )
  306. {
  307. *ppv = TraceInterface( __THISCLASS__, IClusCfgPhysicalDiskProperties, this, 0 );
  308. hr = S_OK;
  309. } // else if:
  310. else if ( IsEqualIID( riid, IID_IClusCfgInitialize ) )
  311. {
  312. *ppv = TraceInterface( __THISCLASS__, IClusCfgInitialize, this, 0 );
  313. hr = S_OK;
  314. } // else if:
  315. else if ( IsEqualIID( riid, IID_IClusCfgManagedResourceCfg ) )
  316. {
  317. *ppv = TraceInterface( __THISCLASS__, IClusCfgManagedResourceCfg, this, 0 );
  318. hr = S_OK;
  319. } // else if:
  320. if ( SUCCEEDED( hr ) )
  321. {
  322. ((IUnknown *) *ppv)->AddRef( );
  323. } // if: success
  324. QIRETURN_IGNORESTDMARSHALLING( hr, riid );
  325. } //*** CPhysicalDisk::QueryInterface
  326. //*************************************************************************//
  327. /////////////////////////////////////////////////////////////////////////////
  328. // CPhysicalDisk -- IClusCfgWbemServices interface.
  329. /////////////////////////////////////////////////////////////////////////////
  330. //////////////////////////////////////////////////////////////////////////////
  331. //++
  332. //
  333. // CPhysicalDisk::SetWbemServices
  334. //
  335. // Description:
  336. // Set the WBEM services provider.
  337. //
  338. // Arguments:
  339. // IN IWbemServices pIWbemServicesIn
  340. //
  341. // Return Value:
  342. // S_OK
  343. // Success
  344. //
  345. // E_POINTER
  346. // The pIWbemServicesIn param is NULL.
  347. //
  348. // Remarks:
  349. // None.
  350. //
  351. //--
  352. //////////////////////////////////////////////////////////////////////////////
  353. STDMETHODIMP
  354. CPhysicalDisk::SetWbemServices( IWbemServices * pIWbemServicesIn )
  355. {
  356. TraceFunc( "[IClusCfgWbemServices]" );
  357. HRESULT hr = S_OK;
  358. if ( pIWbemServicesIn == NULL )
  359. {
  360. hr = THR( E_POINTER );
  361. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_SetWbemServices_PhysDisk, IDS_ERROR_NULL_POINTER, hr );
  362. goto Cleanup;
  363. } // if:
  364. m_pIWbemServices = pIWbemServicesIn;
  365. m_pIWbemServices->AddRef();
  366. Cleanup:
  367. HRETURN( hr );
  368. } //*** CPhysicalDisk::SetWbemServices
  369. //*************************************************************************//
  370. /////////////////////////////////////////////////////////////////////////////
  371. // CPhysicalDisk -- IClusCfgInitialize interface.
  372. /////////////////////////////////////////////////////////////////////////////
  373. //////////////////////////////////////////////////////////////////////////////
  374. //++
  375. //
  376. // CPhysicalDisk::Initialize
  377. //
  378. // Description:
  379. // Initialize this component.
  380. //
  381. // Arguments:
  382. // IN IUknown * punkCallbackIn
  383. //
  384. // IN LCID lcidIn
  385. //
  386. // Return Value:
  387. // S_OK
  388. // Success
  389. //
  390. // Remarks:
  391. // None.
  392. //
  393. //--
  394. //////////////////////////////////////////////////////////////////////////////
  395. STDMETHODIMP
  396. CPhysicalDisk::Initialize(
  397. IUnknown * punkCallbackIn,
  398. LCID lcidIn
  399. )
  400. {
  401. TraceFunc( "[IClusCfgInitialize]" );
  402. Assert( m_picccCallback == NULL );
  403. HRESULT hr = S_OK;
  404. m_lcid = lcidIn;
  405. if ( punkCallbackIn == NULL )
  406. {
  407. hr = THR( E_POINTER );
  408. goto Cleanup;
  409. } // if:
  410. hr = THR( punkCallbackIn->TypeSafeQI( IClusCfgCallback, &m_picccCallback ) );
  411. Cleanup:
  412. HRETURN( hr );
  413. } //*** CPhysicalDisk::Initialize
  414. //*************************************************************************//
  415. /////////////////////////////////////////////////////////////////////////////
  416. // CPhysicalDisk -- IEnumClusCfgPartitions interface.
  417. /////////////////////////////////////////////////////////////////////////////
  418. //////////////////////////////////////////////////////////////////////////////
  419. //++
  420. //
  421. // CPhysicalDisk::Next
  422. //
  423. // Description:
  424. //
  425. //
  426. // Arguments:
  427. //
  428. // Return Value:
  429. // S_OK
  430. // Success
  431. //
  432. // E_POINTER
  433. // The rgpPartitionInfoOut param is NULL.
  434. //
  435. // Remarks:
  436. // None.
  437. //
  438. //--
  439. //////////////////////////////////////////////////////////////////////////////
  440. STDMETHODIMP
  441. CPhysicalDisk::Next(
  442. ULONG cNumberRequestedIn,
  443. IClusCfgPartitionInfo ** rgpPartitionInfoOut,
  444. ULONG * pcNumberFetchedOut
  445. )
  446. {
  447. TraceFunc( "[IEnumClusCfgPartitions]" );
  448. HRESULT hr = S_FALSE;
  449. ULONG cFetched = 0;
  450. ULONG idx;
  451. IClusCfgPartitionInfo * pccpi;
  452. if ( rgpPartitionInfoOut == NULL )
  453. {
  454. hr = THR( E_POINTER );
  455. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Next_PhysDisk, IDS_ERROR_NULL_POINTER, hr );
  456. goto Cleanup;
  457. } // if:
  458. if ( pcNumberFetchedOut != NULL )
  459. {
  460. *pcNumberFetchedOut = 0;
  461. } // if:
  462. if ( m_prgPartitions == NULL )
  463. {
  464. LOG_STATUS_REPORT1( TASKID_Minor_PhysDisk_No_Partitions, L"A physical disk does not have a partitions enumerator", hr );
  465. goto Cleanup;
  466. } // if:
  467. cFetched = min( cNumberRequestedIn, ( m_idxNextPartition - m_idxEnumPartitionNext ) );
  468. for ( idx = 0; idx < cFetched; idx++, m_idxEnumPartitionNext++ )
  469. {
  470. hr = THR( ((*m_prgPartitions)[ m_idxEnumPartitionNext ])->TypeSafeQI( IClusCfgPartitionInfo, &pccpi ) );
  471. if ( FAILED( hr ) )
  472. {
  473. LogMsg( L"[SRV] CPhysicalDisk::Next() could not query for IClusCfgPartitionInfo. (hr = %#08x)", hr );
  474. break;
  475. } // if:
  476. rgpPartitionInfoOut[ idx ] = pccpi;
  477. } // for:
  478. if ( FAILED( hr ) )
  479. {
  480. ULONG idxStop = idx;
  481. m_idxEnumPartitionNext -= idx;
  482. for ( idx = 0; idx < idxStop; idx++ )
  483. {
  484. (rgpPartitionInfoOut[ idx ])->Release();
  485. } // for:
  486. cFetched = 0;
  487. goto Cleanup;
  488. } // if:
  489. if ( pcNumberFetchedOut != NULL )
  490. {
  491. *pcNumberFetchedOut = cFetched;
  492. } // if:
  493. if ( cFetched < cNumberRequestedIn )
  494. {
  495. hr = S_FALSE;
  496. } // if:
  497. Cleanup:
  498. HRETURN( hr );
  499. } //*** CPhysicalDisk::Next
  500. //////////////////////////////////////////////////////////////////////////////
  501. //++
  502. //
  503. // CPhysicalDisk::Skip
  504. //
  505. // Description:
  506. //
  507. //
  508. // Arguments:
  509. //
  510. // Return Value:
  511. // S_OK
  512. // Success
  513. //
  514. // Remarks:
  515. // None.
  516. //
  517. //--
  518. //////////////////////////////////////////////////////////////////////////////
  519. STDMETHODIMP
  520. CPhysicalDisk::Skip( ULONG cNumberToSkipIn )
  521. {
  522. TraceFunc( "[IEnumClusCfgPartitions]" );
  523. HRESULT hr = S_OK;
  524. m_idxEnumPartitionNext += cNumberToSkipIn;
  525. if ( m_idxEnumPartitionNext > m_idxNextPartition )
  526. {
  527. m_idxEnumPartitionNext = m_idxNextPartition;
  528. hr = S_FALSE;
  529. } // if:
  530. HRETURN( hr );
  531. } //*** CPhysicalDisk::Skip
  532. //////////////////////////////////////////////////////////////////////////////
  533. //++
  534. //
  535. // CPhysicalDisk::Reset
  536. //
  537. // Description:
  538. //
  539. //
  540. // Arguments:
  541. //
  542. // Return Value:
  543. // S_OK
  544. // Success
  545. //
  546. // Remarks:
  547. // None.
  548. //
  549. //--
  550. //////////////////////////////////////////////////////////////////////////////
  551. STDMETHODIMP
  552. CPhysicalDisk::Reset( void )
  553. {
  554. TraceFunc( "[IEnumClusCfgPartitions]" );
  555. HRESULT hr = S_OK;
  556. m_idxEnumPartitionNext = 0;
  557. HRETURN( hr );
  558. } //*** CPhysicalDisk::Reset
  559. //////////////////////////////////////////////////////////////////////////////
  560. //++
  561. //
  562. // CPhysicalDisk::Clone
  563. //
  564. // Description:
  565. //
  566. //
  567. // Arguments:
  568. //
  569. // Return Value:
  570. // S_OK
  571. // Success
  572. //
  573. // E_POINTER
  574. // The ppEnumClusCfgPartitionsOut param is NULL.
  575. //
  576. // Remarks:
  577. // None.
  578. //
  579. //--
  580. //////////////////////////////////////////////////////////////////////////////
  581. STDMETHODIMP
  582. CPhysicalDisk::Clone( IEnumClusCfgPartitions ** ppEnumClusCfgPartitionsOut )
  583. {
  584. TraceFunc( "[IEnumClusCfgPartitions]" );
  585. HRESULT hr = S_OK;
  586. if ( ppEnumClusCfgPartitionsOut == NULL )
  587. {
  588. hr = THR( E_POINTER );
  589. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Clone_PhysDisk, IDS_ERROR_NULL_POINTER, hr );
  590. goto Cleanup;
  591. } // if:
  592. hr = THR( E_NOTIMPL );
  593. Cleanup:
  594. HRETURN( hr );
  595. } //*** CPhysicalDisk::Clone
  596. //////////////////////////////////////////////////////////////////////////////
  597. //++
  598. //
  599. // CPhysicalDisk::Count
  600. //
  601. // Description:
  602. //
  603. //
  604. // Arguments:
  605. //
  606. // Return Value:
  607. // S_OK
  608. // Success
  609. //
  610. // E_POINTER
  611. // The pnCountOut param is NULL.
  612. //
  613. // Remarks:
  614. // None.
  615. //
  616. //--
  617. //////////////////////////////////////////////////////////////////////////////
  618. STDMETHODIMP
  619. CPhysicalDisk::Count( DWORD * pnCountOut )
  620. {
  621. TraceFunc( "[IEnumClusCfgPartitions]" );
  622. HRESULT hr = THR( S_OK );
  623. if ( pnCountOut == NULL )
  624. {
  625. hr = THR( E_POINTER );
  626. goto Cleanup;
  627. } // if:
  628. *pnCountOut = m_cPartitions;
  629. Cleanup:
  630. HRETURN( hr );
  631. } //*** CPhysicalDisk::Count
  632. //*************************************************************************//
  633. /////////////////////////////////////////////////////////////////////////////
  634. // CPhysicalDisk -- IClusCfgSetWbemObject interface.
  635. /////////////////////////////////////////////////////////////////////////////
  636. //////////////////////////////////////////////////////////////////////////////
  637. //++
  638. //
  639. // CPhysicalDisk::SetWbemObject
  640. //
  641. // Description:
  642. // Set the disk information information provider.
  643. //
  644. // Arguments:
  645. //
  646. // Return Value:
  647. // S_OK
  648. // Success
  649. //
  650. // Remarks:
  651. // None.
  652. //
  653. //--
  654. //////////////////////////////////////////////////////////////////////////////
  655. STDMETHODIMP
  656. CPhysicalDisk::SetWbemObject(
  657. IWbemClassObject * pDiskIn
  658. , bool * pfRetainObjectOut
  659. )
  660. {
  661. TraceFunc( "[IClusCfgSetWbemObject]" );
  662. Assert( pDiskIn != NULL );
  663. Assert( pfRetainObjectOut != NULL );
  664. HRESULT hr = S_FALSE;
  665. VARIANT var;
  666. m_fIsQuorumCapable = TRUE;
  667. m_fIsQuorumJoinable = TRUE;
  668. VariantInit( &var );
  669. hr = THR( HrGetWMIProperty( pDiskIn, L"Name", VT_BSTR, &var ) );
  670. if ( FAILED( hr ) )
  671. {
  672. goto Cleanup;
  673. } // if:
  674. hr = THR( HrCreateFriendlyName( var.bstrVal ) );
  675. if ( FAILED( hr ) )
  676. {
  677. goto Cleanup;
  678. } // if:
  679. VariantClear( &var );
  680. hr = THR( HrGetWMIProperty( pDiskIn, L"DeviceID", VT_BSTR, &var ) );
  681. if ( FAILED( hr ) )
  682. {
  683. goto Cleanup;
  684. } // if:
  685. m_bstrDeviceID = TraceSysAllocString( var.bstrVal );
  686. if (m_bstrDeviceID == NULL )
  687. {
  688. goto OutOfMemory;
  689. } // if:
  690. VariantClear( &var );
  691. hr = THR( HrGetWMIProperty( pDiskIn, L"Description", VT_BSTR, &var ) );
  692. if ( FAILED( hr ) )
  693. {
  694. goto Cleanup;
  695. } // if:
  696. m_bstrDescription = TraceSysAllocString( var.bstrVal );
  697. if ( m_bstrDescription == NULL )
  698. {
  699. goto OutOfMemory;
  700. } // if:
  701. VariantClear( &var );
  702. hr = THR( HrGetWMIProperty( pDiskIn, L"SCSIBus", VT_I4, &var ) );
  703. if ( FAILED( hr ) )
  704. {
  705. goto Cleanup;
  706. } // if:
  707. m_ulSCSIBus = var.lVal;
  708. VariantClear( &var );
  709. hr = THR( HrGetWMIProperty( pDiskIn, L"SCSITargetId", VT_I4, &var ) );
  710. if ( FAILED( hr ) )
  711. {
  712. goto Cleanup;
  713. } // if:
  714. m_ulSCSITid = var.lVal;
  715. VariantClear( &var );
  716. hr = THR( HrGetWMIProperty( pDiskIn, L"SCSIPort", VT_I4, &var ) );
  717. if ( FAILED( hr ) )
  718. {
  719. goto Cleanup;
  720. } // if:
  721. m_ulSCSIPort = var.lVal;
  722. VariantClear( &var );
  723. hr = THR( HrGetWMIProperty( pDiskIn, L"SCSILogicalUnit", VT_I4, &var ) );
  724. if ( FAILED( hr ) )
  725. {
  726. goto Cleanup;
  727. } // if:
  728. m_ulSCSILun = var.lVal;
  729. VariantClear( &var );
  730. //
  731. // KB: 23-JUN-2000 GalenB
  732. //
  733. // Yucky code. Since we cannot read the signature for a clustered disk we have to handle the
  734. // empty property case properly.
  735. //
  736. hr = HrGetWMIProperty( pDiskIn, L"Signature", VT_I4, &var );
  737. if ( ( hr == E_PROPTYPEMISMATCH ) && ( var.vt == VT_NULL ) )
  738. {
  739. hr = S_OK;
  740. } // if: property is empty
  741. else if ( SUCCEEDED( hr ) )
  742. {
  743. m_dwSignature = (DWORD) var.lVal;
  744. } // else if:
  745. if ( FAILED( hr ) )
  746. {
  747. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_PhysDisk_Signature, IDS_ERROR_PHYSDISK_SIGNATURE, hr );
  748. THR( hr );
  749. goto Cleanup;
  750. } // if:
  751. VariantClear( &var );
  752. hr = STHR( HrGetPartitionInfo( pDiskIn, pfRetainObjectOut ) );
  753. if ( FAILED( hr ) )
  754. {
  755. goto Cleanup;
  756. } // if:
  757. //
  758. // KB: 28-JUL-2000 GalenB
  759. //
  760. // HrGetPartitionInfo() returns S_FALSE when it cannot get the partition info for a disk.
  761. // This is usually caused by the disk already being under ClusDisk control. This is not
  762. // and error, it just means we cannot query the partition or logical drive info.
  763. //
  764. if ( hr == S_OK )
  765. {
  766. hr = THR( HrCreateFriendlyName() );
  767. if ( FAILED( hr ) )
  768. {
  769. goto Cleanup;
  770. } // if:
  771. //
  772. // Since we have partition info we also have a signature and need to see if this
  773. // disk is cluster capable.
  774. hr = STHR( HrIsClusterCapable() );
  775. if ( FAILED( hr ) )
  776. {
  777. goto Cleanup;
  778. } // if:
  779. //
  780. // If the disk is not cluster capable then we don't want the enumerator
  781. // to keep it.
  782. //
  783. if ( hr == S_FALSE )
  784. {
  785. *pfRetainObjectOut = false;
  786. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_PhysDisk_Not_Cluster_Capable, IDS_INFO_PHYSDISK_NOT_CLUSTER_CAPABLE, m_bstrFriendlyName, hr );
  787. } // if:
  788. } // if:
  789. //
  790. // TODO: 15-MAR-2001 GalenB
  791. //
  792. // Need to check this error code when this feature is complete!
  793. //
  794. /*hr = */THR( HrGetDiskFirmwareSerialNumber() );
  795. // THR( HrGetDiskFirmwareVitalData() );
  796. goto Cleanup;
  797. OutOfMemory:
  798. hr = THR( E_OUTOFMEMORY );
  799. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_SetWbemObject_PhysDisk, IDS_ERROR_OUTOFMEMORY, hr );
  800. Cleanup:
  801. VariantClear( &var );
  802. HRETURN( hr );
  803. } //*** CPhysicalDisk::SetWbemObject
  804. //*************************************************************************//
  805. /////////////////////////////////////////////////////////////////////////////
  806. // CPhysicalDisk -- IClusCfgManagedResourceInfo interface.
  807. /////////////////////////////////////////////////////////////////////////////
  808. //////////////////////////////////////////////////////////////////////////////
  809. //++
  810. //
  811. // CPhysicalDisk::GetUID
  812. //
  813. // Description:
  814. //
  815. // Arguments:
  816. // pbstrUIDOut
  817. //
  818. // Return Value:
  819. //
  820. // Remarks:
  821. // None.
  822. //
  823. //--
  824. //////////////////////////////////////////////////////////////////////////////
  825. STDMETHODIMP
  826. CPhysicalDisk::GetUID( BSTR * pbstrUIDOut )
  827. {
  828. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  829. HRESULT hr = S_OK;
  830. WCHAR sz[ 256 ];
  831. if ( pbstrUIDOut == NULL )
  832. {
  833. hr = THR( E_POINTER );
  834. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_PhysDisk_GetUID_Pointer, IDS_ERROR_NULL_POINTER, hr );
  835. goto Cleanup;
  836. } // if:
  837. _snwprintf( sz, ARRAYSIZE( sz ), L"SCSI Tid %ld, SCSI Lun %ld", m_ulSCSITid, m_ulSCSILun );
  838. *pbstrUIDOut = SysAllocString( sz );
  839. if ( *pbstrUIDOut == NULL )
  840. {
  841. hr = THR( E_OUTOFMEMORY );
  842. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_PhysDisk_GetUID_Memory, IDS_ERROR_OUTOFMEMORY, hr );
  843. } // if:
  844. Cleanup:
  845. HRETURN( hr );
  846. } //*** CPhysicalDisk::GetUID
  847. //////////////////////////////////////////////////////////////////////////////
  848. //++
  849. //
  850. // CPhysicalDisk::GetName
  851. //
  852. // Description:
  853. //
  854. // Arguments:
  855. //
  856. // Return Value:
  857. //
  858. // Remarks:
  859. // None.
  860. //
  861. //--
  862. //////////////////////////////////////////////////////////////////////////////
  863. STDMETHODIMP
  864. CPhysicalDisk::GetName( BSTR * pbstrNameOut )
  865. {
  866. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  867. HRESULT hr = S_OK;
  868. if ( pbstrNameOut == NULL )
  869. {
  870. hr = THR( E_POINTER );
  871. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_GetName_Pointer, IDS_ERROR_NULL_POINTER, hr );
  872. goto Cleanup;
  873. } // if:
  874. //
  875. // Prefer the "friendly" name over the WMI name -- if we have it...
  876. //
  877. if ( m_bstrFriendlyName != NULL )
  878. {
  879. *pbstrNameOut = SysAllocString( m_bstrFriendlyName );
  880. } // if:
  881. else
  882. {
  883. *pbstrNameOut = SysAllocString( m_bstrName );
  884. } // else:
  885. if (*pbstrNameOut == NULL )
  886. {
  887. hr = THR( E_OUTOFMEMORY );
  888. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_GetName_Memory, IDS_ERROR_OUTOFMEMORY, hr );
  889. } // if:
  890. Cleanup:
  891. HRETURN( hr );
  892. } //*** CPhysicalDisk::GetName
  893. //////////////////////////////////////////////////////////////////////////////
  894. //++
  895. //
  896. // CPhysicalDisk::SetName
  897. //
  898. // Description:
  899. //
  900. // Arguments:
  901. //
  902. // Return Value:
  903. //
  904. // Remarks:
  905. // None.
  906. //
  907. //--
  908. //////////////////////////////////////////////////////////////////////////////
  909. STDMETHODIMP
  910. CPhysicalDisk::SetName( LPCWSTR pcszNameIn )
  911. {
  912. TraceFunc1( "[IClusCfgManagedResourceInfo] pcszNameIn = '%ws'", pcszNameIn == NULL ? L"<null>" : pcszNameIn );
  913. HRESULT hr = S_OK;
  914. BSTR bstr = NULL;
  915. if ( pcszNameIn == NULL )
  916. {
  917. hr = THR( E_INVALIDARG );
  918. goto Cleanup;
  919. } // if:
  920. bstr = TraceSysAllocString( pcszNameIn );
  921. if ( bstr == NULL )
  922. {
  923. hr = THR( E_OUTOFMEMORY );
  924. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_SetName_PhysDisk, IDS_ERROR_OUTOFMEMORY, hr );
  925. goto Cleanup;
  926. } // if:
  927. TraceSysFreeString( m_bstrName );
  928. m_bstrName = bstr;
  929. //
  930. // Since we got asked from the outside to set a new name, this should actually be reflected in
  931. // the friendly name, too, since that, ultimately, gets preference over the real name
  932. //
  933. hr = HrSetFriendlyName( pcszNameIn );
  934. Cleanup:
  935. HRETURN( hr );
  936. } //*** CPhysicalDisk::SetName
  937. //////////////////////////////////////////////////////////////////////////////
  938. //++
  939. //
  940. // CPhysicalDisk::IsManaged
  941. //
  942. // Description:
  943. //
  944. // Arguments:
  945. //
  946. // Return Value:
  947. // S_OK
  948. // The device is managed.
  949. //
  950. // S_FALSE
  951. // The device is not managed.
  952. //
  953. // Win32 error as HRESULT when an error occurs.
  954. //
  955. // Remarks:
  956. // None.
  957. //
  958. //--
  959. //////////////////////////////////////////////////////////////////////////////
  960. STDMETHODIMP
  961. CPhysicalDisk::IsManaged( void )
  962. {
  963. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  964. HRESULT hr = S_FALSE;
  965. if ( m_fIsManaged )
  966. {
  967. hr = S_OK;
  968. } // if:
  969. HRETURN( hr );
  970. } //*** CPhysicalDisk::IsManaged
  971. //////////////////////////////////////////////////////////////////////////////
  972. //++
  973. //
  974. // CPhysicalDisk::SetManaged
  975. //
  976. // Description:
  977. //
  978. // Arguments:
  979. // fIsManagedIn
  980. //
  981. // Return Value:
  982. //
  983. // Remarks:
  984. // None.
  985. //
  986. //--
  987. //////////////////////////////////////////////////////////////////////////////
  988. STDMETHODIMP
  989. CPhysicalDisk::SetManaged( BOOL fIsManagedIn )
  990. {
  991. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  992. HRESULT hr = S_OK;
  993. m_fIsManaged = fIsManagedIn;
  994. LOG_STATUS_REPORT_STRING2(
  995. L"Physical disk '%1!ws!' '%2!ws!"
  996. , ( m_bstrFriendlyName != NULL ) ? m_bstrFriendlyName : m_bstrName
  997. , fIsManagedIn ? L"is managed" : L"is not managed"
  998. , hr
  999. );
  1000. Cleanup:
  1001. HRETURN( hr );
  1002. } //*** CPhysicalDisk::SetManaged
  1003. //////////////////////////////////////////////////////////////////////////////
  1004. //++
  1005. //
  1006. // CPhysicalDisk::IsQuorumDevice
  1007. //
  1008. // Description:
  1009. //
  1010. // Arguments:
  1011. //
  1012. // Return Value:
  1013. // S_OK
  1014. // The device is the quorum device.
  1015. //
  1016. // S_FALSE
  1017. // The device is not the quorum device.
  1018. //
  1019. // Win32 error as HRESULT when an error occurs.
  1020. //
  1021. // Remarks:
  1022. // None.
  1023. //
  1024. //--
  1025. //////////////////////////////////////////////////////////////////////////////
  1026. STDMETHODIMP
  1027. CPhysicalDisk::IsQuorumDevice( void )
  1028. {
  1029. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1030. HRESULT hr = S_FALSE;
  1031. if ( m_fIsQuorumDevice )
  1032. {
  1033. hr = S_OK;
  1034. } // if:
  1035. LOG_STATUS_REPORT_STRING2(
  1036. L"Physical disk '%1!ws!' '%2!ws!' the quorum device."
  1037. , ( m_bstrFriendlyName != NULL ) ? m_bstrFriendlyName : m_bstrDeviceID
  1038. , m_fIsQuorumDevice ? L"is" : L"is not"
  1039. , hr
  1040. );
  1041. Cleanup:
  1042. HRETURN( hr );
  1043. } //*** CPhysicalDisk::IsQuorumDevice
  1044. //////////////////////////////////////////////////////////////////////////////
  1045. //++
  1046. //
  1047. // CPhysicalDisk::SetQuorumedDevice
  1048. //
  1049. // Description:
  1050. //
  1051. // Arguments:
  1052. //
  1053. // Return Value:
  1054. //
  1055. // Remarks:
  1056. // None.
  1057. //
  1058. //--
  1059. //////////////////////////////////////////////////////////////////////////////
  1060. STDMETHODIMP
  1061. CPhysicalDisk::SetQuorumedDevice( BOOL fIsQuorumDeviceIn )
  1062. {
  1063. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1064. HRESULT hr = S_OK;
  1065. m_fIsQuorumDevice = fIsQuorumDeviceIn;
  1066. LOG_STATUS_REPORT_STRING2(
  1067. L"Setting physical disk '%1!ws!' '%2!ws!' the quorum device."
  1068. , ( m_bstrFriendlyName != NULL ) ? m_bstrFriendlyName : m_bstrDeviceID
  1069. , m_fIsQuorumDevice ? L"to be" : L"to not be"
  1070. , hr
  1071. );
  1072. Cleanup:
  1073. HRETURN( hr );
  1074. } //*** CPhysicalDisk::SetQuorumedDevice
  1075. //////////////////////////////////////////////////////////////////////////////
  1076. //++
  1077. //
  1078. // CPhysicalDisk::IsQuorumCapable
  1079. //
  1080. // Description:
  1081. //
  1082. // Arguments:
  1083. //
  1084. // Return Value:
  1085. // S_OK
  1086. // The device is a quorum capable device.
  1087. //
  1088. // S_FALSE
  1089. // The device is not a quorum capable device.
  1090. //
  1091. // Win32 error as HRESULT when an error occurs.
  1092. //
  1093. // Remarks:
  1094. // None.
  1095. //
  1096. //--
  1097. //////////////////////////////////////////////////////////////////////////////
  1098. STDMETHODIMP
  1099. CPhysicalDisk::IsQuorumCapable( void )
  1100. {
  1101. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1102. HRESULT hr = S_FALSE;
  1103. if ( m_fIsQuorumCapable )
  1104. {
  1105. hr = S_OK;
  1106. } // if:
  1107. HRETURN( hr );
  1108. } //*** CPhysicalDisk::IsQuorumCapable
  1109. //////////////////////////////////////////////////////////////////////////////
  1110. //++
  1111. //
  1112. // CPhysicalDisk::GetDriveLetterMappings
  1113. //
  1114. // Description:
  1115. //
  1116. // Arguments:
  1117. //
  1118. // Return Value:
  1119. //
  1120. // Remarks:
  1121. // None.
  1122. //
  1123. //--
  1124. //////////////////////////////////////////////////////////////////////////////
  1125. STDMETHODIMP
  1126. CPhysicalDisk::GetDriveLetterMappings(
  1127. SDriveLetterMapping * pdlmDriveLetterMappingOut
  1128. )
  1129. {
  1130. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1131. HRESULT hr = S_FALSE;
  1132. IClusCfgPartitionInfo * piccpi = NULL;
  1133. ULONG idx;
  1134. if ( pdlmDriveLetterMappingOut == NULL )
  1135. {
  1136. hr = THR( E_POINTER );
  1137. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_GetDriveLetterMappings_PhysDisk, IDS_ERROR_NULL_POINTER, hr );
  1138. goto Cleanup;
  1139. } // if:
  1140. for ( idx = 0; idx < m_idxNextPartition; idx++ )
  1141. {
  1142. hr = ( ((*m_prgPartitions)[ idx ])->TypeSafeQI( IClusCfgPartitionInfo, &piccpi ) );
  1143. if ( FAILED( hr ) )
  1144. {
  1145. goto Cleanup;
  1146. } // if:
  1147. hr = STHR( piccpi->GetDriveLetterMappings( pdlmDriveLetterMappingOut ) );
  1148. if ( FAILED( hr ) )
  1149. {
  1150. goto Cleanup;
  1151. } // if:
  1152. piccpi->Release();
  1153. piccpi = NULL;
  1154. } // for:
  1155. Cleanup:
  1156. if ( piccpi != NULL )
  1157. {
  1158. piccpi->Release();
  1159. } // if:
  1160. HRETURN( hr );
  1161. } //*** CPhysicalDisk::GetDriveLetterMappings
  1162. //////////////////////////////////////////////////////////////////////////////
  1163. //++
  1164. //
  1165. // CPhysicalDisk::SetDriveLetterMappings
  1166. //
  1167. // Description:
  1168. //
  1169. // Arguments:
  1170. //
  1171. // Return Value:
  1172. //
  1173. // Remarks:
  1174. // None.
  1175. //
  1176. //--
  1177. //////////////////////////////////////////////////////////////////////////////
  1178. STDMETHODIMP
  1179. CPhysicalDisk::SetDriveLetterMappings(
  1180. SDriveLetterMapping dlmDriveLetterMappingIn
  1181. )
  1182. {
  1183. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1184. HRESULT hr = THR( E_NOTIMPL );
  1185. HRETURN( hr );
  1186. } //*** CPhysicalDisk::SetDriveLetterMappings
  1187. //////////////////////////////////////////////////////////////////////////////
  1188. //++
  1189. //
  1190. // CPhysicalDisk::IsDeviceJoinable
  1191. //
  1192. // Description:
  1193. //
  1194. // Arguments:
  1195. //
  1196. // Return Value:
  1197. // S_OK
  1198. // The quorumable device allows join.
  1199. //
  1200. // S_FALSE
  1201. // The device does not allow join.
  1202. //
  1203. // Win32 error as HRESULT when an error occurs.
  1204. //
  1205. // Remarks:
  1206. // None.
  1207. //
  1208. //--
  1209. //////////////////////////////////////////////////////////////////////////////
  1210. STDMETHODIMP
  1211. CPhysicalDisk::IsDeviceJoinable( void )
  1212. {
  1213. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1214. HRESULT hr = S_FALSE;
  1215. if ( m_fIsQuorumJoinable )
  1216. {
  1217. hr = S_OK;
  1218. } // if:
  1219. HRETURN( hr );
  1220. } //*** CPhysicalDisk::IsDeviceJoinable
  1221. //////////////////////////////////////////////////////////////////////////////
  1222. //++
  1223. //
  1224. // CPhysicalDisk::SetDeviceJoinable
  1225. //
  1226. // Description:
  1227. //
  1228. // Arguments:
  1229. //
  1230. // Return Value:
  1231. // S_OK
  1232. // The quorumable device allows join.
  1233. //
  1234. // S_FALSE
  1235. // The device does not allow join.
  1236. //
  1237. // Win32 error as HRESULT when an error occurs.
  1238. //
  1239. // Remarks:
  1240. // This function should never be called
  1241. //
  1242. //--
  1243. //////////////////////////////////////////////////////////////////////////////
  1244. STDMETHODIMP
  1245. CPhysicalDisk::SetDeviceJoinable( BOOL fIsJoinableIn )
  1246. {
  1247. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1248. HRETURN( THR( E_NOTIMPL ) );
  1249. } //*** CPhysicalDisk::IsDeviceJoinable
  1250. //*************************************************************************//
  1251. /////////////////////////////////////////////////////////////////////////////
  1252. // CPhysicalDisk class -- IClusCfgPhysicalDiskProperties Interface.
  1253. /////////////////////////////////////////////////////////////////////////////
  1254. //////////////////////////////////////////////////////////////////////////////
  1255. //++
  1256. //
  1257. // CPhysicalDisk::IsThisLogicalDisk
  1258. //
  1259. // Description:
  1260. //
  1261. // Arguments:
  1262. // None.
  1263. //
  1264. // Return Value:
  1265. //
  1266. //
  1267. // Remarks:
  1268. // None.
  1269. //
  1270. //--
  1271. //////////////////////////////////////////////////////////////////////////////
  1272. STDMETHODIMP
  1273. CPhysicalDisk::IsThisLogicalDisk( WCHAR cLogicalDiskIn )
  1274. {
  1275. TraceFunc( "[IClusCfgPhysicalDiskProperties]" );
  1276. HRESULT hr = S_FALSE;
  1277. ULONG idx;
  1278. IClusCfgPartitionProperties * piccpp = NULL;
  1279. for ( idx = 0; idx < m_idxNextPartition; idx++ )
  1280. {
  1281. hr = ( ((*m_prgPartitions)[ idx ])->TypeSafeQI( IClusCfgPartitionProperties, &piccpp ) );
  1282. if ( FAILED( hr ) )
  1283. {
  1284. goto Cleanup;
  1285. } // if:
  1286. hr = STHR( piccpp->IsThisLogicalDisk( cLogicalDiskIn ) );
  1287. if ( FAILED( hr ) )
  1288. {
  1289. goto Cleanup;
  1290. } // if:
  1291. if ( hr == S_OK )
  1292. {
  1293. break;
  1294. } // if:
  1295. piccpp->Release();
  1296. piccpp = NULL;
  1297. } // for:
  1298. Cleanup:
  1299. if ( piccpp != NULL )
  1300. {
  1301. piccpp->Release();
  1302. } // if:
  1303. HRETURN( hr );
  1304. } //*** CPhysicalDisk::IsThisLogicalDisk
  1305. //////////////////////////////////////////////////////////////////////////////
  1306. //++
  1307. //
  1308. // CPhysicalDisk::HrGetSCSIBus
  1309. //
  1310. // Description:
  1311. //
  1312. // Arguments:
  1313. // None.
  1314. //
  1315. // Return Value:
  1316. //
  1317. //
  1318. // Remarks:
  1319. // None.
  1320. //
  1321. //--
  1322. //////////////////////////////////////////////////////////////////////////////
  1323. STDMETHODIMP
  1324. CPhysicalDisk::HrGetSCSIBus( ULONG * pulSCSIBusOut )
  1325. {
  1326. TraceFunc( "[IClusCfgPhysicalDiskProperties]" );
  1327. HRESULT hr = S_OK;
  1328. if ( pulSCSIBusOut == NULL )
  1329. {
  1330. hr = THR( E_POINTER );
  1331. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetSCSIBus, IDS_ERROR_NULL_POINTER, hr );
  1332. goto Cleanup;
  1333. } // if:
  1334. *pulSCSIBusOut = m_ulSCSIBus;
  1335. Cleanup:
  1336. HRETURN( hr );
  1337. } //*** CPhysicalDisk::HrGetSCSIBus
  1338. //////////////////////////////////////////////////////////////////////////////
  1339. //++
  1340. //
  1341. // CPhysicalDisk::HrGetSCSIPort
  1342. //
  1343. // Description:
  1344. //
  1345. // Arguments:
  1346. // None.
  1347. //
  1348. // Return Value:
  1349. //
  1350. //
  1351. // Remarks:
  1352. // None.
  1353. //
  1354. //--
  1355. //////////////////////////////////////////////////////////////////////////////
  1356. STDMETHODIMP
  1357. CPhysicalDisk::HrGetSCSIPort( ULONG * pulSCSIPortOut )
  1358. {
  1359. TraceFunc( "[IClusCfgPhysicalDiskProperties]" );
  1360. HRESULT hr = S_OK;
  1361. if ( pulSCSIPortOut == NULL )
  1362. {
  1363. hr = THR( E_POINTER );
  1364. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetSCSIPort, IDS_ERROR_NULL_POINTER, hr );
  1365. goto Cleanup;
  1366. } // if:
  1367. *pulSCSIPortOut = m_ulSCSIPort;
  1368. Cleanup:
  1369. HRETURN( hr );
  1370. } //*** CPhysicalDisk::HrGetSCSIPort
  1371. //////////////////////////////////////////////////////////////////////////////
  1372. //++
  1373. //
  1374. // CPhysicalDisk::HrGetDeviceID
  1375. //
  1376. // Description:
  1377. //
  1378. // Arguments:
  1379. // None.
  1380. //
  1381. // Return Value:
  1382. //
  1383. //
  1384. // Remarks:
  1385. // None.
  1386. //
  1387. //--
  1388. //////////////////////////////////////////////////////////////////////////////
  1389. STDMETHODIMP
  1390. CPhysicalDisk::HrGetDeviceID( BSTR * pbstrDeviceIDOut )
  1391. {
  1392. TraceFunc( "" );
  1393. Assert( m_bstrDeviceID != NULL );
  1394. HRESULT hr = S_OK;
  1395. if ( pbstrDeviceIDOut == NULL )
  1396. {
  1397. hr = THR( E_POINTER );
  1398. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetDeviceID_Pointer, IDS_ERROR_NULL_POINTER, hr );
  1399. goto Cleanup;
  1400. } // if:
  1401. *pbstrDeviceIDOut = TraceSysAllocString( m_bstrDeviceID );
  1402. if ( *pbstrDeviceIDOut == NULL )
  1403. {
  1404. hr = THR( E_OUTOFMEMORY );
  1405. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetDeviceID_Memory, IDS_ERROR_OUTOFMEMORY, hr );
  1406. } // if:
  1407. Cleanup:
  1408. HRETURN( hr );
  1409. } //*** CPhysicalDisk::HrGetDeviceID
  1410. //////////////////////////////////////////////////////////////////////////////
  1411. //++
  1412. //
  1413. // CPhysicalDisk::HrGetSignature
  1414. //
  1415. // Description:
  1416. //
  1417. // Arguments:
  1418. // None.
  1419. //
  1420. // Return Value:
  1421. //
  1422. //
  1423. // Remarks:
  1424. // None.
  1425. //
  1426. //--
  1427. //////////////////////////////////////////////////////////////////////////////
  1428. STDMETHODIMP
  1429. CPhysicalDisk::HrGetSignature( DWORD * pdwSignatureOut )
  1430. {
  1431. TraceFunc( "" );
  1432. Assert( m_dwSignature != 0 );
  1433. HRESULT hr = S_OK;
  1434. if ( pdwSignatureOut == NULL )
  1435. {
  1436. hr = THR( E_POINTER );
  1437. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetSignature_Pointer, IDS_ERROR_NULL_POINTER, hr );
  1438. goto Cleanup;
  1439. } // if:
  1440. *pdwSignatureOut = m_dwSignature;
  1441. Cleanup:
  1442. HRETURN( hr );
  1443. } //*** CPhysicalDisk::HrGetSignature
  1444. //////////////////////////////////////////////////////////////////////////////
  1445. //++
  1446. //
  1447. // CPhysicalDisk::HrSetFriendlyName
  1448. //
  1449. // Description:
  1450. //
  1451. // Arguments:
  1452. //
  1453. // Return Value:
  1454. //
  1455. // Remarks:
  1456. // None.
  1457. //
  1458. //--
  1459. //////////////////////////////////////////////////////////////////////////////
  1460. STDMETHODIMP
  1461. CPhysicalDisk::HrSetFriendlyName( LPCWSTR pcszFriendlyNameIn )
  1462. {
  1463. TraceFunc1( "[IClusCfgManagedResourceInfo] pcszFriendlyNameIn = '%ws'", pcszFriendlyNameIn == NULL ? L"<null>" : pcszFriendlyNameIn );
  1464. HRESULT hr = S_OK;
  1465. BSTR bstr = NULL;
  1466. if ( pcszFriendlyNameIn == NULL )
  1467. {
  1468. hr = THR( E_INVALIDARG );
  1469. goto Cleanup;
  1470. } // if:
  1471. bstr = TraceSysAllocString( pcszFriendlyNameIn );
  1472. if ( bstr == NULL )
  1473. {
  1474. hr = THR( E_OUTOFMEMORY );
  1475. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrSetFriendlyName_PhysDisk, IDS_ERROR_OUTOFMEMORY, hr );
  1476. } // if:
  1477. TraceSysFreeString( m_bstrFriendlyName );
  1478. m_bstrFriendlyName = bstr;
  1479. Cleanup:
  1480. HRETURN( hr );
  1481. } //*** CPhysicalDisk::HrSetFriendlyName
  1482. //////////////////////////////////////////////////////////////////////////////
  1483. //++
  1484. //
  1485. // CPhysicalDisk::CanBeManaged
  1486. //
  1487. // Description:
  1488. //
  1489. // Arguments:
  1490. //
  1491. // Return Value:
  1492. // S_OK
  1493. // The device is managed.
  1494. //
  1495. // S_FALSE
  1496. // The device is not managed.
  1497. //
  1498. // Win32 error as HRESULT when an error occurs.
  1499. //
  1500. // Remarks:
  1501. // None.
  1502. //
  1503. //--
  1504. //////////////////////////////////////////////////////////////////////////////
  1505. STDMETHODIMP
  1506. CPhysicalDisk::CanBeManaged( void )
  1507. {
  1508. TraceFunc( "[IClusCfgPhysicalDiskProperties]" );
  1509. HRESULT hr = S_OK;
  1510. ULONG idx;
  1511. IClusCfgPartitionProperties * piccpp = NULL;
  1512. //
  1513. // KB: 12-JUN-2000 GalenB
  1514. //
  1515. // Turn off the managed state because this disk may already be managed by
  1516. // another node, or it may be RAW.
  1517. //
  1518. m_fIsManaged = FALSE;
  1519. //
  1520. // If this disk has no partitions then it may already be managed by
  1521. // another node, or it may be RAW.
  1522. //
  1523. if ( m_idxNextPartition == 0 )
  1524. {
  1525. hr = S_FALSE;
  1526. goto Cleanup;
  1527. } // if:
  1528. //
  1529. // A disk must have at least one NTFS partition in order to be a quorum device.
  1530. //
  1531. m_fIsQuorumCapable = FALSE;
  1532. m_fIsQuorumJoinable = FALSE;
  1533. LOG_STATUS_REPORT_STRING( L"Marking disk %1!ws! as not being quorum capable", ( m_bstrFriendlyName != NULL ) ? m_bstrFriendlyName : m_bstrName, hr );
  1534. //
  1535. // Enum the partitions and set the quorum capable flag if an NTFS partition is found.
  1536. //
  1537. for ( idx = 0; idx < m_idxNextPartition; idx++ )
  1538. {
  1539. hr = ( ((*m_prgPartitions)[ idx ])->TypeSafeQI( IClusCfgPartitionProperties, &piccpp ) );
  1540. if ( FAILED( hr ) )
  1541. {
  1542. goto Cleanup;
  1543. } // if:
  1544. hr = STHR( piccpp->IsNTFS() );
  1545. if ( hr == S_OK )
  1546. {
  1547. m_fIsQuorumCapable = TRUE;
  1548. m_fIsQuorumJoinable = TRUE;
  1549. m_fIsManaged = TRUE;
  1550. LOG_STATUS_REPORT_STRING( L"Marking disk %1!ws! as being quorum capable", ( m_bstrFriendlyName != NULL ) ? m_bstrFriendlyName : m_bstrName, hr );
  1551. break;
  1552. } // if:
  1553. piccpp->Release();
  1554. piccpp = NULL;
  1555. } // for:
  1556. Cleanup:
  1557. if ( FAILED( hr ) )
  1558. {
  1559. LogMsg( L"[SRV] CPhysicalDisk::CanBeManaged failed. (hr = %#08x)", hr );
  1560. } // if:
  1561. if ( piccpp != NULL )
  1562. {
  1563. piccpp->Release();
  1564. } // if:
  1565. HRETURN( hr );
  1566. } //*** CPhysicalDisk::CanBeManaged
  1567. //*************************************************************************//
  1568. /////////////////////////////////////////////////////////////////////////////
  1569. // CPhysicalDisk class -- IClusCfgManagedResourceCfg
  1570. /////////////////////////////////////////////////////////////////////////////
  1571. //////////////////////////////////////////////////////////////////////////////
  1572. //++
  1573. //
  1574. // CPhysicalDisk::PreCreate
  1575. //
  1576. // Description:
  1577. //
  1578. // Arguments:
  1579. //
  1580. // Return Value:
  1581. // S_OK
  1582. // Success
  1583. //
  1584. // Win32 error as HRESULT when an error occurs.
  1585. //
  1586. // Remarks:
  1587. // None.
  1588. //
  1589. //--
  1590. //////////////////////////////////////////////////////////////////////////////
  1591. STDMETHODIMP
  1592. CPhysicalDisk::PreCreate( IUnknown * punkServicesIn )
  1593. {
  1594. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1595. HRESULT hr = S_OK;
  1596. IClusCfgResourcePreCreate * pccrpc = NULL;
  1597. BSTR bstr = m_bstrFriendlyName != NULL ? m_bstrFriendlyName : m_bstrName;
  1598. hr = THR( punkServicesIn->TypeSafeQI( IClusCfgResourcePreCreate, &pccrpc ) );
  1599. if ( FAILED( hr ) )
  1600. {
  1601. goto Cleanup;
  1602. } // if:
  1603. hr = THR( pccrpc->SetType( (LPCLSID) &RESTYPE_PhysicalDisk ) );
  1604. if ( FAILED( hr ) )
  1605. {
  1606. goto Cleanup;
  1607. } // if:
  1608. hr = THR( pccrpc->SetClassType( (LPCLSID) &RESCLASSTYPE_StorageDevice ) );
  1609. if ( FAILED( hr ) )
  1610. {
  1611. goto Cleanup;
  1612. } // if:
  1613. #if 0 // test code only
  1614. hr = THR( pccrpc->SetDependency( (LPCLSID) &IID_NULL, dfSHARED ) );
  1615. if ( FAILED( hr ) )
  1616. {
  1617. goto Cleanup;
  1618. } // if:
  1619. #endif // test code only
  1620. Cleanup:
  1621. STATUS_REPORT_STRING( TASKID_Major_Configure_Resources, TASKID_Minor_PhysDisk_PreCreate, IDS_INFO_PHYSDISK_PRECREATE, bstr, hr );
  1622. if ( pccrpc != NULL )
  1623. {
  1624. pccrpc->Release();
  1625. } // if:
  1626. HRETURN( hr );
  1627. } //*** CPhysicalDisk::PreCreate
  1628. //////////////////////////////////////////////////////////////////////////////
  1629. //++
  1630. //
  1631. // CPhysicalDisk::Create
  1632. //
  1633. // Description:
  1634. //
  1635. // Arguments:
  1636. //
  1637. // Return Value:
  1638. // S_OK
  1639. // Success
  1640. //
  1641. // Win32 error as HRESULT when an error occurs.
  1642. //
  1643. // Remarks:
  1644. // None.
  1645. //
  1646. //--
  1647. //////////////////////////////////////////////////////////////////////////////
  1648. STDMETHODIMP
  1649. CPhysicalDisk::Create( IUnknown * punkServicesIn )
  1650. {
  1651. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1652. HRESULT hr = S_OK;
  1653. IClusCfgResourceCreate * pccrc = NULL;
  1654. BSTR bstr = m_bstrFriendlyName != NULL ? m_bstrFriendlyName : m_bstrName;
  1655. hr = THR( punkServicesIn->TypeSafeQI( IClusCfgResourceCreate, &pccrc ) );
  1656. if ( FAILED( hr ) )
  1657. {
  1658. goto Cleanup;
  1659. } // if:
  1660. if ( m_dwSignature != 0 )
  1661. {
  1662. hr = THR( pccrc->SetPropertyDWORD( L"Signature", m_dwSignature ) );
  1663. if ( FAILED( hr ) )
  1664. {
  1665. goto Cleanup;
  1666. } // if:
  1667. } // if:
  1668. Cleanup:
  1669. STATUS_REPORT_STRING( TASKID_Major_Configure_Resources, TASKID_Minor_PhysDisk_Create, IDS_INFO_PHYSDISK_CREATE, bstr, hr );
  1670. if ( pccrc != NULL )
  1671. {
  1672. pccrc->Release();
  1673. } // if:
  1674. HRETURN( hr );
  1675. } //*** CPhysicalDisk::Create
  1676. //////////////////////////////////////////////////////////////////////////////
  1677. //++
  1678. //
  1679. // CPhysicalDisk::PostCreate
  1680. //
  1681. // Description:
  1682. //
  1683. // Arguments:
  1684. //
  1685. // Return Value:
  1686. // S_OK
  1687. // Success
  1688. //
  1689. // Win32 error as HRESULT when an error occurs.
  1690. //
  1691. // Remarks:
  1692. // None.
  1693. //
  1694. //--
  1695. //////////////////////////////////////////////////////////////////////////////
  1696. STDMETHODIMP
  1697. CPhysicalDisk::PostCreate( IUnknown * punkServicesIn )
  1698. {
  1699. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1700. HRETURN( S_OK );
  1701. } //*** CPhysicalDisk::PostCreate
  1702. //////////////////////////////////////////////////////////////////////////////
  1703. //++
  1704. //
  1705. // CPhysicalDisk::Evict
  1706. //
  1707. // Description:
  1708. //
  1709. // Arguments:
  1710. //
  1711. // Return Value:
  1712. // S_OK
  1713. // Success
  1714. //
  1715. // Win32 error as HRESULT when an error occurs.
  1716. //
  1717. // Remarks:
  1718. // None.
  1719. //
  1720. //--
  1721. //////////////////////////////////////////////////////////////////////////////
  1722. STDMETHODIMP
  1723. CPhysicalDisk::Evict( IUnknown * punkServicesIn )
  1724. {
  1725. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1726. HRETURN( S_OK );
  1727. } //*** CPhysicalDisk::Evict
  1728. //*************************************************************************//
  1729. /////////////////////////////////////////////////////////////////////////////
  1730. // CPhysicalDisk class -- Private Methods.
  1731. /////////////////////////////////////////////////////////////////////////////
  1732. //////////////////////////////////////////////////////////////////////////////
  1733. //++
  1734. //
  1735. // CPhysicalDisk::HrInit
  1736. //
  1737. // Description:
  1738. // Initialize this component.
  1739. //
  1740. // Arguments:
  1741. // None.
  1742. //
  1743. // Return Value:
  1744. //
  1745. //
  1746. // Remarks:
  1747. // None.
  1748. //
  1749. //--
  1750. //////////////////////////////////////////////////////////////////////////////
  1751. HRESULT
  1752. CPhysicalDisk::HrInit( void )
  1753. {
  1754. TraceFunc( "" );
  1755. HRESULT hr = S_OK;
  1756. HRETURN( hr );
  1757. } //*** CPhysicalDisk::HrInit
  1758. //////////////////////////////////////////////////////////////////////////////
  1759. //++
  1760. //
  1761. // CPhysicalDisk::HrGetPartitionInfo
  1762. //
  1763. // Description:
  1764. // Gather the partition information.
  1765. //
  1766. // Arguments:
  1767. // None.
  1768. //
  1769. // Return Value:
  1770. //
  1771. //
  1772. // Remarks:
  1773. // None.
  1774. //
  1775. //--
  1776. //////////////////////////////////////////////////////////////////////////////
  1777. HRESULT
  1778. CPhysicalDisk::HrGetPartitionInfo(
  1779. IWbemClassObject * pDiskIn
  1780. , bool * pfRetainObjectOut
  1781. )
  1782. {
  1783. TraceFunc( "" );
  1784. Assert( pDiskIn != NULL );
  1785. Assert( pfRetainObjectOut != NULL );
  1786. HRESULT hr;
  1787. VARIANT var;
  1788. VARIANT varDiskName;
  1789. WCHAR szBuf[ 256 ];
  1790. IEnumWbemClassObject * pPartitions = NULL;
  1791. IWbemClassObject * pPartition = NULL;
  1792. ULONG ulReturned;
  1793. BSTR bstrQuery = NULL;
  1794. BSTR bstrWQL = NULL;
  1795. DWORD c;
  1796. bstrWQL = TraceSysAllocString( L"WQL" );
  1797. if ( bstrWQL == NULL )
  1798. {
  1799. goto OutOfMemory;
  1800. } // if:
  1801. VariantInit( &var );
  1802. VariantInit( &varDiskName );
  1803. //
  1804. // Need to enum the partition(s) of this disk to determine if it is booted
  1805. // bootable.
  1806. //
  1807. hr = THR( HrGetWMIProperty( pDiskIn, L"DeviceID", VT_BSTR, &var ) );
  1808. if ( FAILED( hr ) )
  1809. {
  1810. goto Cleanup;
  1811. } // if:
  1812. _snwprintf( szBuf,
  1813. ARRAYSIZE( szBuf ),
  1814. L"Associators of {Win32_DiskDrive.DeviceID='%s'} where AssocClass=Win32_DiskDriveToDiskPartition",
  1815. var.bstrVal
  1816. );
  1817. bstrQuery = TraceSysAllocString( szBuf );
  1818. if ( bstrQuery == NULL )
  1819. {
  1820. goto OutOfMemory;
  1821. } // if:
  1822. hr = THR( m_pIWbemServices->ExecQuery( bstrWQL, bstrQuery, WBEM_FLAG_FORWARD_ONLY, NULL, &pPartitions ) );
  1823. if ( FAILED( hr ) )
  1824. {
  1825. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_WMI_DiskDrivePartitions_Qry_Failed, IDS_ERROR_WMI_DISKDRIVEPARTITIONS_QRY_FAILED, var.bstrVal, hr );
  1826. goto Cleanup;
  1827. } // if:
  1828. for ( c = 0; ; c++ )
  1829. {
  1830. hr = STHR( pPartitions->Next( WBEM_INFINITE, 1, &pPartition, &ulReturned ) );
  1831. if ( ( hr == S_OK ) && ( ulReturned == 1 ) )
  1832. {
  1833. hr = STHR( HrIsPartitionLDM( pPartition ) );
  1834. if ( FAILED( hr ) )
  1835. {
  1836. goto Cleanup;
  1837. } // if:
  1838. //
  1839. // If the partition is logical disk manager (LDM) then we cannot accept this disk therefore cannot manage it.
  1840. //
  1841. if ( hr == S_OK )
  1842. {
  1843. hr = THR( HrGetWMIProperty( pDiskIn, L"Name", VT_BSTR, &varDiskName ) );
  1844. if ( FAILED( hr ) )
  1845. {
  1846. goto Cleanup;
  1847. } // if:
  1848. hr = S_FALSE;
  1849. *pfRetainObjectOut = false;
  1850. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_Partition_LDM_Disk, IDS_ERROR_LDM_DISK, varDiskName.bstrVal, hr );
  1851. goto Cleanup;
  1852. } // if:
  1853. hr = STHR( HrIsPartitionGPT( pPartition ) );
  1854. if ( FAILED( hr ) )
  1855. {
  1856. goto Cleanup;
  1857. } // if:
  1858. //
  1859. // If the partition is GPT then we cannot accept this disk therefore cannot manage it.
  1860. //
  1861. if ( hr == S_OK )
  1862. {
  1863. hr = THR( HrGetWMIProperty( pDiskIn, L"Name", VT_BSTR, &varDiskName ) );
  1864. if ( FAILED( hr ) )
  1865. {
  1866. goto Cleanup;
  1867. } // if:
  1868. hr = S_FALSE;
  1869. *pfRetainObjectOut = false;
  1870. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_Partition_GPT_Disk, IDS_ERROR_GPT_DISK, varDiskName.bstrVal, hr );
  1871. goto Cleanup;
  1872. } // if:
  1873. hr = THR( HrCreatePartitionInfo( pPartition ) );
  1874. if ( FAILED( hr ) )
  1875. {
  1876. goto Cleanup;
  1877. } // if:
  1878. pPartition->Release();
  1879. pPartition = NULL;
  1880. } // if:
  1881. else if ( ( hr == S_FALSE ) && ( ulReturned == 0 ) )
  1882. {
  1883. break;
  1884. } // else if:
  1885. else
  1886. {
  1887. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_WQL_Partition_Qry_Next_Failed, IDS_ERROR_WQL_QRY_NEXT_FAILED, bstrQuery, hr );
  1888. goto Cleanup;
  1889. } // else:
  1890. } // for:
  1891. //
  1892. // The enumerator can be empty because we cannot read the partition info from
  1893. // clustered disks. If the enumerator was empty retain the S_FALSE, otherwise
  1894. // return S_OK if count is greater than 0.
  1895. //
  1896. if ( c > 0 )
  1897. {
  1898. hr = S_OK;
  1899. } // if:
  1900. else
  1901. {
  1902. LOG_STATUS_REPORT_STRING( L"The physical disk '%1!ws!' does not have any partitions and will not be managed", var.bstrVal, hr );
  1903. m_fIsManaged = FALSE;
  1904. } // else:
  1905. goto Cleanup;
  1906. OutOfMemory:
  1907. hr = THR( E_OUTOFMEMORY );
  1908. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetPartitionInfo, IDS_ERROR_OUTOFMEMORY, hr );
  1909. Cleanup:
  1910. VariantClear( &var );
  1911. VariantClear( &varDiskName );
  1912. TraceSysFreeString( bstrQuery );
  1913. TraceSysFreeString( bstrWQL );
  1914. if ( pPartition != NULL )
  1915. {
  1916. pPartition->Release();
  1917. } // if:
  1918. if ( pPartitions != NULL )
  1919. {
  1920. pPartitions->Release();
  1921. } // if:
  1922. HRETURN( hr );
  1923. } //*** CPhysicalDisk::HrGetPartitionInfo
  1924. /////////////////////////////////////////////////////////////////////////////
  1925. //++
  1926. //
  1927. // CPhysicalDisk:HrAddPartitionToArray
  1928. //
  1929. // Description:
  1930. // Add the passed in partition to the array of punks that holds the
  1931. // partitions.
  1932. //
  1933. // Arguments:
  1934. //
  1935. //
  1936. // Return Value:
  1937. // S_OK
  1938. // Success
  1939. //
  1940. // E_OUTOFMEMORY
  1941. // Couldn't allocate memeory.
  1942. //
  1943. // Remarks:
  1944. // None.
  1945. //
  1946. //--
  1947. //////////////////////////////////////////////////////////////////////////////
  1948. HRESULT
  1949. CPhysicalDisk::HrAddPartitionToArray( IUnknown * punkIn )
  1950. {
  1951. TraceFunc( "" );
  1952. HRESULT hr = S_OK;
  1953. IUnknown * ((*prgpunks)[]) = NULL;
  1954. prgpunks = (IUnknown *((*)[])) TraceReAlloc( m_prgPartitions, sizeof( IUnknown * ) * ( m_idxNextPartition + 1 ), HEAP_ZERO_MEMORY );
  1955. if ( prgpunks == NULL )
  1956. {
  1957. hr = THR( E_OUTOFMEMORY );
  1958. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrAddPartitionToArray, IDS_ERROR_OUTOFMEMORY, hr );
  1959. goto Cleanup;
  1960. } // if:
  1961. m_prgPartitions = prgpunks;
  1962. (*m_prgPartitions)[ m_idxNextPartition++ ] = punkIn;
  1963. punkIn->AddRef();
  1964. m_cPartitions += 1;
  1965. Cleanup:
  1966. HRETURN( hr );
  1967. } //*** CPhysicalDisk::HrAddPartitionToArray
  1968. /////////////////////////////////////////////////////////////////////////////
  1969. //++
  1970. //
  1971. // CPhysicalDisk:HrCreatePartitionInfo
  1972. //
  1973. // Description:
  1974. // Create a partition info from the passes in WMI partition.
  1975. //
  1976. // Arguments:
  1977. //
  1978. //
  1979. // Return Value:
  1980. // S_OK
  1981. // Success
  1982. //
  1983. // S_FALSE
  1984. // The file system was not NTFS.
  1985. //
  1986. // E_OUTOFMEMORY
  1987. // Couldn't allocate memeory.
  1988. //
  1989. // Remarks:
  1990. // None.
  1991. //
  1992. //--
  1993. //////////////////////////////////////////////////////////////////////////////
  1994. HRESULT
  1995. CPhysicalDisk::HrCreatePartitionInfo( IWbemClassObject * pPartitionIn )
  1996. {
  1997. TraceFunc( "" );
  1998. HRESULT hr = S_OK;
  1999. IUnknown * punk = NULL;
  2000. IClusCfgSetWbemObject * piccswo = NULL;
  2001. bool fRetainObject = true;
  2002. hr = THR( CClusCfgPartitionInfo::S_HrCreateInstance( &punk ) );
  2003. if ( FAILED( hr ) )
  2004. {
  2005. goto Cleanup;
  2006. } // if:
  2007. punk = TraceInterface( L"CClusCfgPartitionInfo", IUnknown, punk, 1 );
  2008. hr = THR( HrSetInitialize( punk, m_picccCallback, m_lcid ) );
  2009. if ( FAILED( hr ) )
  2010. {
  2011. goto Cleanup;
  2012. } // if:
  2013. hr = THR( HrSetWbemServices( punk, m_pIWbemServices ) );
  2014. if ( FAILED( hr ) )
  2015. {
  2016. goto Cleanup;
  2017. } // if:
  2018. hr = THR( punk->TypeSafeQI( IClusCfgSetWbemObject, &piccswo ) );
  2019. if ( FAILED( hr ) )
  2020. {
  2021. goto Cleanup;
  2022. } // if:
  2023. hr = THR( piccswo->SetWbemObject( pPartitionIn, &fRetainObject ) );
  2024. if ( FAILED( hr ) )
  2025. {
  2026. goto Cleanup;
  2027. } // if:
  2028. if ( fRetainObject )
  2029. {
  2030. hr = THR( HrAddPartitionToArray( punk ) );
  2031. } // if:
  2032. Cleanup:
  2033. if ( piccswo != NULL )
  2034. {
  2035. piccswo->Release();
  2036. } // if:
  2037. if ( punk != NULL )
  2038. {
  2039. punk->Release();
  2040. } // if:
  2041. HRETURN( hr );
  2042. } //*** CPhysicalDisk::HrCreatePartitionInfo
  2043. /////////////////////////////////////////////////////////////////////////////
  2044. //++
  2045. //
  2046. // CPhysicalDisk:HrCreateFriendlyName
  2047. //
  2048. // Description:
  2049. // Create a cluster friendly name.
  2050. //
  2051. // Arguments:
  2052. //
  2053. //
  2054. // Return Value:
  2055. // S_OK
  2056. // Success
  2057. //
  2058. // E_OUTOFMEMORY
  2059. // Couldn't allocate memeory.
  2060. //
  2061. // Remarks:
  2062. // None.
  2063. //
  2064. //--
  2065. //////////////////////////////////////////////////////////////////////////////
  2066. HRESULT
  2067. CPhysicalDisk::HrCreateFriendlyName( void )
  2068. {
  2069. TraceFunc( "" );
  2070. Assert( m_idxNextPartition > 0 );
  2071. HRESULT hr = S_FALSE;
  2072. WCHAR * psz = NULL;
  2073. WCHAR * pszTmp = NULL;
  2074. DWORD cch = 5; // length of "Disk" plus EOS
  2075. DWORD idx;
  2076. IClusCfgPartitionProperties * piccpp = NULL;
  2077. BSTR bstrName = NULL;
  2078. bool fFoundLogicalDisk = false;
  2079. BSTR bstr = NULL;
  2080. if ( m_idxNextPartition == 0 )
  2081. {
  2082. goto Cleanup;
  2083. } // if:
  2084. psz = (WCHAR * ) TraceAlloc( HEAP_ZERO_MEMORY, sizeof( WCHAR ) * cch );
  2085. if ( psz == NULL )
  2086. {
  2087. goto OutOfMemory;
  2088. } // if:
  2089. wcscpy( psz, L"Disk" );
  2090. for ( idx = 0; idx < m_idxNextPartition; idx++ )
  2091. {
  2092. hr = THR( ((*m_prgPartitions)[ idx ])->TypeSafeQI( IClusCfgPartitionProperties, &piccpp ) );
  2093. if ( FAILED( hr ) )
  2094. {
  2095. goto Cleanup;
  2096. } // if:
  2097. hr = STHR( piccpp->GetFriendlyName( &bstrName ) );
  2098. if ( FAILED( hr ) )
  2099. {
  2100. goto Cleanup;
  2101. } // if:
  2102. if ( hr == S_FALSE )
  2103. {
  2104. continue;
  2105. } // if:
  2106. fFoundLogicalDisk = true;
  2107. cch += ( UINT ) wcslen( bstrName ) + 1;
  2108. pszTmp = (WCHAR * ) TraceReAlloc( psz, sizeof( WCHAR ) * cch, HEAP_ZERO_MEMORY );
  2109. if ( pszTmp == NULL )
  2110. {
  2111. goto OutOfMemory;
  2112. } // if:
  2113. psz = pszTmp;
  2114. pszTmp = NULL;
  2115. wcscat( psz, bstrName );
  2116. TraceSysFreeString( bstrName );
  2117. bstrName = NULL;
  2118. piccpp->Release();
  2119. piccpp = NULL;
  2120. } // for:
  2121. //
  2122. // KB: 31-JUL-2000
  2123. //
  2124. // If we didn't find any logical disk IDs then we don't want
  2125. // to touch m_bstrFriendlyName.
  2126. //
  2127. if ( !fFoundLogicalDisk )
  2128. {
  2129. hr = S_OK; // ensure that that the caller doesn't fail since this is not a fatal error...
  2130. goto Cleanup;
  2131. } // if:
  2132. bstr = TraceSysAllocString( psz );
  2133. if ( bstr == NULL )
  2134. {
  2135. goto OutOfMemory;
  2136. } // if:
  2137. TraceSysFreeString( m_bstrFriendlyName );
  2138. m_bstrFriendlyName = bstr;
  2139. goto Cleanup;
  2140. OutOfMemory:
  2141. hr = THR( E_OUTOFMEMORY );
  2142. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrCreateFriendlyName_VOID, IDS_ERROR_OUTOFMEMORY, hr );
  2143. Cleanup:
  2144. if ( piccpp != NULL )
  2145. {
  2146. piccpp->Release();
  2147. } // if:
  2148. if ( psz != NULL )
  2149. {
  2150. TraceFree( psz );
  2151. } // if:
  2152. if ( pszTmp != NULL )
  2153. {
  2154. free( pszTmp );
  2155. } // if:
  2156. TraceSysFreeString( bstrName );
  2157. HRETURN( hr );
  2158. } //*** CPhysicalDisk::HrCreateFriendlyName
  2159. /////////////////////////////////////////////////////////////////////////////
  2160. //++
  2161. //
  2162. // CPhysicalDisk:HrCreateFriendlyName
  2163. //
  2164. // Description:
  2165. // Convert the WMI disk name into a more freindly version.
  2166. // Create a cluster friendly name.
  2167. //
  2168. // Arguments:
  2169. //
  2170. //
  2171. // Return Value:
  2172. // S_OK
  2173. // Success
  2174. //
  2175. // E_OUTOFMEMORY
  2176. // Couldn't allocate memeory.
  2177. //
  2178. // Remarks:
  2179. // None.
  2180. //
  2181. //--
  2182. //////////////////////////////////////////////////////////////////////////////
  2183. HRESULT
  2184. CPhysicalDisk::HrCreateFriendlyName( BSTR bstrNameIn )
  2185. {
  2186. TraceFunc1( "bstrNameIn = '%ws'", bstrNameIn == NULL ? L"<null>" : bstrNameIn );
  2187. HRESULT hr = S_OK;
  2188. WCHAR * psz = NULL;
  2189. BSTR bstr = NULL;
  2190. //
  2191. // KB: 27-JUN-2000 GalenB
  2192. //
  2193. // Disk names in WMI start with "\\.\". As a better and easy
  2194. // friendly name I am just going to trim these leading chars
  2195. // off.
  2196. //
  2197. psz = bstrNameIn + wcslen( L"\\\\.\\" );
  2198. bstr = TraceSysAllocString( psz );
  2199. if ( bstr == NULL )
  2200. {
  2201. hr = THR( E_OUTOFMEMORY );
  2202. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrCreateFriendlyName_BSTR, IDS_ERROR_OUTOFMEMORY, hr );
  2203. goto Cleanup;
  2204. } // if:
  2205. TraceSysFreeString( m_bstrFriendlyName );
  2206. m_bstrFriendlyName = bstr;
  2207. Cleanup:
  2208. HRETURN( hr );
  2209. } //*** CPhysicalDisk::HrCreateFriendlyName
  2210. /////////////////////////////////////////////////////////////////////////////
  2211. //++
  2212. //
  2213. // CPhysicalDisk:HrIsPartitionGPT
  2214. //
  2215. // Description:
  2216. // Is the passed in partition a GPT partition.
  2217. //
  2218. // Arguments:
  2219. //
  2220. //
  2221. // Return Value:
  2222. // S_OK
  2223. // The partition is a GPT partition.
  2224. //
  2225. // S_FALSE
  2226. // The partition is not GPT.
  2227. //
  2228. // E_OUTOFMEMORY
  2229. // Couldn't allocate memeory.
  2230. //
  2231. // Remarks:
  2232. // If the type property of a Win32_DiskPartition starts with "GPT"
  2233. // then the whole spindle has GPT partitions.
  2234. //
  2235. //--
  2236. //////////////////////////////////////////////////////////////////////////////
  2237. HRESULT
  2238. CPhysicalDisk::HrIsPartitionGPT( IWbemClassObject * pPartitionIn )
  2239. {
  2240. TraceFunc( "" );
  2241. HRESULT hr = S_OK;
  2242. VARIANT var;
  2243. WCHAR szData[ 4 ];
  2244. BSTR bstrGPT = NULL;
  2245. VariantInit( &var );
  2246. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_GPT, &bstrGPT ) );
  2247. if ( FAILED( hr ) )
  2248. {
  2249. goto Cleanup;
  2250. } // if:
  2251. hr = THR( HrGetWMIProperty( pPartitionIn, L"Type", VT_BSTR, &var ) );
  2252. if ( FAILED( hr ) )
  2253. {
  2254. goto Cleanup;
  2255. } // if:
  2256. //
  2257. // Get the fist three characters. When the spindle has GPT partitions then
  2258. // these characters will be "GPT". I am unsure if this will be localized?
  2259. //
  2260. wcsncpy( szData, var.bstrVal, ARRAYSIZE( szData ) - 1 );
  2261. szData[ 3 ] = UNICODE_NULL;
  2262. CharUpper( szData );
  2263. if ( wcscmp( szData, bstrGPT ) != 0 )
  2264. {
  2265. hr = S_FALSE;
  2266. } // if:
  2267. Cleanup:
  2268. VariantClear( &var );
  2269. TraceSysFreeString( bstrGPT );
  2270. HRETURN( hr );
  2271. } //*** CPhysicalDisk::HrIsPartitionGPT
  2272. /////////////////////////////////////////////////////////////////////////////
  2273. //++
  2274. //
  2275. // CPhysicalDisk:HrIsPartitionLDM
  2276. //
  2277. // Description:
  2278. // Is the passed in partition an LDM partition.
  2279. //
  2280. // Arguments:
  2281. //
  2282. //
  2283. // Return Value:
  2284. // S_OK
  2285. // The partition is an LDM partition.
  2286. //
  2287. // S_FALSE
  2288. // The partition is not LDM.
  2289. //
  2290. // E_OUTOFMEMORY
  2291. // Couldn't allocate memeory.
  2292. //
  2293. // Remarks:
  2294. // If the type property of a Win32_DiskPartition is "logical disk
  2295. // manager" then this disk is an LDM disk.
  2296. //
  2297. //--
  2298. //////////////////////////////////////////////////////////////////////////////
  2299. HRESULT
  2300. CPhysicalDisk::HrIsPartitionLDM( IWbemClassObject * pPartitionIn )
  2301. {
  2302. TraceFunc( "" );
  2303. HRESULT hr = S_OK;
  2304. VARIANT var;
  2305. BSTR bstrLDM = NULL;
  2306. VariantInit( &var );
  2307. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_LDM, &bstrLDM ) );
  2308. if ( FAILED( hr ) )
  2309. {
  2310. goto Cleanup;
  2311. } // if:
  2312. hr = THR( HrGetWMIProperty( pPartitionIn, L"Type", VT_BSTR, &var ) );
  2313. if ( FAILED( hr ) )
  2314. {
  2315. goto Cleanup;
  2316. } // if:
  2317. CharUpper( var.bstrVal );
  2318. if ( wcscmp( var.bstrVal, bstrLDM ) != 0 )
  2319. {
  2320. hr = S_FALSE;
  2321. } // if:
  2322. Cleanup:
  2323. VariantClear( &var );
  2324. TraceSysFreeString( bstrLDM );
  2325. HRETURN( hr );
  2326. } //*** CPhysicalDisk::HrIsPartitionLDM
  2327. /////////////////////////////////////////////////////////////////////////////
  2328. //++
  2329. //
  2330. // CPhysicalDisk:HrGetDiskFirmwareSerialNumber
  2331. //
  2332. // Description:
  2333. // Get the disk firmware serial number.
  2334. //
  2335. // Arguments:
  2336. // None.
  2337. //
  2338. // Return Value:
  2339. // S_OK
  2340. // Success.
  2341. //
  2342. // S_FALSE
  2343. // There wasn't a firmware serial number.
  2344. //
  2345. // E_OUTOFMEMORY
  2346. // Couldn't allocate memeory.
  2347. //
  2348. // Remarks:
  2349. //
  2350. //--
  2351. //////////////////////////////////////////////////////////////////////////////
  2352. HRESULT
  2353. CPhysicalDisk::HrGetDiskFirmwareSerialNumber( void )
  2354. {
  2355. TraceFunc( "" );
  2356. HRESULT hr = S_OK;
  2357. HANDLE hVolume = NULL;
  2358. DWORD dwSize;
  2359. DWORD sc;
  2360. STORAGE_PROPERTY_QUERY spq;
  2361. BOOL fRet;
  2362. PSTORAGE_DEVICE_DESCRIPTOR pddBuffer = NULL;
  2363. DWORD cbBuffer;
  2364. PCHAR psz = NULL;
  2365. //
  2366. // get handle to disk
  2367. //
  2368. hVolume = CreateFile(
  2369. m_bstrDeviceID
  2370. , GENERIC_READ
  2371. , FILE_SHARE_READ
  2372. , NULL
  2373. , OPEN_EXISTING
  2374. , FILE_ATTRIBUTE_NORMAL
  2375. , NULL
  2376. );
  2377. if ( hVolume == INVALID_HANDLE_VALUE )
  2378. {
  2379. sc = TW32( GetLastError() );
  2380. hr = HRESULT_FROM_WIN32( sc );
  2381. goto Cleanup;
  2382. } // if:
  2383. cbBuffer = sizeof( STORAGE_DEVICE_DESCRIPTOR) + 2048;
  2384. pddBuffer = (PSTORAGE_DEVICE_DESCRIPTOR ) TraceAlloc( 0, cbBuffer );
  2385. if ( pddBuffer == NULL )
  2386. {
  2387. goto OutOfMemory;
  2388. } // if:
  2389. ZeroMemory( pddBuffer, cbBuffer );
  2390. ZeroMemory( &spq, sizeof( spq ) );
  2391. spq.PropertyId = StorageDeviceProperty;
  2392. spq.QueryType = PropertyStandardQuery;
  2393. //
  2394. // issue storage class ioctl to get the disk's firmware serial number.
  2395. //
  2396. fRet = DeviceIoControl(
  2397. hVolume
  2398. , IOCTL_STORAGE_QUERY_PROPERTY
  2399. , &spq
  2400. , sizeof( spq )
  2401. , pddBuffer
  2402. , cbBuffer
  2403. , &dwSize
  2404. , NULL
  2405. );
  2406. if ( !fRet )
  2407. {
  2408. sc = TW32( GetLastError() );
  2409. hr = HRESULT_FROM_WIN32( sc );
  2410. goto Cleanup;
  2411. } // if:
  2412. if ( dwSize > 0 )
  2413. {
  2414. //
  2415. // Ensure that there is a serial number offset and that it is within the buffer extents.
  2416. //
  2417. if ( ( pddBuffer->SerialNumberOffset == 0 ) || ( pddBuffer->SerialNumberOffset > pddBuffer->Size ) )
  2418. {
  2419. LOG_STATUS_REPORT_STRING( L"The disk '%1!ws!' does not have a firmware serial number.", m_bstrDeviceID, hr );
  2420. hr = S_FALSE;
  2421. goto Cleanup;
  2422. } // if:
  2423. //
  2424. // Serial number string is a zero terminated ASCII string.
  2425. //
  2426. // The header ntddstor.h says the for devices with no serial number,
  2427. // the offset will be zero. This doesn't seem to be TRUE.
  2428. //
  2429. // For devices with no serial number, it looks like a string with a single
  2430. // null character '\0' is returned.
  2431. //
  2432. psz = (PCHAR) pddBuffer + (DWORD) pddBuffer->SerialNumberOffset;
  2433. hr = THR( HrAnsiStringToBSTR( psz, &m_bstrFirmwareSerialNumber ) );
  2434. if ( FAILED( hr ) )
  2435. {
  2436. goto Cleanup;
  2437. } // if:
  2438. LOG_STATUS_REPORT_STRING3(
  2439. L"Disk '%1!ws!' has firmware serial number '%2!ws!' at offset '%3!#08x!'."
  2440. , m_bstrDeviceID
  2441. , m_bstrFirmwareSerialNumber
  2442. , pddBuffer->SerialNumberOffset
  2443. , hr
  2444. );
  2445. } // if:
  2446. goto Cleanup;
  2447. OutOfMemory:
  2448. hr = THR( E_OUTOFMEMORY );
  2449. LogMsg( L"[SRV] HrGetDiskFirmwareSerialNumber() is out of memory. (hr = %#08x)", hr );
  2450. Cleanup:
  2451. if ( hVolume != NULL )
  2452. {
  2453. CloseHandle( hVolume );
  2454. } // if:
  2455. TraceFree( pddBuffer );
  2456. HRETURN( hr );
  2457. } //*** CPhysicalDisk::HrGetDiskFirmwareSerialNumber
  2458. /////////////////////////////////////////////////////////////////////////////
  2459. //++
  2460. //
  2461. // CPhysicalDisk:HrGetDiskFirmwareVitalData
  2462. //
  2463. // Description:
  2464. // Get the disk firmware vital data.
  2465. //
  2466. // Arguments:
  2467. // None.
  2468. //
  2469. // Return Value:
  2470. // S_OK
  2471. // Success.
  2472. //
  2473. // S_FALSE
  2474. // There wasn't a firmware serial number.
  2475. //
  2476. // E_OUTOFMEMORY
  2477. // Couldn't allocate memeory.
  2478. //
  2479. // Remarks:
  2480. //
  2481. //--
  2482. //////////////////////////////////////////////////////////////////////////////
  2483. HRESULT
  2484. CPhysicalDisk::HrGetDiskFirmwareVitalData( void )
  2485. {
  2486. TraceFunc( "" );
  2487. HRESULT hr = S_OK;
  2488. HANDLE hVolume = NULL;
  2489. DWORD dwSize;
  2490. DWORD sc;
  2491. STORAGE_PROPERTY_QUERY spq;
  2492. BOOL fRet;
  2493. PSTORAGE_DEVICE_ID_DESCRIPTOR psdidBuffer = NULL;
  2494. DWORD cbBuffer;
  2495. //
  2496. // get handle to disk
  2497. //
  2498. hVolume = CreateFile(
  2499. m_bstrDeviceID
  2500. , GENERIC_READ
  2501. , FILE_SHARE_READ
  2502. , NULL
  2503. , OPEN_EXISTING
  2504. , FILE_ATTRIBUTE_NORMAL
  2505. , NULL
  2506. );
  2507. if ( hVolume == INVALID_HANDLE_VALUE )
  2508. {
  2509. sc = TW32( GetLastError() );
  2510. hr = HRESULT_FROM_WIN32( sc );
  2511. goto Cleanup;
  2512. } // if:
  2513. cbBuffer = sizeof( STORAGE_DEVICE_ID_DESCRIPTOR ) + 2048;
  2514. psdidBuffer = (PSTORAGE_DEVICE_ID_DESCRIPTOR) TraceAlloc( 0, cbBuffer );
  2515. if ( psdidBuffer == NULL )
  2516. {
  2517. goto OutOfMemory;
  2518. } // if:
  2519. ZeroMemory( psdidBuffer, cbBuffer );
  2520. ZeroMemory( &spq, sizeof( spq ) );
  2521. spq.PropertyId = StorageDeviceIdProperty;
  2522. spq.QueryType = PropertyStandardQuery;
  2523. //
  2524. // issue storage class ioctl to get the disk's firmware vital data
  2525. //
  2526. fRet = DeviceIoControl(
  2527. hVolume
  2528. , IOCTL_STORAGE_QUERY_PROPERTY
  2529. , &spq
  2530. , sizeof( spq )
  2531. , psdidBuffer
  2532. , cbBuffer
  2533. , &dwSize
  2534. , NULL
  2535. );
  2536. if ( !fRet )
  2537. {
  2538. sc = TW32( GetLastError() );
  2539. hr = HRESULT_FROM_WIN32( sc );
  2540. goto Cleanup;
  2541. } // if:
  2542. if ( dwSize > 0 )
  2543. {
  2544. } // if:
  2545. goto Cleanup;
  2546. OutOfMemory:
  2547. hr = THR( E_OUTOFMEMORY );
  2548. LogMsg( L"[SRV] HrGetDiskFirmwareVitalData() is out of memory. (hr = %#08x)", hr );
  2549. Cleanup:
  2550. if ( hVolume != NULL )
  2551. {
  2552. CloseHandle( hVolume );
  2553. } // if:
  2554. TraceFree( psdidBuffer );
  2555. HRETURN( hr );
  2556. } //*** CPhysicalDisk::HrGetDiskFirmwareVitalData
  2557. /////////////////////////////////////////////////////////////////////////////
  2558. //++
  2559. //
  2560. // CPhysicalDisk:HrIsClusterCapable
  2561. //
  2562. // Description:
  2563. // Is this disk cluster capable?
  2564. //
  2565. // Arguments:
  2566. // None.
  2567. //
  2568. // Return Value:
  2569. // S_OK
  2570. // The disk is cluster capable.
  2571. //
  2572. // S_FALSE
  2573. // The disk is not cluster capable.
  2574. //
  2575. // E_OUTOFMEMORY
  2576. // Couldn't allocate memeory.
  2577. //
  2578. // Remarks:
  2579. //
  2580. //--
  2581. //////////////////////////////////////////////////////////////////////////////
  2582. HRESULT
  2583. CPhysicalDisk::HrIsClusterCapable( void )
  2584. {
  2585. TraceFunc( "" );
  2586. HRESULT hr = S_FALSE;
  2587. HANDLE hVolume = NULL;
  2588. DWORD dwSize;
  2589. DWORD sc;
  2590. BOOL fRet;
  2591. //
  2592. // get handle to disk
  2593. //
  2594. hVolume = CreateFile(
  2595. m_bstrDeviceID
  2596. , GENERIC_READ
  2597. , FILE_SHARE_READ
  2598. , NULL
  2599. , OPEN_EXISTING
  2600. , FILE_ATTRIBUTE_NORMAL
  2601. , NULL
  2602. );
  2603. if ( hVolume == INVALID_HANDLE_VALUE )
  2604. {
  2605. sc = TW32( GetLastError() );
  2606. hr = HRESULT_FROM_WIN32( sc );
  2607. goto Cleanup;
  2608. } // if:
  2609. //
  2610. // issue cluster storage ioctl to determine whether the disk is cluster capable
  2611. //
  2612. fRet = DeviceIoControl(
  2613. hVolume
  2614. , IOCTL_DISK_CLUSTER_NOT_CLUSTER_CAPABLE
  2615. , NULL
  2616. , 0
  2617. , NULL
  2618. , 0
  2619. , &dwSize
  2620. , NULL
  2621. );
  2622. if ( !fRet )
  2623. {
  2624. hr = S_OK;
  2625. } // if:
  2626. Cleanup:
  2627. if ( hVolume != NULL )
  2628. {
  2629. CloseHandle( hVolume );
  2630. } // if:
  2631. HRETURN( hr );
  2632. } //*** CPhysicalDisk::HrIsClusterCapable