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.

500 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. FTMan
  5. File Name:
  6. LogVol.cpp
  7. Abstract:
  8. Implementation of the CLogicalVolumeData class. The class who stores all properties of a logical volume
  9. Author:
  10. Cristian Teodorescu October 20, 1998
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "stdafx.h"
  15. #include "DiskMap.h"
  16. #include "FTUtil.h"
  17. #include "Global.h"
  18. #include "LogVol.h"
  19. #include "MainFrm.h"
  20. #include "PhPart.h"
  21. #include "Resource.h"
  22. // Because ftapi library is written in C the header must be included with extern "C".
  23. // Otherwise it can't be linked
  24. extern "C"
  25. {
  26. #include <FTAPI.h>
  27. }
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. ////////////////////////////////////////////////////////////////////////////////////////
  34. // CLogicalVolumeData
  35. // Constructor
  36. CLogicalVolumeData::CLogicalVolumeData(
  37. FT_LOGICAL_DISK_ID llVolID,
  38. CItemData* pParentData /* = NULL */,
  39. BOOL bIsRootVolume /* = FALSE */,
  40. USHORT unMemberIndex /* = MAXWORD */,
  41. FT_MEMBER_STATE nMemberStatus /* = FtMemberHealthy */ ) :
  42. CItemData( IT_LogicalVolume, pParentData, bIsRootVolume ), m_llVolID(llVolID), m_unMemberIndex(unMemberIndex)
  43. {
  44. m_nMemberStatus = nMemberStatus;
  45. if( bIsRootVolume )
  46. {
  47. ASSERT( unMemberIndex == MAXWORD );
  48. ASSERT( nMemberStatus == FtMemberHealthy );
  49. }
  50. }
  51. // Copy constructor
  52. CLogicalVolumeData::CLogicalVolumeData( CLogicalVolumeData& rData )
  53. : CItemData(rData),
  54. m_llVolID(rData.m_llVolID), m_llVolSize(rData.m_llVolSize), m_nVolType(rData.m_nVolType),
  55. m_unMemberIndex(rData.m_unMemberIndex)
  56. {
  57. memcpy(&m_ConfigInfo, &(rData.m_ConfigInfo), sizeof(m_ConfigInfo));
  58. memcpy(&m_StateInfo, &(rData.m_StateInfo), sizeof(m_StateInfo));
  59. }
  60. ////////////////////////////////////////////////////////////////////////////////////////
  61. // Public methods
  62. BOOL CLogicalVolumeData::ReadItemInfo( CString& strErrors )
  63. {
  64. MY_TRY
  65. m_bValid = TRUE;
  66. strErrors = _T("");
  67. m_ulNumMembers = 0;
  68. if( !ReadFTInfo( strErrors ) )
  69. {
  70. m_bValid = FALSE;
  71. // this is a serious error so return immediately
  72. return FALSE;
  73. }
  74. if( m_nVolType == FtPartition )
  75. {
  76. // I need some extra information for FtPartitions
  77. PARTITION_INFORMATION partInfo;
  78. PARTITION_TYPE wPartitionType;
  79. CString strMemberErrors;
  80. BOOL bMissingDisk;
  81. CDiskMap diskMap( m_ConfigInfo.partConfig.Config.DiskNumber );
  82. if( diskMap.ReadPartitionInformation( m_ConfigInfo.partConfig.Config.ByteOffset,
  83. partInfo,
  84. wPartitionType,
  85. strMemberErrors,
  86. bMissingDisk) )
  87. {
  88. m_ConfigInfo.partConfig.dwPartitionNumber = partInfo.PartitionNumber;
  89. m_ConfigInfo.partConfig.wPartitionType = wPartitionType;
  90. }
  91. strErrors += strMemberErrors;
  92. }
  93. // Read the drive letter, volume name and mount paths ( if any )
  94. if( !ReadDriveLetterAndVolumeName() )
  95. {
  96. //AddError( strErrors, IDS_ERR_READ_DRIVE_LETTER_AND_VOLUME_NAME, FALSE );
  97. m_bValid = FALSE;
  98. }
  99. // The mount paths will be retrieved later together with all other siblings mount paths ( for performance reason )
  100. m_arrMountPaths.RemoveAll();
  101. // Retrieve all disks used by this volume
  102. if( !RetrieveDisksSet() )
  103. {
  104. AddError( strErrors, IDS_ERR_RETRIEVE_DISKS_SET, FALSE );
  105. m_bValid = FALSE;
  106. }
  107. if( !FTChkIO( m_llVolID, &m_bIoOK) )
  108. {
  109. AddError( strErrors, IDS_ERR_FTCHKIO, TRUE );
  110. m_bValid = FALSE;
  111. }
  112. m_iImage = ComputeImageIndex();
  113. return m_bValid;
  114. MY_CATCH_AND_THROW
  115. }
  116. BOOL CLogicalVolumeData::ReadFTInfo( CString& strErrors )
  117. {
  118. MY_TRY
  119. strErrors = _T("");
  120. USHORT numMembers;
  121. FT_LOGICAL_DISK_ID members[100];
  122. // Read all information related to this logical volume
  123. if( ! FtQueryLogicalDiskInformation ( m_llVolID,
  124. &m_nVolType,
  125. &m_llVolSize,
  126. 100,
  127. members,
  128. &numMembers,
  129. sizeof(m_ConfigInfo),
  130. &m_ConfigInfo,
  131. sizeof(m_StateInfo),
  132. &m_StateInfo ) )
  133. {
  134. AddError( strErrors, IDS_ERR_RETRIEVING_VOL_INFO, TRUE );
  135. m_bValid = FALSE;
  136. // this is a serious error so return immediately
  137. return FALSE;
  138. }
  139. m_ulNumMembers = (ULONG)numMembers;
  140. return TRUE;
  141. MY_CATCH_AND_THROW
  142. }
  143. BOOL CLogicalVolumeData::ReadMembers( CObArray& arrMembersData, CString& strErrors )
  144. {
  145. MY_TRY
  146. arrMembersData.RemoveAll();
  147. strErrors = _T("");
  148. m_ulNumMembers = 0;
  149. USHORT numMembers;
  150. FT_LOGICAL_DISK_ID members[100];
  151. // Read all information related to this logical volume
  152. if( !FtQueryLogicalDiskInformation ( m_llVolID,
  153. &m_nVolType,
  154. &m_llVolSize,
  155. 100,
  156. members,
  157. &numMembers,
  158. sizeof(m_ConfigInfo),
  159. &m_ConfigInfo,
  160. sizeof(m_StateInfo),
  161. &m_StateInfo ) )
  162. {
  163. AddError( strErrors, IDS_ERR_RETRIEVING_VOL_INFO, TRUE );
  164. return FALSE;
  165. }
  166. m_ulNumMembers = (ULONG)numMembers;
  167. for( USHORT i = 0; i < m_ulNumMembers; i++ )
  168. {
  169. // Get the status of the member
  170. FT_MEMBER_STATE nMemberStatus;
  171. nMemberStatus = FtMemberHealthy;
  172. if( ( m_nVolType == FtMirrorSet ) ||
  173. ( m_nVolType == FtStripeSetWithParity ) )
  174. {
  175. if( ( m_StateInfo.stripeState.UnhealthyMemberState != FtMemberHealthy ) &&
  176. ( m_StateInfo.stripeState.UnhealthyMemberNumber == i ) )
  177. nMemberStatus = m_StateInfo.stripeState.UnhealthyMemberState;
  178. }
  179. // Create the logical volume item data
  180. CLogicalVolumeData* pData = new CLogicalVolumeData( members[i], this, FALSE, i, nMemberStatus );
  181. // Read logical volume info and collect errors ( if any )
  182. CString strMemberErrors;
  183. pData->ReadItemInfo( strMemberErrors);
  184. strErrors += strMemberErrors;
  185. // Add the structure to the members' data array
  186. arrMembersData.Add(pData);
  187. }
  188. return TRUE;
  189. MY_CATCH_AND_THROW
  190. }
  191. int CLogicalVolumeData::ComputeImageIndex() const
  192. {
  193. MY_TRY
  194. // Is it necessary to display the error image?
  195. BOOL bError = FALSE;
  196. // Is it necessary to display the warning image?
  197. BOOL bWarning = FALSE;
  198. // The error image should be displayed in three situations:
  199. // 1. The item is not valid. That means that not all information about the volume was successfully read,
  200. // so the volume cannot be used in actions
  201. // 2. The check IO test failed. The volume cannot be used for IO operations
  202. // 3. The volume is an orphan member of a mirror set or of a stripe set with parity.
  203. bError = !m_bValid || !m_bIoOK || ( m_nMemberStatus == FtMemberOrphaned );
  204. if( !bError )
  205. {
  206. // The warning image should be displayed in four situations:
  207. // 1. The volume is a regenerating member of a mirror set or stripe set with parity
  208. // 2. The volume is a member of a stripe set with parity who is initializing
  209. // 3. The volume is a stripe set with parity initializing
  210. // 4. The volume is a mirror set or a stripe set with parity containing a not healthy member.
  211. // Situations 1,2 are general and could happen to all logical volumes
  212. // Situations 3,4 are particular for mirrors and swp's so they will be treated in the main switch at
  213. // the end of the method
  214. if( m_nMemberStatus == FtMemberRegenerating )
  215. bWarning = TRUE;
  216. else if( ( m_pParentData != NULL ) && ( m_pParentData->GetItemType() == IT_LogicalVolume ) )
  217. {
  218. CLogicalVolumeData* pParentData = (CLogicalVolumeData*)m_pParentData;
  219. if( ( pParentData->m_nVolType == FtStripeSetWithParity ) &&
  220. ( pParentData->m_StateInfo.stripeState.IsInitializing ) )
  221. bWarning = TRUE;
  222. }
  223. }
  224. switch( m_nVolType )
  225. {
  226. case FtPartition:
  227. if( bError )
  228. return II_PhysicalPartition_Error; //II_FTPartition; The user shouldn't know about the existence of FTPartitions
  229. else if( bWarning )
  230. return II_PhysicalPartition_Warning;
  231. else
  232. return II_PhysicalPartition;
  233. case FtVolumeSet:
  234. if( bError )
  235. return II_VolumeSet_Error;
  236. else if( bWarning )
  237. return II_VolumeSet_Warning;
  238. else
  239. return II_VolumeSet;
  240. case FtStripeSet:
  241. if( bError )
  242. return II_StripeSet_Error;
  243. else if( bWarning )
  244. return II_StripeSet_Warning;
  245. else
  246. return II_StripeSet;
  247. case FtMirrorSet:
  248. if( bError )
  249. return II_MirrorSet_Error;
  250. else if( bWarning || ( m_StateInfo.stripeState.UnhealthyMemberState != FtMemberHealthy ) )
  251. return II_MirrorSet_Warning;
  252. else
  253. return II_MirrorSet;
  254. case FtStripeSetWithParity:
  255. if( bError )
  256. return II_StripeSetWithParity_Error;
  257. else if( bWarning || ( m_StateInfo.stripeState.UnhealthyMemberState != FtMemberHealthy ) ||
  258. ( m_StateInfo.stripeState.IsInitializing ) )
  259. return II_StripeSetWithParity_Warning;
  260. else
  261. return II_StripeSetWithParity;
  262. case FtRedistribution:
  263. // I don't have yet a bitmap for redistributions
  264. ASSERT(FALSE);
  265. if( bError )
  266. return II_PhysicalPartition_Error;
  267. else if( bWarning )
  268. return II_PhysicalPartition_Warning;
  269. else
  270. return II_PhysicalPartition;
  271. default:
  272. ASSERT(FALSE);
  273. return II_PhysicalPartition_Error;
  274. }
  275. MY_CATCH_AND_THROW
  276. }
  277. BOOL CLogicalVolumeData::operator==(CItemData& rData) const
  278. {
  279. if( rData.GetItemType() != IT_LogicalVolume )
  280. return FALSE;
  281. CLogicalVolumeData* pLogVolData = (CLogicalVolumeData*)(&rData);
  282. return( m_llVolID == pLogVolData->m_llVolID );
  283. }
  284. void CLogicalVolumeData::GetDisplayName( CString& strDisplay ) const
  285. {
  286. MY_TRY
  287. strDisplay = _T("");
  288. for( int i = 0; i < m_arrMountPaths.GetSize(); i++ )
  289. {
  290. if( i != 0 )
  291. strDisplay += _T("; ");
  292. strDisplay += m_arrMountPaths[i];
  293. }
  294. if( strDisplay.IsEmpty() )
  295. {
  296. if( m_cDriveLetter )
  297. strDisplay.Format(_T("%c:"), m_cDriveLetter );
  298. /*
  299. else
  300. strDisplay.Format(_T("%I64X"), m_llVolID );
  301. */
  302. }
  303. if( m_nVolType == FtPartition )
  304. {
  305. CString str;
  306. str.Format( IDS_STR_PHYSICAL_PARTITION_NAME,
  307. m_ConfigInfo.partConfig.Config.DiskNumber, m_ConfigInfo.partConfig.dwPartitionNumber );
  308. if( !strDisplay.IsEmpty() )
  309. strDisplay += _T(" ");
  310. strDisplay += str;
  311. }
  312. MY_CATCH_AND_THROW
  313. }
  314. void CLogicalVolumeData::GetDisplayType( CString& strDisplay ) const
  315. {
  316. MY_TRY
  317. switch( m_nVolType )
  318. {
  319. case FtPartition:
  320. //strDisplay.LoadString(IDS_TYPE_FTPARTITION);
  321. switch( m_ConfigInfo.partConfig.wPartitionType )
  322. {
  323. case PT_Primary:
  324. strDisplay.LoadString( IDS_TYPE_PRIMARY_PARTITION);
  325. break;
  326. case PT_InExtendedPartition:
  327. strDisplay.LoadString( IDS_TYPE_PARTITION_IN_EXTENDED_PARTITION);
  328. break;
  329. default:
  330. ASSERT(FALSE);
  331. }
  332. break;
  333. case FtVolumeSet:
  334. strDisplay.LoadString(IDS_TYPE_FTVOLUMESET);
  335. break;
  336. case FtStripeSet:
  337. strDisplay.LoadString(IDS_TYPE_FTSTRIPESET);
  338. break;
  339. case FtMirrorSet:
  340. strDisplay.LoadString(IDS_TYPE_FTMIRRORSET);
  341. break;
  342. case FtStripeSetWithParity:
  343. strDisplay.LoadString(IDS_TYPE_FTSTRIPESETWITHPARITY);
  344. break;
  345. case FtRedistribution:
  346. strDisplay.LoadString(IDS_TYPE_FTREDISTRIBUTION);
  347. break;
  348. default:
  349. ASSERT(FALSE);
  350. strDisplay = _T("");
  351. }
  352. MY_CATCH_AND_THROW
  353. }
  354. void CLogicalVolumeData::GetDisplayExtendedName( CString& strDisplay ) const
  355. {
  356. MY_TRY
  357. GetDisplayName( strDisplay );
  358. if( m_nVolType != FtPartition )
  359. {
  360. CString strType;
  361. GetDisplayType( strType );
  362. if( !strDisplay.IsEmpty() )
  363. strDisplay += _T(" ");
  364. strDisplay += strType;
  365. }
  366. MY_CATCH_AND_THROW
  367. }
  368. BOOL CLogicalVolumeData::GetVolumeID( FT_LOGICAL_DISK_ID& llVolID ) const
  369. {
  370. llVolID = m_llVolID;
  371. return TRUE;
  372. }
  373. BOOL CLogicalVolumeData::GetSize( LONGLONG& llSize ) const
  374. {
  375. llSize = m_llVolSize;
  376. return TRUE;
  377. }
  378. BOOL CLogicalVolumeData::GetDiskNumber( ULONG& ulDiskNumber ) const
  379. {
  380. if( m_nVolType == FtPartition )
  381. {
  382. ulDiskNumber = m_ConfigInfo.partConfig.Config.DiskNumber;
  383. return TRUE;
  384. }
  385. return FALSE;
  386. }
  387. BOOL CLogicalVolumeData::GetOffset( LONGLONG& llOffset) const
  388. {
  389. if( m_nVolType == FtPartition )
  390. {
  391. llOffset = m_ConfigInfo.partConfig.Config.ByteOffset;
  392. return TRUE;
  393. }
  394. return FALSE;
  395. }
  396. ////////////////////////////////////////////////////////////////////////////////////////////////////
  397. // Protected methods
  398. BOOL CLogicalVolumeData::RetrieveNTName( CString& strNTName ) const
  399. {
  400. MY_TRY
  401. return FTQueryNTDeviceName( m_llVolID, strNTName );
  402. MY_CATCH_AND_THROW
  403. }
  404. BOOL CLogicalVolumeData::RetrieveDisksSet()
  405. {
  406. MY_TRY
  407. return FTGetDisksSet( m_llVolID, m_setDisks );
  408. MY_CATCH_AND_THROW
  409. }