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.

712 lines
21 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // Disks.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CPhysDiskParamsPage class.
  10. //
  11. // Author:
  12. // David Potter (davidp) June 28, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "CluAdmX.h"
  21. #include "ExtObj.h"
  22. #include "Disks.h"
  23. #include "DDxDDv.h"
  24. #include "PropList.h"
  25. #include "HelpData.h"
  26. #include "ExcOper.h"
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CPhysDiskParamsPage property page
  34. /////////////////////////////////////////////////////////////////////////////
  35. IMPLEMENT_DYNCREATE(CPhysDiskParamsPage, CBasePropertyPage)
  36. /////////////////////////////////////////////////////////////////////////////
  37. // Message Maps
  38. BEGIN_MESSAGE_MAP(CPhysDiskParamsPage, CBasePropertyPage)
  39. //{{AFX_MSG_MAP(CPhysDiskParamsPage)
  40. ON_CBN_SELCHANGE(IDC_PP_DISKS_PARAMS_DISK, OnChangeDisk)
  41. //}}AFX_MSG_MAP
  42. // TODO: Modify the following lines to represent the data displayed on this page.
  43. END_MESSAGE_MAP()
  44. /////////////////////////////////////////////////////////////////////////////
  45. //++
  46. //
  47. // CPhysDiskParamsPage::CPhysDiskParamsPage
  48. //
  49. // Routine Description:
  50. // Default constructor.
  51. //
  52. // Arguments:
  53. // None.
  54. //
  55. // Return Value:
  56. // None.
  57. //
  58. //--
  59. /////////////////////////////////////////////////////////////////////////////
  60. CPhysDiskParamsPage::CPhysDiskParamsPage(void)
  61. : CBasePropertyPage(g_aHelpIDs_IDD_PP_DISKS_PARAMETERS, g_aHelpIDs_IDD_WIZ_DISKS_PARAMETERS)
  62. {
  63. // TODO: Modify the following lines to represent the data displayed on this page.
  64. //{{AFX_DATA_INIT(CPhysDiskParamsPage)
  65. m_strDisk = _T("");
  66. //}}AFX_DATA_INIT
  67. m_dwSignature = 0;
  68. m_pbAvailDiskInfo = NULL;
  69. m_cbAvailDiskInfo = 0;
  70. m_pbDiskInfo = NULL;
  71. m_cbDiskInfo = 0;
  72. // Setup the property array.
  73. {
  74. m_rgProps[epropSignature].Set(REGPARAM_DISKS_SIGNATURE, m_dwSignature, m_dwPrevSignature);
  75. } // Setup the property array
  76. m_iddPropertyPage = IDD_PP_DISKS_PARAMETERS;
  77. m_iddWizardPage = IDD_WIZ_DISKS_PARAMETERS;
  78. } //*** CPhysDiskParamsPage::CPhysDiskParamsPage()
  79. /////////////////////////////////////////////////////////////////////////////
  80. //++
  81. //
  82. // CPhysDiskParamsPage::~CPhysDiskParamsPage
  83. //
  84. // Routine Description:
  85. // Destructor.
  86. //
  87. // Arguments:
  88. // None.
  89. //
  90. // Return Value:
  91. // None.
  92. //
  93. //--
  94. /////////////////////////////////////////////////////////////////////////////
  95. CPhysDiskParamsPage::~CPhysDiskParamsPage(void)
  96. {
  97. delete [] m_pbAvailDiskInfo;
  98. delete [] m_pbDiskInfo;
  99. } //*** CPhysDiskParamsPage::~CPhysDiskParamsPage()
  100. /////////////////////////////////////////////////////////////////////////////
  101. //++
  102. //
  103. // CPhysDiskParamsPage::HrInit
  104. //
  105. // Routine Description:
  106. // Initialize the page.
  107. //
  108. // Arguments:
  109. // peo [IN OUT] Pointer to the extension object.
  110. //
  111. // Return Value:
  112. // S_OK Page initialized successfully.
  113. // hr Page failed to initialize.
  114. //
  115. //--
  116. /////////////////////////////////////////////////////////////////////////////
  117. HRESULT CPhysDiskParamsPage::HrInit(IN OUT CExtObject * peo)
  118. {
  119. HRESULT _hr;
  120. CWaitCursor _wc;
  121. do
  122. {
  123. // Call the base class method.
  124. _hr = CBasePropertyPage::HrInit(peo);
  125. if ( FAILED( _hr ) )
  126. {
  127. break;
  128. } // if: error from base class method
  129. // Collect available disk information.
  130. BGetAvailableDisks();
  131. // If creating a new resource, select the first disk.
  132. // Otherwise, collect information about the selected disk.
  133. if (BWizard())
  134. {
  135. CLUSPROP_BUFFER_HELPER buf;
  136. buf.pb = m_pbAvailDiskInfo;
  137. if (m_cbAvailDiskInfo > 0)
  138. {
  139. while (buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK)
  140. {
  141. if (BStringFromDiskInfo(buf, m_cbAvailDiskInfo, m_strDisk))
  142. break;
  143. ASSERT( (buf.pSyntax->dw == CLUSPROP_SYNTAX_ENDMARK)
  144. || (buf.pSyntax->dw == CLUSPROP_SYNTAX_DISK_SIGNATURE));
  145. } // while: more entries in the list
  146. } // if: there are available disks
  147. } // if: creating a new resource
  148. else
  149. {
  150. // Don't return false because that will prevent the page from showing up.
  151. BGetDiskInfo();
  152. // Get the current state of the resource.
  153. m_crs = GetClusterResourceState(Peo()->PrdResData()->m_hresource, NULL, NULL, NULL, NULL );
  154. } // else: viewing an existing resource
  155. } while ( 0 );
  156. return _hr;
  157. } //*** CPhysDiskParamsPage::HrInit()
  158. /////////////////////////////////////////////////////////////////////////////
  159. //++
  160. //
  161. // CPhysDiskParamsPage::DoDataExchange
  162. //
  163. // Routine Description:
  164. // Do data exchange between the dialog and the class.
  165. //
  166. // Arguments:
  167. // pDX [IN OUT] Data exchange object
  168. //
  169. // Return Value:
  170. // None.
  171. //
  172. //--
  173. /////////////////////////////////////////////////////////////////////////////
  174. void CPhysDiskParamsPage::DoDataExchange(CDataExchange * pDX)
  175. {
  176. if (!pDX->m_bSaveAndValidate || !BSaved())
  177. {
  178. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  179. // TODO: Modify the following lines to represent the data displayed on this page.
  180. //{{AFX_DATA_MAP(CPhysDiskParamsPage)
  181. DDX_Control(pDX, IDC_PP_DISKS_PARAMS_DISK, m_cboxDisk);
  182. DDX_Text(pDX, IDC_PP_DISKS_PARAMS_DISK, m_strDisk);
  183. //}}AFX_DATA_MAP
  184. if (pDX->m_bSaveAndValidate)
  185. {
  186. if (!BBackPressed())
  187. {
  188. if (BWizard()
  189. && !( (m_strDisk.GetLength() == 0)
  190. && (m_crs == ClusterResourceOffline)))
  191. {
  192. DDV_RequiredText(pDX, IDC_PP_DISKS_PARAMS_DISK, IDC_PP_DISKS_PARAMS_DISK_LABEL, m_strDisk);
  193. m_dwSignature = (DWORD)m_cboxDisk.GetItemData(m_cboxDisk.GetCurSel());
  194. ASSERT(m_dwSignature != 0);
  195. } // if: not offline with an empty disk string
  196. } // if: Back button not pressed
  197. } // if: saving data
  198. } // if: not saving or haven't saved yet
  199. CBasePropertyPage::DoDataExchange(pDX);
  200. } //*** CPhysDiskParamsPage::DoDataExchange()
  201. /////////////////////////////////////////////////////////////////////////////
  202. //++
  203. //
  204. // CPhysDiskParamsPage::OnInitDialog
  205. //
  206. // Routine Description:
  207. // Handler for the WM_INITDIALOG message.
  208. //
  209. // Arguments:
  210. // None.
  211. //
  212. // Return Value:
  213. // TRUE We need the focus to be set for us.
  214. // FALSE We already set the focus to the proper control.
  215. //
  216. //--
  217. /////////////////////////////////////////////////////////////////////////////
  218. BOOL CPhysDiskParamsPage::OnInitDialog(void)
  219. {
  220. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  221. CBasePropertyPage::OnInitDialog();
  222. // Set the combobox as read-only if not creating a new resource.
  223. m_cboxDisk.EnableWindow(BWizard());
  224. // Fill the disks list.
  225. FillList();
  226. return TRUE; // return TRUE unless you set the focus to a control
  227. // EXCEPTION: OCX Property Pages should return FALSE
  228. } //*** CPhysDiskParamsPage::OnInitDialog()
  229. /////////////////////////////////////////////////////////////////////////////
  230. //++
  231. //
  232. // CPhysDiskParamsPage::OnSetActive
  233. //
  234. // Routine Description:
  235. // Handler for the PSN_SETACTIVE message.
  236. //
  237. // Arguments:
  238. // None.
  239. //
  240. // Return Value:
  241. // TRUE Page successfully initialized.
  242. // FALSE Page not initialized.
  243. //
  244. //--
  245. /////////////////////////////////////////////////////////////////////////////
  246. BOOL CPhysDiskParamsPage::OnSetActive(void)
  247. {
  248. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  249. // Enable/disable the Next/Finish button.
  250. if (BWizard())
  251. {
  252. if (m_strDisk.GetLength() == 0)
  253. EnableNext(FALSE);
  254. else
  255. EnableNext(TRUE);
  256. } // if: enable/disable the Next button
  257. return CBasePropertyPage::OnSetActive();
  258. } //*** CPhysDiskParamsPage::OnSetActive()
  259. /////////////////////////////////////////////////////////////////////////////
  260. //++
  261. //
  262. // CPhysDiskParamsPage::BApplyChanges
  263. //
  264. // Routine Description:
  265. // Apply changes made on the page.
  266. //
  267. // Arguments:
  268. // None.
  269. //
  270. // Return Value:
  271. // TRUE Page successfully applied.
  272. // FALSE Error applying page.
  273. //
  274. //--
  275. /////////////////////////////////////////////////////////////////////////////
  276. BOOL CPhysDiskParamsPage::BApplyChanges(void)
  277. {
  278. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  279. CWaitCursor wc;
  280. if (!( (m_strDisk.GetLength() == 0)
  281. && (m_crs == ClusterResourceOffline)))
  282. {
  283. // Call the base class method.
  284. if (!CBasePropertyPage::BApplyChanges())
  285. return FALSE;
  286. // Reread the disk info and the available disks.
  287. // Ignore errors because we can't do anything about it at this point anyway.
  288. BGetAvailableDisks();
  289. BGetDiskInfo();
  290. // Refill the combobox.
  291. FillList();
  292. } // if: not offline with an empty disk string
  293. return TRUE;
  294. } //*** CPhysDiskParamsPage::BApplyChanges()
  295. /////////////////////////////////////////////////////////////////////////////
  296. //++
  297. //
  298. // CPhysDiskParamsPage::OnChangeDisk
  299. //
  300. // Routine Description:
  301. // Handler for the CBN_SELCHANGE message on the Disks combobox.
  302. //
  303. // Arguments:
  304. // None.
  305. //
  306. // Return Value:
  307. // None.
  308. //
  309. //--
  310. /////////////////////////////////////////////////////////////////////////////
  311. void CPhysDiskParamsPage::OnChangeDisk(void)
  312. {
  313. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  314. OnChangeCtrl();
  315. if (BWizard())
  316. {
  317. if (m_cboxDisk.GetWindowTextLength() == 0)
  318. EnableNext(FALSE);
  319. else
  320. EnableNext(TRUE);
  321. } // if: in a wizard
  322. } //*** CPhysDiskParamsPage::OnChangeDisk()
  323. /////////////////////////////////////////////////////////////////////////////
  324. //++
  325. //
  326. // CPhysDiskParamsPage::BGetAvailableDisks
  327. //
  328. // Routine Description:
  329. // Get the list of disks for this type of resource that can be assigned
  330. // to a resource.
  331. //
  332. // Arguments:
  333. // None.
  334. //
  335. // Return Value:
  336. // TRUE The operation was successful.
  337. // FALSE The operation failed.
  338. //
  339. //--
  340. /////////////////////////////////////////////////////////////////////////////
  341. BOOL CPhysDiskParamsPage::BGetAvailableDisks(void)
  342. {
  343. DWORD dwStatus = ERROR_SUCCESS;
  344. DWORD cbDiskInfo = sizeof(CLUSPROP_DWORD)
  345. + sizeof(CLUSPROP_SCSI_ADDRESS)
  346. + sizeof(CLUSPROP_DISK_NUMBER)
  347. + sizeof(CLUSPROP_PARTITION_INFO)
  348. + sizeof(CLUSPROP_SYNTAX);
  349. PBYTE pbDiskInfo = NULL;
  350. try
  351. {
  352. // Get disk info.
  353. pbDiskInfo = new BYTE[cbDiskInfo];
  354. dwStatus = ClusterResourceTypeControl(
  355. Peo()->Hcluster(),
  356. Peo()->PrdResData()->m_strResTypeName,
  357. NULL,
  358. CLUSCTL_RESOURCE_TYPE_STORAGE_GET_AVAILABLE_DISKS,
  359. NULL,
  360. 0,
  361. pbDiskInfo,
  362. cbDiskInfo,
  363. &cbDiskInfo
  364. );
  365. if (dwStatus == ERROR_MORE_DATA)
  366. {
  367. delete [] pbDiskInfo;
  368. pbDiskInfo = new BYTE[cbDiskInfo];
  369. dwStatus = ClusterResourceTypeControl(
  370. Peo()->Hcluster(),
  371. Peo()->PrdResData()->m_strResTypeName,
  372. NULL,
  373. CLUSCTL_RESOURCE_TYPE_STORAGE_GET_AVAILABLE_DISKS,
  374. NULL,
  375. 0,
  376. pbDiskInfo,
  377. cbDiskInfo,
  378. &cbDiskInfo
  379. );
  380. } // if: buffer too small
  381. } // try
  382. catch (CMemoryException * pme)
  383. {
  384. pme->Delete();
  385. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  386. } // catch: CMemoryException
  387. if (dwStatus != ERROR_SUCCESS)
  388. {
  389. CNTException nte(
  390. dwStatus,
  391. IDS_GET_AVAILABLE_DISKS_ERROR,
  392. Peo()->PrdResData()->m_strResTypeName,
  393. NULL,
  394. FALSE /*bAutoDelete*/
  395. );
  396. delete [] pbDiskInfo;
  397. nte.ReportError();
  398. nte.Delete();
  399. return FALSE;
  400. } // if: error getting disk info
  401. delete [] m_pbAvailDiskInfo;
  402. m_pbAvailDiskInfo = pbDiskInfo;
  403. m_cbAvailDiskInfo = cbDiskInfo;
  404. return TRUE;
  405. } //*** CPhysDiskParamsPage::BGetAvailableDisks()
  406. /////////////////////////////////////////////////////////////////////////////
  407. //++
  408. //
  409. // CPhysDiskParamsPage::BGetDiskInfo
  410. //
  411. // Routine Description:
  412. // Get information about the currently selected disk.
  413. //
  414. // Arguments:
  415. // None.
  416. //
  417. // Return Value:
  418. // TRUE The operation was successful.
  419. // FALSE The operation failed.
  420. //
  421. //--
  422. /////////////////////////////////////////////////////////////////////////////
  423. BOOL CPhysDiskParamsPage::BGetDiskInfo(void)
  424. {
  425. DWORD dwStatus = ERROR_SUCCESS;
  426. DWORD cbDiskInfo = sizeof(CLUSPROP_DWORD)
  427. + sizeof(CLUSPROP_SCSI_ADDRESS)
  428. + sizeof(CLUSPROP_DISK_NUMBER)
  429. + sizeof(CLUSPROP_PARTITION_INFO)
  430. + sizeof(CLUSPROP_SYNTAX);
  431. PBYTE pbDiskInfo = NULL;
  432. try
  433. {
  434. // Get disk info.
  435. pbDiskInfo = new BYTE[cbDiskInfo];
  436. dwStatus = ClusterResourceControl(
  437. Peo()->PrdResData()->m_hresource,
  438. NULL,
  439. CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO,
  440. NULL,
  441. 0,
  442. pbDiskInfo,
  443. cbDiskInfo,
  444. &cbDiskInfo
  445. );
  446. if (dwStatus == ERROR_MORE_DATA)
  447. {
  448. delete [] pbDiskInfo;
  449. pbDiskInfo = new BYTE[cbDiskInfo];
  450. dwStatus = ClusterResourceControl(
  451. Peo()->PrdResData()->m_hresource,
  452. NULL,
  453. CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO,
  454. NULL,
  455. 0,
  456. pbDiskInfo,
  457. cbDiskInfo,
  458. &cbDiskInfo
  459. );
  460. } // if: buffer too small
  461. } // try
  462. catch (CMemoryException * pme)
  463. {
  464. pme->Delete();
  465. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  466. } // catch: CMemoryException
  467. if (dwStatus != ERROR_SUCCESS)
  468. {
  469. CNTException nte(
  470. dwStatus,
  471. IDS_GET_DISK_INFO_ERROR,
  472. Peo()->PrdResData()->m_strName,
  473. NULL,
  474. FALSE /*bAutoDelete*/
  475. );
  476. delete [] pbDiskInfo;
  477. nte.ReportError();
  478. nte.Delete();
  479. return FALSE;
  480. } // if: error getting disk info
  481. delete [] m_pbDiskInfo;
  482. m_pbDiskInfo = pbDiskInfo;
  483. m_cbDiskInfo = cbDiskInfo;
  484. return TRUE;
  485. } //*** CPhysDiskParamsPage::BGetDiskInfo()
  486. /////////////////////////////////////////////////////////////////////////////
  487. //++
  488. //
  489. // CPhysDiskParamsPage::BStringFromDiskInfo
  490. //
  491. // Routine Description:
  492. // Convert disk information to a string for display.
  493. //
  494. // Arguments:
  495. // rbuf [IN OUT] Buffer pointer.
  496. // cbBuf [IN] Number of bytes in the buffer.
  497. // rstr [OUT] String to fill.
  498. // pdwSignature [OUT] Signature associated with the disk info being
  499. // returned.
  500. //
  501. // Return Value:
  502. // TRUE A string was produced from disk info.
  503. // FALSE No string could be produced.
  504. //
  505. //--
  506. /////////////////////////////////////////////////////////////////////////////
  507. BOOL CPhysDiskParamsPage::BStringFromDiskInfo(
  508. IN OUT CLUSPROP_BUFFER_HELPER & rbuf,
  509. IN DWORD cbBuf,
  510. OUT CString & rstr,
  511. OUT DWORD * pdwSignature // = NULL
  512. ) const
  513. {
  514. CString strPartitionInfo;
  515. DWORD dwSignature = 0;
  516. DWORD cbData;
  517. BOOL bDisplay;
  518. ASSERT(cbBuf > 0);
  519. ASSERT(rbuf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK);
  520. rstr = _T("");
  521. if (rbuf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK)
  522. {
  523. do
  524. {
  525. // Calculate the size of the value.
  526. cbData = sizeof(*rbuf.pValue) + ALIGN_CLUSPROP(rbuf.pValue->cbLength);
  527. ASSERT(cbData <= cbBuf);
  528. // Parse the value.
  529. if (rbuf.pSyntax->dw == CLUSPROP_SYNTAX_DISK_SIGNATURE)
  530. {
  531. // Save the signature.
  532. dwSignature = rbuf.pDwordValue->dw;
  533. ASSERT(dwSignature != 0);
  534. } // if: signature
  535. else if (rbuf.pSyntax->dw == CLUSPROP_SYNTAX_PARTITION_INFO)
  536. {
  537. // Add the partition to the string if it is a usable partition
  538. // and hasn't been added already. If the resource is offline,
  539. // don't check the usable flag.
  540. bDisplay = ( rstr.Find(rbuf.pPartitionInfoValue->szDeviceName) == -1 );
  541. if ( bDisplay && ( m_crs == ClusterResourceOnline ) )
  542. {
  543. bDisplay = (rbuf.pPartitionInfoValue->dwFlags & CLUSPROP_PIFLAG_USABLE) == CLUSPROP_PIFLAG_USABLE;
  544. } // if: resource is online
  545. if (bDisplay)
  546. {
  547. try
  548. {
  549. strPartitionInfo.Format(
  550. (rbuf.pPartitionInfoValue->szVolumeLabel[0] ? _T("%ls (%ls) ") : _T("%ls ")),
  551. rbuf.pPartitionInfoValue->szDeviceName,
  552. rbuf.pPartitionInfoValue->szVolumeLabel
  553. );
  554. rstr += strPartitionInfo;
  555. if (pdwSignature != NULL)
  556. {
  557. _ASSERTE(dwSignature != 0);
  558. *pdwSignature = dwSignature;
  559. } // if: caller wants signature as well
  560. } // try
  561. catch (...)
  562. {
  563. // Ignore all errors because there is really nothing we can do.
  564. // Displaying a message isn't really very useful.
  565. } // catch: Anything
  566. } // if: partition should be displayed
  567. } // else if: partition info
  568. // Advance the buffer pointer
  569. rbuf.pb += cbData;
  570. cbBuf -= cbData;
  571. } while ( (rbuf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK)
  572. && (rbuf.pSyntax->dw != CLUSPROP_SYNTAX_DISK_SIGNATURE));
  573. } // if: not an endmark
  574. return (rstr.GetLength() > 0);
  575. } //*** CPhysDiskParamsPage::BStringFromDiskInfo()
  576. /////////////////////////////////////////////////////////////////////////////
  577. //++
  578. //
  579. // CPhysDiskParamsPage::FillList
  580. //
  581. // Routine Description:
  582. // Fill the list of disks.
  583. //
  584. // Arguments:
  585. // None.
  586. //
  587. // Return Value:
  588. // None.
  589. //
  590. //--
  591. /////////////////////////////////////////////////////////////////////////////
  592. void CPhysDiskParamsPage::FillList(void)
  593. {
  594. CString strDisk;
  595. DWORD dwSignature;
  596. int icbox;
  597. // Clear the list first.
  598. m_cboxDisk.ResetContent();
  599. // Add the disk info first.
  600. if (m_cbDiskInfo > 0)
  601. {
  602. CLUSPROP_BUFFER_HELPER buf;
  603. buf.pb = m_pbDiskInfo;
  604. if (BStringFromDiskInfo(buf, m_cbDiskInfo, m_strDisk, &dwSignature))
  605. {
  606. ASSERT(dwSignature != 0);
  607. icbox = m_cboxDisk.AddString(m_strDisk);
  608. m_cboxDisk.SetItemData(icbox, dwSignature);
  609. } // if: disk info was found
  610. } // if: there is disk info
  611. // Now add the available disk info.
  612. if (m_cbAvailDiskInfo > 0)
  613. {
  614. CString strDisk;
  615. CLUSPROP_BUFFER_HELPER buf;
  616. buf.pb = m_pbAvailDiskInfo;
  617. while (buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK)
  618. {
  619. if (BStringFromDiskInfo(buf, m_cbAvailDiskInfo, strDisk, &dwSignature))
  620. {
  621. ASSERT(dwSignature != 0);
  622. icbox = m_cboxDisk.AddString(strDisk);
  623. m_cboxDisk.SetItemData(icbox, dwSignature);
  624. } // if: disk info was found
  625. } // while: more entries in the list
  626. } // if: there is available disk info
  627. // Now select an item in the list.
  628. if (m_strDisk.GetLength() > 0)
  629. {
  630. int nIndex;
  631. nIndex = m_cboxDisk.FindStringExact(-1, m_strDisk);
  632. m_cboxDisk.SetCurSel(nIndex);
  633. } // if: there is a selected item
  634. } //*** CPhysDiskParamsPage::FillList()