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.

1745 lines
46 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. FTMan
  5. File Name:
  6. Actions.cpp
  7. Abstract:
  8. Definition of global functions related to actions that can be performed in the tree and list views
  9. Every action function receives an array of CItemData items and performs the appropriate action on them
  10. Author:
  11. Cristian Teodorescu December 1, 1998
  12. Notes:
  13. Revision History:
  14. --*/
  15. #include "stdafx.h"
  16. #include "Resource.h"
  17. #include "ActDlg.h"
  18. #include "Actions.h"
  19. #include "DiskMap.h"
  20. #include "FrSpace.h"
  21. #include "FTTreeVw.h"
  22. #include "FTUtil.h"
  23. #include "Item.h"
  24. #include "LogVol.h"
  25. #include "MainFrm.h"
  26. #include "PhPart.h"
  27. #include "RootVol.h"
  28. #include <winbase.h>
  29. //////////////////////////////////////////////////////////////////////////////////////////////
  30. // Assign drive letter
  31. void ActionAssign( CObArray& arrSelectedItems )
  32. {
  33. MY_TRY
  34. CAutoRefresh ar(FALSE);
  35. CItemData* pData;
  36. ASSERT( arrSelectedItems.GetSize() == 1 );
  37. pData = (CItemData*)( arrSelectedItems[0] );
  38. ASSERT(pData);
  39. ASSERT( ( pData->GetItemType() == IT_LogicalVolume ) ||
  40. ( pData->GetItemType() == IT_PhysicalPartition ) );
  41. ASSERT( pData->IsRootVolume() && pData->IsValid() );
  42. CAssignDlg dlg( pData );
  43. if( dlg.DoModal() != IDOK )
  44. return;;
  45. AfxGetApp()->DoWaitCursor(1);
  46. TCHAR cOldDriveLetter = pData->GetDriveLetter();
  47. BOOL bResult = FALSE, bChanged = FALSE;
  48. // If the volume had a drive letter and now it shouldn't have any or it should have another one
  49. // then free the old drive letter
  50. if( cOldDriveLetter &&
  51. ( !dlg.m_bAssign || ( dlg.m_bAssign && ( cOldDriveLetter != dlg.m_cDriveLetter ) ) ) )
  52. {
  53. CString strMountPoint;
  54. strMountPoint.Format(_T("%c:\\"), cOldDriveLetter);
  55. bResult = DeleteVolumeMountPoint(strMountPoint);
  56. if( !bResult )
  57. {
  58. DisplaySystemErrorMessage( IDS_ERR_DELETE_MOUNT_POINT );
  59. AfxRefreshAll();
  60. AfxGetApp()->DoWaitCursor(-1);
  61. return;
  62. }
  63. else
  64. bChanged = TRUE;
  65. }
  66. // If the volume had a drive letter and now it should have another one or if it had no drive letter and
  67. // now it should have one then assign a the new drive letter to the volume
  68. if( dlg.m_bAssign &&
  69. ( ( cOldDriveLetter && ( cOldDriveLetter != dlg.m_cDriveLetter ) ) || !cOldDriveLetter ) )
  70. {
  71. CString strMountPoint, strVolumeName;
  72. strMountPoint.Format(_T("%c:\\"), dlg.m_cDriveLetter );
  73. strVolumeName = pData->GetVolumeName();
  74. strVolumeName += _T("\\");
  75. bResult = SetVolumeMountPoint( strMountPoint, strVolumeName );
  76. if( !bResult )
  77. DisplaySystemErrorMessage( IDS_ERR_SET_MOUNT_POINT );
  78. else
  79. bChanged = TRUE;
  80. }
  81. if( bResult )
  82. AfxMessageBox(IDS_MSG_ASSIGN, MB_ICONINFORMATION);
  83. if( bChanged )
  84. AfxRefreshAll();
  85. AfxGetApp()->DoWaitCursor(-1);
  86. MY_CATCH_AND_REPORT
  87. }
  88. void UpdateActionAssign( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  89. {
  90. // Action enabling conditions:
  91. // 1. 1 ( and only 1 ) item must be selected
  92. // 2. The selected item must be a root volume ( logical volume or physical partition )
  93. // 3. The selected item must be valid
  94. CItemData* pData;
  95. if( arrSelectedItems.GetSize() != 1 )
  96. goto label_disable;
  97. pData = (CItemData*)( arrSelectedItems[0] );
  98. ASSERT(pData);
  99. if( ( pData->GetItemType() != IT_LogicalVolume ) &&
  100. ( pData->GetItemType() != IT_PhysicalPartition ) )
  101. goto label_disable;
  102. if( !pData->IsRootVolume() || !pData->IsValid() )
  103. goto label_disable;
  104. pCmdUI->Enable(TRUE);
  105. return;
  106. label_disable:
  107. pCmdUI->Enable(FALSE);
  108. }
  109. //////////////////////////////////////////////////////////////////////////////////////////////
  110. // Break mirror
  111. /*
  112. void ActionFtbreak( CObArray& arrSelectedItems )
  113. {
  114. MY_TRY
  115. ASSERT( arrSelectedItems.GetSize() == 1 );
  116. ASSERT( m_pParentData->GetItemType() == IT_Root );
  117. CItemData* pData = (CItemData*)(arrSelectedItems[0]);
  118. ASSERT(pData);
  119. ASSERT( pData->GetItemType() == IT_LogicalVolume );
  120. CObArray arrVolumeData;
  121. arrVolumeData.Add(pData);
  122. CActionDlg dlg(&arrVolumeData);
  123. if( dlg.DoModal() != IDOK )
  124. return;
  125. FT_LOGICAL_DISK_ID llVolID;
  126. pData->GetVolumeID( llVolID );
  127. FTBreak( llVolID );
  128. AfxRefreshAll();
  129. MY_CATCH_AND_REPORT
  130. }
  131. */
  132. void ActionFtbreak( CObArray& arrSelectedItems)
  133. {
  134. MY_TRY
  135. CAutoRefresh ar(FALSE);
  136. CItemData* pData;
  137. ASSERT( arrSelectedItems.GetSize() == 1 );
  138. pData = (CItemData*)( arrSelectedItems[0] );
  139. ASSERT(pData);
  140. ASSERT( pData->GetItemType() == IT_LogicalVolume );
  141. ASSERT( pData->IsRootVolume() && pData->IsValid() );
  142. CLogicalVolumeData* pLogVolData = (CLogicalVolumeData*)pData;
  143. ASSERT( pLogVolData->m_nVolType == FtMirrorSet );
  144. // Read the members of the mirror
  145. CObArray arrMembersData;
  146. CString strErrors;
  147. if( !pLogVolData->ReadMembers( arrMembersData, strErrors ) )
  148. {
  149. AfxMessageBox( strErrors, MB_ICONSTOP );
  150. return;
  151. }
  152. CBreakDlg dlg( pLogVolData, &arrMembersData );
  153. if( dlg.DoModal() != IDOK )
  154. goto label_cleanup;
  155. AfxGetApp()->DoWaitCursor(1);
  156. if( dlg.m_nWinnerIndex == 1 )
  157. {
  158. // The winner is the second member. We have to orphan the first member ( if healthy )
  159. if( ((CItemData*)arrMembersData[0])->GetMemberStatus() == FtMemberHealthy )
  160. {
  161. if( !FTOrphan( pLogVolData->m_llVolID, 0 ) )
  162. {
  163. AfxGetApp()->DoWaitCursor(-1);
  164. goto label_cleanup;
  165. }
  166. }
  167. }
  168. else
  169. {
  170. ASSERT( dlg.m_nWinnerIndex == 0 );
  171. }
  172. // Break the mirror
  173. if( FTBreak( pLogVolData->m_llVolID ) )
  174. {
  175. CItemIDSet setTreeSelectedItems;
  176. CItemIDSet setListSelectedItems;
  177. CItemID idItem;
  178. // Now break all former members ( if they are FT Partitions )
  179. // All members must be added to setListSelectedItems in order to emphasize them after
  180. // refreshing the list view
  181. // Select the root volumes item in the tree view
  182. idItem.m_wItemType = IT_RootVolumes;
  183. setTreeSelectedItems.Add( idItem );
  184. for( int i = 0; i < arrMembersData.GetSize(); i++ )
  185. {
  186. BOOL bPhPart;
  187. CLogicalVolumeData* pMemberData = (CLogicalVolumeData*)(arrMembersData[i]);
  188. if( pMemberData->m_nVolType == FtPartition )
  189. bPhPart = FTBreak( pMemberData->m_llVolID );
  190. else
  191. bPhPart = FALSE;
  192. if( bPhPart )
  193. {
  194. // The member is now a physical partition
  195. ASSERT( pMemberData->m_nVolType == FtPartition );
  196. idItem.m_wItemType = IT_PhysicalPartition;
  197. idItem.m_ID.m_PhysicalPartitionID.m_ulDiskNumber = pMemberData->m_ConfigInfo.partConfig.Config.DiskNumber;
  198. idItem.m_ID.m_PhysicalPartitionID.m_llOffset = pMemberData->m_ConfigInfo.partConfig.Config.ByteOffset;
  199. }
  200. else
  201. {
  202. // The member is still a logical volume
  203. idItem.m_wItemType = IT_LogicalVolume;
  204. idItem.m_ID.m_LogicalVolumeID.m_llVolID = pMemberData->m_llVolID;
  205. }
  206. setListSelectedItems.Add( idItem );
  207. }
  208. AfxMessageBox( IDS_MSG_FTBREAK, MB_ICONINFORMATION );
  209. // Now refresh both views and emphasize the members of the old mirror set
  210. AfxRefreshAll( NULL, &setTreeSelectedItems, &setListSelectedItems );
  211. }
  212. else
  213. AfxRefreshAll();
  214. AfxGetApp()->DoWaitCursor(-1);
  215. label_cleanup:
  216. // Delete the array of members
  217. for( int i = 0; i < arrMembersData.GetSize(); i++ )
  218. {
  219. pData = (CItemData*)(arrMembersData[i]);
  220. if( pData )
  221. delete pData;
  222. }
  223. arrMembersData.RemoveAll();
  224. MY_CATCH_AND_REPORT
  225. }
  226. /*
  227. void UpdateActionFtbreak( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  228. {
  229. // This action should be enabled only when:
  230. // 1. single selection
  231. // 2. Its parent is the root item
  232. // 3. the selected item is a logical volume
  233. POSITION pos;
  234. if( ( arrSelectedItems.GetSize() != 1 ) ||
  235. ( m_pParentData->GetItemType() != IT_Root) )
  236. goto label_disable;
  237. pData = (CItemData*)(arrSelectedItems[0]);
  238. ASSERT(pData);
  239. if( pData->GetTreeItemType() != IT_LogicalVolume )
  240. goto label_disable;
  241. pCmdUI->Enable(TRUE);
  242. return;
  243. label_disable:
  244. pCmdUI->Enable(FALSE);
  245. }
  246. */
  247. void UpdateActionFtbreak( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  248. {
  249. // Action enabling conditions:
  250. // 1. 1 ( and only 1 ) item must be selected
  251. // 2. The selected item must be a root volume
  252. // 3. The selected item must be a mirror set
  253. // 4. The selected item must be valid
  254. CItemData* pData;
  255. if( arrSelectedItems.GetSize() != 1 )
  256. goto label_disable;
  257. pData = (CItemData*)(arrSelectedItems[0]);
  258. ASSERT(pData);
  259. if( pData->GetItemType() != IT_LogicalVolume )
  260. goto label_disable;
  261. if( !pData->IsRootVolume() || !pData->IsValid() )
  262. goto label_disable;
  263. if( ((CLogicalVolumeData*)pData)->m_nVolType != FtMirrorSet )
  264. goto label_disable;
  265. pCmdUI->Enable(TRUE);
  266. return;
  267. label_disable:
  268. pCmdUI->Enable(FALSE);
  269. }
  270. //////////////////////////////////////////////////////////////////////////////////////////////
  271. // Create extended partition
  272. void ActionCreateExtendedPartition( CObArray& arrSelectedItems )
  273. {
  274. MY_TRY
  275. CAutoRefresh ar(FALSE);
  276. CItemData* pData;
  277. ASSERT( arrSelectedItems.GetSize() == 1 );
  278. pData = (CItemData*)(arrSelectedItems[0]);
  279. ASSERT(pData);
  280. ASSERT( pData->GetItemType() == IT_FreeSpace );
  281. CFreeSpaceData* pFreeData = (CFreeSpaceData*)pData;
  282. ASSERT( pFreeData->m_wFreeSpaceType == FST_Primary );
  283. if( pFreeData->m_dwExtendedPartitionCountOnLevel > 0 )
  284. {
  285. // There is another extended partition on the disk
  286. AfxMessageBox( IDS_ERR_ANOTHER_EXTENDED_PARTITION, MB_ICONSTOP );
  287. return;
  288. }
  289. if( pFreeData->m_dwPartitionCountOnLevel + pFreeData->m_dwExtendedPartitionCountOnLevel >= 4 )
  290. {
  291. // This must not happen inside an extended partition!
  292. AfxMessageBox( IDS_ERR_PARTITION_TABLE_FULL, MB_ICONSTOP );
  293. return;
  294. }
  295. // The starting offset of the extended partition must be the next cylinder border after the beginning of the free space
  296. LONGLONG llExtPartStartOffset = ((LONGLONG)((pFreeData->m_llOffset + pFreeData->m_llCylinderSize - 1) / pFreeData->m_llCylinderSize)) * pFreeData->m_llCylinderSize;
  297. CCreatePartitionDlg dlg( pFreeData, llExtPartStartOffset, TRUE );
  298. if( dlg.DoModal() != IDOK )
  299. return;;
  300. AfxGetApp()->DoWaitCursor(1);
  301. CDiskMap diskMap( pFreeData->m_dwDiskNumber );
  302. LONGLONG llNewFreeSpaceOffset;
  303. BOOL bResult = diskMap.CreateExtendedPartition( llExtPartStartOffset, dlg.m_llPartitionSize, llNewFreeSpaceOffset );
  304. if( bResult )
  305. {
  306. AfxMessageBox( IDS_MSG_CREATE_EXTENDED_PARTITION, MB_ICONINFORMATION );
  307. // Now refresh both views and emphasize the new partition
  308. CItemIDSet setTreeSelectedItems;
  309. CItemIDSet setListSelectedItems;
  310. CItemID idItem;
  311. idItem.m_wItemType = IT_RootFreeSpaces;
  312. setTreeSelectedItems.Add( idItem );
  313. idItem.m_wItemType = IT_FreeSpace;
  314. idItem.m_ID.m_FreeSpaceID.m_ulDiskNumber = pFreeData->m_dwDiskNumber;
  315. idItem.m_ID.m_FreeSpaceID.m_llOffset = llNewFreeSpaceOffset;
  316. setListSelectedItems.Add( idItem );
  317. AfxRefreshAll( NULL, &setTreeSelectedItems, &setListSelectedItems );
  318. }
  319. else
  320. {
  321. AfxMessageBox( IDS_ERR_CREATE_EXTENDED_PARTITION, MB_ICONSTOP );
  322. AfxRefreshAll();
  323. }
  324. AfxGetApp()->DoWaitCursor(-1);
  325. MY_CATCH_AND_REPORT
  326. }
  327. void UpdateActionCreateExtendedPartition( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  328. {
  329. // Action enabling conditions:
  330. // 1. 1 ( and only 1 ) item must be selected
  331. // 2. The selected item must be a free space
  332. // 3. The free space must be primary ( between primary partitions )
  333. CItemData* pData;
  334. CFreeSpaceData* pFreeData;
  335. if( arrSelectedItems.GetSize() != 1 )
  336. goto label_disable;
  337. pData = (CItemData*)(arrSelectedItems[0]);
  338. ASSERT(pData);
  339. if( pData->GetItemType() != IT_FreeSpace )
  340. goto label_disable;
  341. pFreeData = (CFreeSpaceData*)pData;
  342. if( pFreeData->m_wFreeSpaceType != FST_Primary )
  343. goto label_disable;
  344. pCmdUI->Enable(TRUE);
  345. return;
  346. label_disable:
  347. pCmdUI->Enable(FALSE);
  348. }
  349. //////////////////////////////////////////////////////////////////////////////////////////////
  350. // Create partition
  351. void ActionCreatePartition( CObArray& arrSelectedItems )
  352. {
  353. MY_TRY
  354. CAutoRefresh ar(FALSE);
  355. CItemData* pData;
  356. ASSERT( arrSelectedItems.GetSize() == 1 );
  357. pData = (CItemData*)(arrSelectedItems[0]);
  358. ASSERT(pData);
  359. ASSERT( pData->GetItemType() == IT_FreeSpace );
  360. CFreeSpaceData* pFreeData = (CFreeSpaceData*)pData;
  361. if( pFreeData->m_dwPartitionCountOnLevel + pFreeData->m_dwExtendedPartitionCountOnLevel >= 4 )
  362. {
  363. // This must not happen inside an extended partition!
  364. ASSERT( pFreeData->m_wFreeSpaceType == FST_Primary );
  365. AfxMessageBox( IDS_ERR_PARTITION_TABLE_FULL, MB_ICONSTOP );
  366. return;
  367. }
  368. CCreatePartitionDlg dlg( pFreeData, pFreeData->m_llOffset );
  369. if( dlg.DoModal() != IDOK )
  370. return;;
  371. AfxGetApp()->DoWaitCursor(1);
  372. CDiskMap diskMap( pFreeData->m_dwDiskNumber );
  373. LONGLONG llExactPartStartOffset;
  374. BOOL bResult = diskMap.CreatePartition( pFreeData->m_llOffset, dlg.m_llPartitionSize, llExactPartStartOffset );
  375. if( bResult )
  376. {
  377. AfxMessageBox( IDS_MSG_CREATE_PARTITION, MB_ICONINFORMATION );
  378. // Now refresh both views and emphasize the new partition
  379. CItemIDSet setTreeSelectedItems;
  380. CItemIDSet setListSelectedItems;
  381. CItemID idItem;
  382. idItem.m_wItemType = IT_RootVolumes;
  383. setTreeSelectedItems.Add( idItem );
  384. idItem.m_wItemType = IT_PhysicalPartition;
  385. idItem.m_ID.m_PhysicalPartitionID.m_ulDiskNumber = pFreeData->m_dwDiskNumber;
  386. idItem.m_ID.m_PhysicalPartitionID.m_llOffset = llExactPartStartOffset;
  387. setListSelectedItems.Add( idItem );
  388. AfxRefreshAll( NULL, &setTreeSelectedItems, &setListSelectedItems );
  389. }
  390. else
  391. {
  392. AfxMessageBox( IDS_ERR_CREATE_PARTITION, MB_ICONSTOP );
  393. AfxRefreshAll();
  394. }
  395. AfxGetApp()->DoWaitCursor(-1);
  396. MY_CATCH_AND_REPORT
  397. }
  398. void UpdateActionCreatePartition( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  399. {
  400. // Action enabling conditions:
  401. // 1. 1 ( and only 1 ) item must be selected
  402. // 2. The selected item must be a free space
  403. CItemData* pData;
  404. if( arrSelectedItems.GetSize() != 1 )
  405. goto label_disable;
  406. pData = (CItemData*)(arrSelectedItems[0]);
  407. ASSERT(pData);
  408. if( pData->GetItemType() != IT_FreeSpace )
  409. goto label_disable;
  410. pCmdUI->Enable(TRUE);
  411. return;
  412. label_disable:
  413. pCmdUI->Enable(FALSE);
  414. }
  415. //////////////////////////////////////////////////////////////////////////////////////////////
  416. // Delete
  417. void ActionDelete( CObArray& arrSelectedItems )
  418. {
  419. MY_TRY
  420. CAutoRefresh ar(FALSE);
  421. CItemData* pData;
  422. ASSERT( arrSelectedItems.GetSize() == 1 );
  423. pData = (CItemData*)(arrSelectedItems[0]);
  424. ASSERT(pData);
  425. // A special case is when the selected item is an empty extended partition
  426. if( pData->GetItemType() == IT_FreeSpace )
  427. {
  428. CFreeSpaceData* pFree = (CFreeSpaceData*)pData;
  429. ASSERT(pFree->m_wFreeSpaceType == FST_EmptyExtendedPartition );
  430. CString strQuestion;
  431. strQuestion.Format( IDS_QST_DELETE_EXTENDED_PARTITION, pFree->m_dwDiskNumber );
  432. if( IDYES != AfxMessageBox(strQuestion, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2 ) )
  433. return;
  434. CDiskMap diskMap( pFree->m_dwDiskNumber );
  435. if( diskMap.DeleteExtendedPartition( pFree->m_llOffset ) )
  436. {
  437. CItemIDSet setTreeSelectedItems;
  438. CItemID idItem;
  439. idItem.m_wItemType = IT_RootFreeSpaces;
  440. setTreeSelectedItems.Add( idItem );
  441. AfxMessageBox( IDS_MSG_DELETE_EXTENDED_PARTITION, MB_ICONINFORMATION );
  442. AfxRefreshAll( NULL, &setTreeSelectedItems, NULL );
  443. }
  444. else
  445. {
  446. AfxMessageBox( IDS_ERR_DELETE_EXTENDED_PARTITION, MB_ICONSTOP );
  447. AfxRefreshAll();
  448. }
  449. return;
  450. }
  451. ASSERT( ( pData->GetItemType() == IT_LogicalVolume ) ||
  452. ( pData->GetItemType() == IT_PhysicalPartition ) );
  453. ASSERT( pData->IsRootVolume() && pData->IsValid() );
  454. CString strQuestion, strName;
  455. pData->GetDisplayExtendedName(strName);
  456. strQuestion.Format( IDS_QST_DELETE_VOLUME, strName );
  457. if( IDYES != AfxMessageBox(strQuestion, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2 ) )
  458. return;
  459. // Delete the volume
  460. BOOL bResult;
  461. AfxGetApp()->DoWaitCursor(1);
  462. if( pData->GetItemType() == IT_LogicalVolume )
  463. {
  464. FT_LOGICAL_DISK_ID llVolID;
  465. ((CLogicalVolumeData*)pData)->GetVolumeID(llVolID);
  466. bResult = FTDelete( llVolID );
  467. }
  468. else if( pData->GetItemType() == IT_PhysicalPartition )
  469. {
  470. CDiskMap diskMap( ((CPhysicalPartitionData*)pData)->m_dwDiskNumber );
  471. bResult = diskMap.DeletePartition( ((CPhysicalPartitionData*)pData)->m_PartInfo.StartingOffset.QuadPart );
  472. }
  473. else
  474. ASSERT(FALSE);
  475. if( bResult )
  476. {
  477. CItemIDSet setTreeSelectedItems;
  478. CItemID idItem;
  479. idItem.m_wItemType = IT_RootVolumes;
  480. setTreeSelectedItems.Add( idItem );
  481. AfxMessageBox( IDS_MSG_DELETE_VOLUME, MB_ICONINFORMATION );
  482. AfxRefreshAll( NULL, &setTreeSelectedItems, NULL );
  483. }
  484. else
  485. {
  486. if( pData->GetItemType() == IT_LogicalVolume )
  487. AfxMessageBox(IDS_ERR_DELETE_LOGICAL_VOLUME, MB_ICONSTOP );
  488. else if( pData->GetItemType() == IT_PhysicalPartition )
  489. AfxMessageBox( IDS_ERR_DELETE_PHYSICAL_PARTITION, MB_ICONSTOP );
  490. AfxRefreshAll();
  491. }
  492. AfxGetApp()->DoWaitCursor(-1);
  493. MY_CATCH_AND_REPORT
  494. }
  495. void UpdateActionDelete( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  496. {
  497. // Action enabling conditions:
  498. // 1. 1 ( and only 1 ) item must be selected
  499. // 2. The selected item must be a root volume ( logical volume or physical partition )
  500. // 3. The selected item must be valid
  501. //OR
  502. // 1. 1 ( and only 1 ) item must be selected
  503. // 2. The selected item is an empty extended partition
  504. CItemData* pData;
  505. if( arrSelectedItems.GetSize() != 1 )
  506. goto label_disable;
  507. pData = (CItemData*)(arrSelectedItems[0]);
  508. ASSERT(pData);
  509. if( ( pData->GetItemType() != IT_LogicalVolume ) &&
  510. ( pData->GetItemType() != IT_PhysicalPartition ) )
  511. {
  512. if( ( pData->GetItemType() == IT_FreeSpace ) && ( ((CFreeSpaceData*)pData)->m_wFreeSpaceType == FST_EmptyExtendedPartition ) )
  513. goto label_enable;
  514. else
  515. goto label_disable;
  516. }
  517. if( !pData->IsRootVolume() || !pData->IsValid() )
  518. goto label_disable;
  519. label_enable:
  520. pCmdUI->Enable(TRUE);
  521. return;
  522. label_disable:
  523. pCmdUI->Enable(FALSE);
  524. }
  525. //////////////////////////////////////////////////////////////////////////////////////////////
  526. // Regenerate an orphan member of a mirror set or stripe set with parity
  527. void ActionFtinit( CObArray& arrSelectedItems )
  528. {
  529. MY_TRY
  530. CAutoRefresh ar(FALSE);
  531. ASSERT( arrSelectedItems.GetSize() == 1 );
  532. CItemData* pData = (CItemData*)(arrSelectedItems[0]);
  533. ASSERT(pData);
  534. ASSERT( pData->GetItemType() == IT_LogicalVolume );
  535. ASSERT( pData->IsValid() );
  536. CLogicalVolumeData* pMemberData = (CLogicalVolumeData*)pData;
  537. CItemData* pParentData = pData->GetParentData();
  538. ASSERT( pParentData );
  539. ASSERT( pParentData->GetItemType() == IT_LogicalVolume );
  540. CLogicalVolumeData* pLVParentData = (CLogicalVolumeData*)pParentData;
  541. ASSERT( ( pLVParentData->m_nVolType == FtMirrorSet ) ||
  542. ( pLVParentData->m_nVolType == FtStripeSetWithParity ) );
  543. ASSERT( pLVParentData->m_StateInfo.stripeState.UnhealthyMemberState == FtMemberOrphaned );
  544. ASSERT( pLVParentData->m_StateInfo.stripeState.UnhealthyMemberNumber == ((CLogicalVolumeData*)pData)->m_unMemberIndex );
  545. CString strMemberDisplayName, strParentDisplayName, strQuestion;
  546. pData->GetDisplayExtendedName( strMemberDisplayName );
  547. pLVParentData->GetDisplayExtendedName( strParentDisplayName );
  548. strQuestion.Format( IDS_QST_FTINIT, strMemberDisplayName, strParentDisplayName );
  549. if( IDYES != AfxMessageBox(strQuestion, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2 ) )
  550. return;
  551. AfxGetApp()->DoWaitCursor(1);
  552. // Now is time to reinitialize the member
  553. if( FTInit( pLVParentData->m_llVolID, TRUE ) )
  554. AfxMessageBox( IDS_MSG_FTINIT, MB_ICONINFORMATION );
  555. AfxRefreshAll();
  556. AfxGetApp()->DoWaitCursor(-1);
  557. MY_CATCH_AND_REPORT
  558. }
  559. void UpdateActionFtinit( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  560. {
  561. // Action enabling conditions:
  562. // 1. 1 ( and only one ) item must be selected
  563. // 2. The selected item is a logical volume
  564. // 3. The parent of the item must be a mirror set or a stripe set with parity
  565. // 4. The selected item must be valid
  566. // 5. The selected item is an orphan member of its parent
  567. CItemData* pData;
  568. CItemData* pParentData;
  569. CLogicalVolumeData* pLVParentData;
  570. if( arrSelectedItems.GetSize() != 1 )
  571. goto label_disable;
  572. pData = (CItemData*)(arrSelectedItems[0]);
  573. ASSERT(pData);
  574. if( pData->GetItemType() != IT_LogicalVolume )
  575. goto label_disable;
  576. if( !pData->IsValid() )
  577. goto label_disable;
  578. pParentData = pData->GetParentData();
  579. if( ( pParentData == NULL ) || ( pParentData->GetItemType() != IT_LogicalVolume ) )
  580. goto label_disable;
  581. pLVParentData = (CLogicalVolumeData*)pParentData;
  582. if( ( pLVParentData->m_nVolType != FtMirrorSet ) &&
  583. ( pLVParentData->m_nVolType != FtStripeSetWithParity ) )
  584. goto label_disable;
  585. if( pLVParentData->m_StateInfo.stripeState.UnhealthyMemberState != FtMemberOrphaned )
  586. goto label_disable;
  587. if( pLVParentData->m_StateInfo.stripeState.UnhealthyMemberNumber != ((CLogicalVolumeData*)pData)->m_unMemberIndex )
  588. goto label_disable;
  589. pCmdUI->Enable( TRUE );
  590. return;
  591. label_disable:
  592. pCmdUI->Enable(FALSE);
  593. }
  594. //////////////////////////////////////////////////////////////////////////////////////////////
  595. // Create mirror
  596. void ActionFtmirror( CObArray& arrSelectedItems )
  597. {
  598. MY_TRY
  599. CAutoRefresh ar(FALSE);
  600. int nNumVols = (int)arrSelectedItems.GetSize();
  601. ASSERT( nNumVols == 2 );
  602. for( int i = 0; i < nNumVols; i++ )
  603. {
  604. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  605. ASSERT(pData);
  606. ASSERT( ( pData->GetItemType() == IT_LogicalVolume ) ||
  607. ( pData->GetItemType() == IT_PhysicalPartition ) );
  608. ASSERT( pData->IsRootVolume() && pData->IsValid() );
  609. }
  610. // Display the dialog
  611. CActionDlg dlg(&arrSelectedItems, IDD_CREATE_MIRROR);
  612. if( dlg.DoModal() != IDOK )
  613. return;
  614. // Display the warning. All data of the second volume will be lost
  615. CString strDisplayName, strNameList, strWarning;
  616. for( i = 1; i < arrSelectedItems.GetSize(); i++ )
  617. {
  618. CItemData* pVolData = (CItemData*)(arrSelectedItems[i]);
  619. ASSERT(pVolData);
  620. pVolData->GetDisplayExtendedName(strDisplayName);
  621. if( i != 1 )
  622. strNameList += _T(", ");
  623. strNameList += _T("\"");
  624. strNameList += strDisplayName;
  625. strNameList += _T("\"");
  626. }
  627. strWarning.Format( IDS_WRN_DATA_LOST, strNameList );
  628. if( IDYES != AfxMessageBox(strWarning, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2 ) )
  629. return;
  630. AfxGetApp()->DoWaitCursor(1);
  631. // Make sure that all selected physical partitions are converted to FT partitions
  632. // and then get all selected items logical volume ID's
  633. FT_LOGICAL_DISK_ID* arrVolID = (FT_LOGICAL_DISK_ID*)LocalAlloc(0, nNumVols*sizeof(FT_LOGICAL_DISK_ID) );
  634. if( !arrVolID )
  635. {
  636. AfxMessageBox(IDS_ERR_ALLOCATION, MB_ICONSTOP );
  637. return;
  638. }
  639. if( !ConvertPartitionsToFT( arrSelectedItems, arrVolID ) )
  640. {
  641. LocalFree(arrVolID);
  642. AfxRefreshAll();
  643. AfxGetApp()->DoWaitCursor(-1);
  644. return;
  645. }
  646. FT_LOGICAL_DISK_ID llNewSetID;
  647. if( FTMirror( arrVolID, (WORD)nNumVols, &llNewSetID ) )
  648. {
  649. AfxMessageBox( IDS_MSG_FTMIRROR, MB_ICONINFORMATION );
  650. // Refresh all and emphasize the newly created mirror
  651. CItemIDSet setTreeSelectedItems;
  652. CItemIDSet setListSelectedItems;
  653. CItemID idItem;
  654. idItem.m_wItemType = IT_RootVolumes;
  655. setTreeSelectedItems.Add( idItem );
  656. idItem.m_wItemType = IT_LogicalVolume;
  657. idItem.m_ID.m_LogicalVolumeID.m_llVolID = llNewSetID;
  658. setListSelectedItems.Add(idItem);
  659. AfxRefreshAll( NULL, &setTreeSelectedItems, &setListSelectedItems );
  660. }
  661. else
  662. {
  663. DeconvertPartitionsFromFT( arrSelectedItems, arrVolID );
  664. AfxRefreshAll();
  665. }
  666. LocalFree(arrVolID);
  667. AfxGetApp()->DoWaitCursor(-1);
  668. MY_CATCH_AND_REPORT
  669. }
  670. void UpdateActionFtmirror( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  671. {
  672. MY_TRY
  673. // Action enabling conditions:
  674. // 1. 2 ( and only 2 ) items must be selected
  675. // 2. Every selected item must be a root volume ( logical volume or physical partition )
  676. // 3. Every selected item must be valid
  677. // 4. The disks sets intersection for every couple of selected items must be empty !
  678. int i;
  679. if( arrSelectedItems.GetSize() != 2 )
  680. goto label_disable;
  681. for( i = 0; i < arrSelectedItems.GetSize(); i++ )
  682. {
  683. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  684. ASSERT(pData);
  685. if( ( pData->GetItemType() != IT_LogicalVolume ) &&
  686. ( pData->GetItemType() != IT_PhysicalPartition ) )
  687. goto label_disable;
  688. if( !pData->IsRootVolume() || !pData->IsValid() )
  689. goto label_disable;
  690. for( int j = 0; j < i; j++ )
  691. {
  692. CItemData* pData2 = (CItemData*)(arrSelectedItems[j]);
  693. CULONGSet setIntersection( pData->GetDisksSet() );
  694. setIntersection *= pData2->GetDisksSet();
  695. if( !setIntersection.IsEmpty() )
  696. goto label_disable;
  697. }
  698. }
  699. pCmdUI->Enable( TRUE );
  700. return;
  701. label_disable:
  702. pCmdUI->Enable(FALSE);
  703. MY_CATCH
  704. }
  705. /*
  706. //////////////////////////////////////////////////////////////////////////////////////////////
  707. // Orphan member
  708. void ActionFtorphan( CObArray& arrSelectedItems )
  709. {
  710. MY_TRY
  711. CAutoRefresh ar(FALSE);
  712. ASSERT( arrSelectedItems.GetSize() == 1 );
  713. CItemData* pData = (CItemData*)(arrSelectedItems[0]);
  714. ASSERT(pData);
  715. ASSERT( pData->GetItemType() == IT_LogicalVolume );
  716. CItemData* pParentData = pData->GetParentData();
  717. ASSERT( pParentData );
  718. ASSERT( pParentData->GetItemType() == IT_LogicalVolume );
  719. ASSERT( ( ((CLogicalVolumeData*)pParentData)->m_nVolType == FtMirrorSet ) ||
  720. ( ((CLogicalVolumeData*)pParentData)->m_nVolType == FtStripeSetWithParity ) );
  721. CObArray arrVolumeData;
  722. arrVolumeData.Add(pData);
  723. CActionDlg dlg(&arrSelectedItems);
  724. if( dlg.DoModal() != IDOK )
  725. return;
  726. FT_LOGICAL_DISK_ID llVolID;
  727. pLogVolData->GetVolumeID( llVolID );
  728. AfxGetApp()->DoWaitCursor(1);
  729. if( FTOrphan( llVolID, iItem ) )
  730. AfxRefreshAll();
  731. AfxGetApp()->DoWaitCursor(-1);
  732. MY_CATCH_AND_REPORT
  733. }
  734. void UpdateActionFtorphan( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  735. {
  736. // This action should be enabled only when:
  737. // 1. single selection
  738. // 2. The selected item is a logical volume
  739. // 3. the parent is a Mirror or Stripe with parity
  740. CItemData* pData, pParentData;
  741. if( arrSelectedItems.GetSize() != 1 )
  742. goto label_disable;
  743. pData = (CItemData*)(arrSelectedItems[0]);
  744. ASSERT(pData);
  745. if( pData->GetItemType() != IT_LogicalVolume )
  746. goto label_disable;
  747. pParentData = pData->GetParentData();
  748. if( ( pParentData == NULL ) || ( pParentData->GetItemType() != IT_LogicalVolume ) )
  749. goto label_disable;
  750. if( ( ((CLogicalVolumeData*)pParentData)->m_nVolType != FtMirrorSet ) &&
  751. ( ((CLogicalVolumeData*)pParentData)->m_nVolType != FtStripeSetWithParity ) )
  752. goto label_disable;
  753. pCmdUI->Enable( TRUE );
  754. return;
  755. label_disable:
  756. pCmdUI->Enable(FALSE);
  757. }
  758. */
  759. /*
  760. //////////////////////////////////////////////////////////////////////////////////////////////
  761. // Create FT partition
  762. void ActionFtpart( CObArray& arrSelectedItems )
  763. {
  764. MY_TRY
  765. CAutoRefresh ar(FALSE);
  766. ASSERT( arrSelectedItems.GetSize() == 1 );
  767. CItemData* pData = (CItemData*)(arrSelectedItems[0]);
  768. ASSERT(pData);
  769. ASSERT( pData->GetItemType() == IT_PhysicalPartition );
  770. CActionDlg dlg(&arrSelectedItems);
  771. if( dlg.DoModal() != IDOK )
  772. return;
  773. CPhysicalPartitionData* pPhPartData = (CPhysicalPartitionData*)pData;
  774. ASSERT( !pPhPartData->IsFTPartition() );
  775. ASSERT( !pData->GetVolumeName().IsEmpty() );
  776. AfxGetApp()->DoWaitCursor(1);
  777. FTPart( pPhPartData->GetVolumeName(), pPhPartData->GetDriveLetter() );
  778. AfxRefreshAll();
  779. AfxGetApp()->DoWaitCursor(-1);
  780. MY_CATCH_AND_REPORT
  781. }
  782. void UpdateActionFtpart( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  783. {
  784. // This action should be enabled only when:
  785. // 1. single selection
  786. // 2. the selected item is a physical partition
  787. // 3. This partition is not a FT partition
  788. // 4. We have a volume name for this partition
  789. CItemData* pData;
  790. if( arrSelectedItems.GetSize() != 1 )
  791. goto label_disable;
  792. pData = (CItemData*)(arrSelectedItems[0]);
  793. ASSERT(pData);
  794. if( pData->GetItemType() != IT_PhysicalPartition )
  795. goto label_disable;
  796. if( ((CPhysicalPartitionData*)pData)->IsFTPartition() )
  797. goto label_disable;
  798. if( pData->GetVolumeName().IsEmpty() )
  799. goto label_disable;
  800. pCmdUI->Enable( TRUE );
  801. return;
  802. label_disable:
  803. pCmdUI->Enable(FALSE);
  804. }
  805. */
  806. //////////////////////////////////////////////////////////////////////////////////////////////
  807. // Create stripe set
  808. void ActionFtstripe( CObArray& arrSelectedItems )
  809. {
  810. MY_TRY
  811. CAutoRefresh ar(FALSE);
  812. int nNumVols = (int)arrSelectedItems.GetSize();
  813. ASSERT( nNumVols >= 2 );
  814. for( int i = 0; i < nNumVols; i++ )
  815. {
  816. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  817. ASSERT(pData);
  818. ASSERT( ( pData->GetItemType() == IT_LogicalVolume ) ||
  819. ( pData->GetItemType() == IT_PhysicalPartition ) );
  820. ASSERT( pData->IsRootVolume() && pData->IsValid() );
  821. }
  822. // Display the dialog
  823. CCreateStripeDlg dlg(&arrSelectedItems);
  824. if( dlg.DoModal() != IDOK )
  825. return;
  826. // Display the warning. All data of selected volumes will be lost
  827. CString strDisplayName, strNameList, strWarning;
  828. for( i = 0; i < arrSelectedItems.GetSize(); i++ )
  829. {
  830. CItemData* pVolData = (CItemData*)(arrSelectedItems[i]);
  831. ASSERT(pVolData);
  832. pVolData->GetDisplayExtendedName(strDisplayName);
  833. if( i != 0 )
  834. strNameList += _T(", ");
  835. strNameList += _T("\"");
  836. strNameList += strDisplayName;
  837. strNameList += _T("\"");
  838. }
  839. strWarning.Format( IDS_WRN_DATA_LOST, strNameList );
  840. if( IDYES != AfxMessageBox(strWarning, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2 ) )
  841. return;
  842. AfxGetApp()->DoWaitCursor(1);
  843. // Make sure that all selected physical partitions are converted to FT partitions
  844. // and then get all selected items logical volume ID's
  845. FT_LOGICAL_DISK_ID* arrVolID = (FT_LOGICAL_DISK_ID*)LocalAlloc(0, nNumVols*sizeof(FT_LOGICAL_DISK_ID) );
  846. if( !arrVolID )
  847. {
  848. AfxMessageBox(IDS_ERR_ALLOCATION, MB_ICONSTOP );
  849. return;
  850. }
  851. if( !ConvertPartitionsToFT( arrSelectedItems, arrVolID ) )
  852. {
  853. LocalFree(arrVolID);
  854. AfxRefreshAll();
  855. AfxGetApp()->DoWaitCursor(-1);
  856. return;
  857. }
  858. FT_LOGICAL_DISK_ID llNewSetID;
  859. if( FTStripe( arrVolID, (WORD)nNumVols, dlg.m_ulStripeSize, &llNewSetID) )
  860. {
  861. AfxMessageBox( IDS_MSG_FTSTRIPE, MB_ICONINFORMATION );
  862. // Refresh all and emphasize the newly created stripe set
  863. CItemIDSet setTreeSelectedItems;
  864. CItemIDSet setListSelectedItems;
  865. CItemID idItem;
  866. idItem.m_wItemType = IT_RootVolumes;
  867. setTreeSelectedItems.Add( idItem );
  868. idItem.m_wItemType = IT_LogicalVolume;
  869. idItem.m_ID.m_LogicalVolumeID.m_llVolID = llNewSetID;
  870. setListSelectedItems.Add(idItem);
  871. AfxRefreshAll( NULL, &setTreeSelectedItems, &setListSelectedItems );
  872. }
  873. else
  874. {
  875. DeconvertPartitionsFromFT( arrSelectedItems, arrVolID );
  876. AfxRefreshAll();
  877. }
  878. LocalFree(arrVolID);
  879. AfxGetApp()->DoWaitCursor(-1);
  880. MY_CATCH_AND_REPORT
  881. }
  882. void UpdateActionFtstripe( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  883. {
  884. MY_TRY
  885. // Action enabling conditions:
  886. // 1. 2 or more items must be selected
  887. // 2. Every selected item must be a root volume ( logical volume or physical partition )
  888. // 3. Every selected item must be valid
  889. // 4. The disks sets intersection for every couple of selected items must be empty !
  890. int i;
  891. if( arrSelectedItems.GetSize() < 2 )
  892. goto label_disable;
  893. for( i = 0; i < arrSelectedItems.GetSize(); i++ )
  894. {
  895. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  896. ASSERT(pData);
  897. if( ( pData->GetItemType() != IT_LogicalVolume ) &&
  898. ( pData->GetItemType() != IT_PhysicalPartition ) )
  899. goto label_disable;
  900. if( !pData->IsRootVolume() || !pData->IsValid() )
  901. goto label_disable;
  902. for( int j = 0; j < i; j++ )
  903. {
  904. CItemData* pData2 = (CItemData*)(arrSelectedItems[j]);
  905. CULONGSet setIntersection( pData->GetDisksSet() );
  906. setIntersection *= pData2->GetDisksSet();
  907. if( !setIntersection.IsEmpty() )
  908. goto label_disable;
  909. }
  910. }
  911. pCmdUI->Enable( TRUE );
  912. return;
  913. label_disable:
  914. pCmdUI->Enable(FALSE);
  915. MY_CATCH
  916. }
  917. //////////////////////////////////////////////////////////////////////////////////////////////
  918. // Swap a member of a mirror set or of a stripe set with parity
  919. void ActionFtswap( CObArray& arrSelectedItems )
  920. {
  921. MY_TRY
  922. CAutoRefresh ar(FALSE);
  923. ASSERT( arrSelectedItems.GetSize() == 1 );
  924. CItemData* pData = (CItemData*)(arrSelectedItems[0]);
  925. ASSERT(pData);
  926. ASSERT( pData->GetItemType() == IT_LogicalVolume );
  927. ASSERT( pData->IsValid() );
  928. CLogicalVolumeData* pMemberData = (CLogicalVolumeData*)pData;
  929. CItemData* pParentData = pData->GetParentData();
  930. ASSERT( pParentData );
  931. ASSERT( pParentData->GetItemType() == IT_LogicalVolume );
  932. CLogicalVolumeData* pLVParentData = (CLogicalVolumeData*)pParentData;
  933. ASSERT( ( pLVParentData->m_nVolType == FtMirrorSet ) ||
  934. ( pLVParentData->m_nVolType == FtStripeSetWithParity ) );
  935. // Now get all possible replacements for the selected member
  936. // Conditions for possible replacements:
  937. // 1. Must be a root volume
  938. // 2. Must be at least as big as the member size of the mirror or stripe set with parity
  939. // 3. Must be valid
  940. // 4. Must not be the parent of the selected member
  941. // 5. Its disks set must not intersect with the reunion of all other members disks sets. And if its
  942. // forefathers to the root are also members of mirrors, stripes or stripe sets with parity take
  943. // also their siblings into consideration
  944. AfxGetApp()->DoWaitCursor(1);
  945. // So, first read all logical volumes
  946. CRootVolumesData objRoot;
  947. CObArray arrVolumeData;
  948. CString strErrors;
  949. if( !objRoot.ReadMembers( arrVolumeData, strErrors ) )
  950. {
  951. AfxMessageBox( strErrors, MB_ICONSTOP );
  952. AfxGetApp()->DoWaitCursor(-1);
  953. return;
  954. }
  955. // Second get the member size of the parent set
  956. LONGLONG llMemberSize;
  957. if( pLVParentData->m_nVolType == FtMirrorSet )
  958. llMemberSize = pLVParentData->m_ConfigInfo.mirrorConfig.MemberSize;
  959. else if ( pLVParentData->m_nVolType == FtStripeSetWithParity )
  960. llMemberSize = pLVParentData->m_ConfigInfo.swpConfig.MemberSize;
  961. else
  962. ASSERT(FALSE);
  963. // Third get the reunion of all other siblings and forefathers' siblings disks set
  964. CULONGSet setForbiddenDisks;
  965. CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
  966. CFTTreeView* pLeftView = (CFTTreeView*)(pFrame->GetLeftPane());
  967. ASSERT( pLeftView );
  968. GetVolumeReplacementForbiddenDisksSet( pLeftView, pMemberData, setForbiddenDisks );
  969. // Now select only those root volumes that match the 5 conditions enumerated above
  970. for( int i = (int)arrVolumeData.GetSize() - 1; i >= 0; i-- )
  971. {
  972. CItemData* pVolData = (CItemData*)(arrVolumeData[i]);
  973. ASSERT( pVolData );
  974. ASSERT( pVolData->IsRootVolume() );
  975. // Get the size of the volume
  976. LONGLONG llVolSize;
  977. pVolData->GetSize( llVolSize );
  978. // Intersect the disks set of the volume with the reunion of all other members disks sets
  979. CULONGSet setIntersection;
  980. setIntersection = setForbiddenDisks;
  981. setIntersection *= pVolData->GetDisksSet();
  982. if( ( ( pVolData->GetItemType() != IT_LogicalVolume ) &&
  983. ( pVolData->GetItemType() != IT_PhysicalPartition )
  984. )
  985. ||
  986. ( !pVolData->IsValid() )
  987. ||
  988. ( llVolSize < llMemberSize )
  989. ||
  990. ( ( pVolData->GetItemType() == IT_LogicalVolume ) &&
  991. ( ((CLogicalVolumeData*)pVolData)->m_llVolID == pLVParentData->m_llVolID )
  992. )
  993. ||
  994. ( !setIntersection.IsEmpty() )
  995. )
  996. {
  997. delete pVolData;
  998. arrVolumeData.RemoveAt(i);
  999. }
  1000. }
  1001. AfxGetApp()->DoWaitCursor(-1);
  1002. CSwapDlg dlg(pLVParentData, pMemberData, &arrVolumeData);
  1003. CItemData* pReplData;
  1004. CString strDisplayName, strNameList, strWarning;
  1005. // If no possible replacements then error message
  1006. if( arrVolumeData.GetSize() == 0 )
  1007. {
  1008. CString str, strSize;
  1009. FormatVolumeSize( strSize, llMemberSize );
  1010. AfxFormatString1(str, IDS_ERR_NO_REPLACEMENTS, strSize );
  1011. AfxMessageBox( str, MB_ICONSTOP );
  1012. goto label_cleanup;
  1013. }
  1014. if( dlg.DoModal() != IDOK )
  1015. goto label_cleanup;
  1016. ASSERT( ( dlg.m_nReplacementIndex >= 0 ) && ( dlg.m_nReplacementIndex < arrVolumeData.GetSize() ) );
  1017. AfxGetApp()->DoWaitCursor(1);
  1018. FT_LOGICAL_DISK_ID llReplVolID;
  1019. // If the selected replacement is a physical partition then convert it to FT Partition
  1020. pReplData = (CItemData*)(arrVolumeData[dlg.m_nReplacementIndex]);
  1021. ASSERT( pReplData );
  1022. // Display the warning. All data of the replacement volume will be lost
  1023. pReplData->GetDisplayExtendedName(strDisplayName);
  1024. strNameList += _T("\"");
  1025. strNameList += strDisplayName;
  1026. strNameList += _T("\"");
  1027. strWarning.Format( IDS_WRN_DATA_LOST, strNameList );
  1028. if( IDYES != AfxMessageBox(strWarning, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2 ) )
  1029. goto label_cleanup;
  1030. if( pReplData->GetItemType() == IT_PhysicalPartition )
  1031. {
  1032. ASSERT( !pReplData->GetVolumeName().IsEmpty() );
  1033. if( !FTPart( pReplData->GetVolumeName(),
  1034. pReplData->GetDriveLetter(),
  1035. &llReplVolID ) )
  1036. {
  1037. AfxGetApp()->DoWaitCursor(-1);
  1038. goto label_cleanup;
  1039. }
  1040. }
  1041. else if( pReplData->GetItemType() == IT_LogicalVolume )
  1042. pReplData->GetVolumeID( llReplVolID );
  1043. else
  1044. ASSERT(FALSE);
  1045. // If the selected member is not orphaned then orphan it
  1046. if( pMemberData->GetMemberStatus() != FtMemberOrphaned )
  1047. {
  1048. if( !FTOrphan( pLVParentData->m_llVolID, pMemberData->m_unMemberIndex ) )
  1049. {
  1050. if( pReplData->GetItemType() == IT_PhysicalPartition )
  1051. FTBreak( llReplVolID );
  1052. AfxGetApp()->DoWaitCursor(-1);
  1053. goto label_cleanup;
  1054. }
  1055. }
  1056. // Now is time to replace the member
  1057. FT_LOGICAL_DISK_ID llNewSetID;
  1058. if( FTRegen( pLVParentData->m_llVolID, pMemberData->m_unMemberIndex, llReplVolID, &llNewSetID ) )
  1059. {
  1060. // If the parent is a mirror set and the old member is a FT Partition break the old member
  1061. // If the parent is a stripe set with parity delete the old member
  1062. if( pLVParentData->m_nVolType == FtMirrorSet )
  1063. {
  1064. if( pMemberData->m_nVolType == FtPartition )
  1065. FTBreak( pMemberData->m_llVolID );
  1066. }
  1067. else if( pLVParentData->m_nVolType == FtStripeSetWithParity )
  1068. FTDelete( pMemberData->m_llVolID );
  1069. else
  1070. ASSERT(FALSE);
  1071. AfxMessageBox( IDS_MSG_FTREGEN, MB_ICONINFORMATION );
  1072. // Now refresh both views and emphasize the new set and its new member
  1073. CItemIDSet setAddTreeExpandedItems;
  1074. CItemIDSet setTreeSelectedItems;
  1075. CItemIDSet setListSelectedItems;
  1076. CItemID idItem;
  1077. idItem.m_wItemType = IT_LogicalVolume;
  1078. idItem.m_ID.m_LogicalVolumeID.m_llVolID = llNewSetID;
  1079. setAddTreeExpandedItems.Add( idItem );
  1080. setTreeSelectedItems.Add( idItem );
  1081. ASSERT( idItem.m_wItemType == IT_LogicalVolume );
  1082. idItem.m_ID.m_LogicalVolumeID.m_llVolID = llReplVolID;
  1083. setListSelectedItems.Add( idItem );
  1084. AfxRefreshAll( &setAddTreeExpandedItems, &setTreeSelectedItems, &setListSelectedItems );
  1085. }
  1086. else
  1087. {
  1088. if( pReplData->GetItemType() == IT_PhysicalPartition )
  1089. FTBreak( llReplVolID );
  1090. AfxRefreshAll();
  1091. }
  1092. AfxGetApp()->DoWaitCursor(-1);
  1093. label_cleanup:
  1094. for( i = 0; i < arrVolumeData.GetSize() ; i++ )
  1095. {
  1096. CItemData* pVolData = (CItemData*)(arrVolumeData[i]);
  1097. delete pVolData;
  1098. }
  1099. arrVolumeData.RemoveAll();
  1100. MY_CATCH_AND_REPORT
  1101. }
  1102. void UpdateActionFtswap( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  1103. {
  1104. // Action enabling conditions:
  1105. // 1. 1 ( and only one ) item must be selected
  1106. // 2. The selected item is a logical volume
  1107. // 3. The parent of the item must be a mirror set or a stripe set with parity
  1108. // 4. The selected item must be valid
  1109. // 5. If its parent has a not healthy member, then this member should be the selected item.
  1110. // ( You cannot regenerate a member of an FT set who already has another not healthy member )
  1111. // 6. If its parent is a stripe set with parity, then the parent shouldn't be initializing
  1112. CItemData* pData;
  1113. CItemData* pParentData;
  1114. CLogicalVolumeData* pLVParentData;
  1115. if( arrSelectedItems.GetSize() != 1 )
  1116. goto label_disable;
  1117. pData = (CItemData*)(arrSelectedItems[0]);
  1118. ASSERT(pData);
  1119. if( pData->GetItemType() != IT_LogicalVolume )
  1120. goto label_disable;
  1121. if( !pData->IsValid() )
  1122. goto label_disable;
  1123. pParentData = pData->GetParentData();
  1124. if( ( pParentData == NULL ) || ( pParentData->GetItemType() != IT_LogicalVolume ) )
  1125. goto label_disable;
  1126. pLVParentData = (CLogicalVolumeData*)pParentData;
  1127. if( ( pLVParentData->m_nVolType != FtMirrorSet ) &&
  1128. ( pLVParentData->m_nVolType != FtStripeSetWithParity ) )
  1129. goto label_disable;
  1130. if( ( pLVParentData->m_StateInfo.stripeState.UnhealthyMemberState != FtMemberHealthy ) &&
  1131. ( pLVParentData->m_StateInfo.stripeState.UnhealthyMemberNumber != ((CLogicalVolumeData*)pData)->m_unMemberIndex ) )
  1132. goto label_disable;
  1133. if( ( pLVParentData->m_nVolType == FtStripeSetWithParity ) &&
  1134. ( pLVParentData->m_StateInfo.stripeState.IsInitializing ) )
  1135. goto label_disable;
  1136. pCmdUI->Enable( TRUE );
  1137. return;
  1138. label_disable:
  1139. pCmdUI->Enable(FALSE);
  1140. }
  1141. //////////////////////////////////////////////////////////////////////////////////////////////
  1142. // Create stripe set with parity
  1143. void ActionFtswp( CObArray& arrSelectedItems )
  1144. {
  1145. MY_TRY
  1146. CAutoRefresh ar(FALSE);
  1147. int nNumVols = (int)arrSelectedItems.GetSize();
  1148. ASSERT( nNumVols >= 3 );
  1149. for( int i = 0; i < nNumVols; i++ )
  1150. {
  1151. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  1152. ASSERT(pData);
  1153. ASSERT( ( pData->GetItemType() == IT_LogicalVolume ) ||
  1154. ( pData->GetItemType() == IT_PhysicalPartition ) );
  1155. ASSERT( pData->IsRootVolume() && pData->IsValid() );
  1156. }
  1157. // Display the dialog
  1158. CCreateStripeDlg dlg(&arrSelectedItems, IDD_CREATE_SWP);
  1159. if( dlg.DoModal() != IDOK )
  1160. return;
  1161. // Display the warning. All data of selected volumes will be lost
  1162. CString strDisplayName, strNameList, strWarning;
  1163. for( i = 0; i < arrSelectedItems.GetSize(); i++ )
  1164. {
  1165. CItemData* pVolData = (CItemData*)(arrSelectedItems[i]);
  1166. ASSERT(pVolData);
  1167. pVolData->GetDisplayExtendedName(strDisplayName);
  1168. if( i != 0 )
  1169. strNameList += _T(", ");
  1170. strNameList += _T("\"");
  1171. strNameList += strDisplayName;
  1172. strNameList += _T("\"");
  1173. }
  1174. strWarning.Format( IDS_WRN_DATA_LOST, strNameList );
  1175. if( IDYES != AfxMessageBox(strWarning, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2 ) )
  1176. return;
  1177. AfxGetApp()->DoWaitCursor(1);
  1178. // Make sure that all selected physical partitions are converted to FT partitions
  1179. // and then get all selected items logical volume ID's
  1180. FT_LOGICAL_DISK_ID* arrVolID = (FT_LOGICAL_DISK_ID*)LocalAlloc(0, nNumVols*sizeof(FT_LOGICAL_DISK_ID) );
  1181. if( !arrVolID )
  1182. {
  1183. AfxMessageBox(IDS_ERR_ALLOCATION, MB_ICONSTOP );
  1184. return;
  1185. }
  1186. if( !ConvertPartitionsToFT( arrSelectedItems, arrVolID ) )
  1187. {
  1188. LocalFree(arrVolID);
  1189. AfxRefreshAll();
  1190. AfxGetApp()->DoWaitCursor(-1);
  1191. return;
  1192. }
  1193. FT_LOGICAL_DISK_ID llNewSetID;
  1194. if( FTSWP( arrVolID, (WORD)nNumVols, dlg.m_ulStripeSize, &llNewSetID) )
  1195. {
  1196. AfxMessageBox( IDS_MSG_FTSWP, MB_ICONINFORMATION );
  1197. // Refresh all and emphasize the newly created stripe set with parity
  1198. CItemIDSet setTreeSelectedItems;
  1199. CItemIDSet setListSelectedItems;
  1200. CItemID idItem;
  1201. idItem.m_wItemType = IT_RootVolumes;
  1202. setTreeSelectedItems.Add( idItem );
  1203. idItem.m_wItemType = IT_LogicalVolume;
  1204. idItem.m_ID.m_LogicalVolumeID.m_llVolID = llNewSetID;
  1205. setListSelectedItems.Add(idItem);
  1206. AfxRefreshAll( NULL, &setTreeSelectedItems, &setListSelectedItems );
  1207. }
  1208. else
  1209. {
  1210. DeconvertPartitionsFromFT( arrSelectedItems, arrVolID );
  1211. AfxRefreshAll();
  1212. }
  1213. LocalFree(arrVolID);
  1214. AfxGetApp()->DoWaitCursor(-1);
  1215. MY_CATCH_AND_REPORT
  1216. }
  1217. void UpdateActionFtswp( CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  1218. {
  1219. MY_TRY
  1220. // Action enabling conditions:
  1221. // 1. 3 or more items must be selected
  1222. // 2. Every selected item must be a root volume ( logical volume or physical partition )
  1223. // 3. Every selected item must be valid
  1224. // 4. The disks sets intersection for every couple of selected items must be empty !
  1225. int i;
  1226. if( arrSelectedItems.GetSize() < 3 )
  1227. goto label_disable;
  1228. for( i = 0; i < arrSelectedItems.GetSize(); i++ )
  1229. {
  1230. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  1231. ASSERT(pData);
  1232. if( ( pData->GetItemType() != IT_LogicalVolume ) &&
  1233. ( pData->GetItemType() != IT_PhysicalPartition ) )
  1234. goto label_disable;
  1235. if( !pData->IsRootVolume() || !pData->IsValid() )
  1236. goto label_disable;
  1237. for( int j = 0; j < i; j++ )
  1238. {
  1239. CItemData* pData2 = (CItemData*)(arrSelectedItems[j]);
  1240. CULONGSet setIntersection( pData->GetDisksSet() );
  1241. setIntersection *= pData2->GetDisksSet();
  1242. if( !setIntersection.IsEmpty() )
  1243. goto label_disable;
  1244. }
  1245. }
  1246. pCmdUI->Enable( TRUE );
  1247. return;
  1248. label_disable:
  1249. pCmdUI->Enable(FALSE);
  1250. MY_CATCH
  1251. }
  1252. //////////////////////////////////////////////////////////////////////////////////////////////
  1253. // Create volume set
  1254. void ActionFtvolset( CObArray& arrSelectedItems )
  1255. {
  1256. MY_TRY
  1257. CAutoRefresh ar(FALSE);
  1258. int nNumVols = (int)arrSelectedItems.GetSize();
  1259. ASSERT( nNumVols >= 2 );
  1260. // Get the array of selected items
  1261. for( int i = 0; i < nNumVols; i++ )
  1262. {
  1263. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  1264. ASSERT(pData);
  1265. ASSERT( ( pData->GetItemType() == IT_LogicalVolume ) ||
  1266. ( pData->GetItemType() == IT_PhysicalPartition ) );
  1267. ASSERT( pData->IsRootVolume() && pData->IsValid() );
  1268. }
  1269. // Display the dialog
  1270. CActionDlg dlg(&arrSelectedItems, IDD_CREATE_VOLSET);
  1271. if( dlg.DoModal() != IDOK )
  1272. return;
  1273. // Display the warning. All data of selected volumes ( except the first one ) will be lost
  1274. CString strDisplayName, strNameList, strWarning;
  1275. for( i = 1; i < arrSelectedItems.GetSize(); i++ )
  1276. {
  1277. CItemData* pVolData = (CItemData*)(arrSelectedItems[i]);
  1278. ASSERT(pVolData);
  1279. pVolData->GetDisplayExtendedName(strDisplayName);
  1280. if( i != 1 )
  1281. strNameList += _T(", ");
  1282. strNameList += _T("\"");
  1283. strNameList += strDisplayName;
  1284. strNameList += _T("\"");
  1285. }
  1286. strWarning.Format( IDS_WRN_DATA_LOST, strNameList );
  1287. if( IDYES != AfxMessageBox(strWarning, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2 ) )
  1288. return;
  1289. AfxGetApp()->DoWaitCursor(1);
  1290. // Make sure that all selected physical partitions are converted to FT partitions
  1291. // and then get all selected items logical volume ID's
  1292. FT_LOGICAL_DISK_ID* arrVolID = (FT_LOGICAL_DISK_ID*)LocalAlloc(0, nNumVols*sizeof(FT_LOGICAL_DISK_ID) );
  1293. if( !arrVolID )
  1294. {
  1295. AfxMessageBox(IDS_ERR_ALLOCATION, MB_ICONSTOP );
  1296. return;
  1297. }
  1298. if( !ConvertPartitionsToFT( arrSelectedItems, arrVolID ) )
  1299. {
  1300. LocalFree(arrVolID);
  1301. AfxRefreshAll();
  1302. AfxGetApp()->DoWaitCursor(-1);
  1303. return;
  1304. }
  1305. FT_LOGICAL_DISK_ID llNewSetID;
  1306. if( FTVolSet( arrVolID, (WORD)nNumVols, &llNewSetID ) )
  1307. {
  1308. AfxMessageBox( IDS_MSG_FTVOLSET, MB_ICONINFORMATION );
  1309. FTExtend( llNewSetID );
  1310. // Refresh all and emphasize the newly created volume set
  1311. CItemIDSet setTreeSelectedItems;
  1312. CItemIDSet setListSelectedItems;
  1313. CItemID idItem;
  1314. idItem.m_wItemType = IT_RootVolumes;
  1315. setTreeSelectedItems.Add( idItem );
  1316. idItem.m_wItemType = IT_LogicalVolume;
  1317. idItem.m_ID.m_LogicalVolumeID.m_llVolID = llNewSetID;
  1318. setListSelectedItems.Add(idItem);
  1319. AfxRefreshAll( NULL, &setTreeSelectedItems, &setListSelectedItems );
  1320. }
  1321. else
  1322. {
  1323. DeconvertPartitionsFromFT( arrSelectedItems, arrVolID );
  1324. AfxRefreshAll();
  1325. }
  1326. LocalFree(arrVolID);
  1327. AfxGetApp()->DoWaitCursor(-1);
  1328. MY_CATCH_AND_REPORT
  1329. }
  1330. void UpdateActionFtvolset(CCmdUI* pCmdUI, CObArray& arrSelectedItems )
  1331. {
  1332. // Action enabling conditions:
  1333. // 1. 2 or more items must be selected
  1334. // 2. Every selected item must be a root volume ( logical volume or physical partition )
  1335. // 3. Every selected item must be valid
  1336. int i;
  1337. if( arrSelectedItems.GetSize() < 2 )
  1338. goto label_disable;
  1339. for( i = 0; i < arrSelectedItems.GetSize(); i++ )
  1340. {
  1341. CItemData* pData = (CItemData*)(arrSelectedItems[i]);
  1342. ASSERT(pData);
  1343. if( ( pData->GetItemType() != IT_LogicalVolume ) &&
  1344. ( pData->GetItemType() != IT_PhysicalPartition ) )
  1345. goto label_disable;
  1346. if( !pData->IsRootVolume() || !pData->IsValid() )
  1347. goto label_disable;
  1348. }
  1349. pCmdUI->Enable( TRUE );
  1350. return;
  1351. label_disable:
  1352. pCmdUI->Enable(FALSE);
  1353. }
  1354. #ifdef _DEBUG
  1355. #define new DEBUG_NEW
  1356. #undef THIS_FILE
  1357. static char THIS_FILE[] = __FILE__;
  1358. #endif
  1359.