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.

943 lines
26 KiB

  1. /**********************************************************************************
  2. FILENAME: DiskView.cpp
  3. CLASS: DISKVIEW
  4. CLASS DESCRIPTION:
  5. DiskView takes data from the engines about what each cluster of the disk is used for.
  6. It creates an array in memory (ClusterArray) to hold this data and then creates a
  7. similar array to hold the data that DiskDisplay will use (LineArray) to display a
  8. graphical image on the screen. This means that DiskView must look through many
  9. clusters in it's array an determine that the bulk of them are fragmented or not,
  10. (or some special type of file), and set a byte to a specific color in the LineArray
  11. (memory array for the display data -- 1 line = 1 block of clusters).
  12. COPYRIGHT 2001 Microsoft Corporation and Executive Software International, Inc.
  13. */
  14. #include "stdafx.h"
  15. #ifndef SNAPIN
  16. #include <windows.h>
  17. #endif
  18. extern "C" {
  19. #include "SysStruc.h"
  20. }
  21. #include "ErrMacro.h"
  22. #include "DfrgCmn.h"
  23. #include "DfrgEngn.h"
  24. #include "DfrgRes.h"
  25. #include "DiskView.h"
  26. #include "Graphix.h"
  27. #include "IntFuncs.h"
  28. #include "GetReg.h"
  29. #ifdef _DEBUG
  30. #define CLASSINVARIANT() EH_ASSERT(Invariant())
  31. #else
  32. #define CLASSINVARIANT()
  33. #endif
  34. // default: set line to frag color if 3% of clusters are fragged
  35. #define FRAGTHRESHDEFAULT 3
  36. // TEMP TEMP
  37. #define ANALYZE_MEM_FAIL 0
  38. #define DEFRAG_MEM_FAIL 0
  39. /**********************************************************************************
  40. Construction/Destruction
  41. **********************************************************************************/
  42. DiskView::DiskView()
  43. {
  44. ::InitializeCriticalSection(&m_CriticalSection);
  45. // data we need from UI
  46. NumLines = 0;
  47. ClusterFactor = 0;
  48. pLineArray = NULL;
  49. // control variables
  50. m_bIsDataSent = FALSE;
  51. m_IsActive = FALSE;
  52. m_FragColorThreshold = FRAGTHRESHDEFAULT;
  53. m_bMemAllocFailed = FALSE;
  54. m_nFreeDelta = 0;
  55. m_nFragDelta = 0;
  56. m_nNonMovableDelta = 0;
  57. m_nUsedDelta = 0;
  58. // init basic variables.
  59. MftZoneStart = 0;
  60. MftZoneEnd = 0;
  61. Clusters = 0;
  62. pClusterArray = NULL;
  63. InitFragColorThreshold();
  64. CLASSINVARIANT();
  65. }
  66. DiskView::DiskView(const int InClusters,
  67. const int InMftZoneStart = 0,
  68. const int InMftZoneEnd = 0)
  69. {
  70. require(InClusters > 0);
  71. ::InitializeCriticalSection(&m_CriticalSection);
  72. // data we need from UI
  73. NumLines = 0;
  74. ClusterFactor = 0;
  75. pLineArray = NULL;
  76. // control variables
  77. m_bIsDataSent = FALSE;
  78. m_IsActive = FALSE;
  79. m_FragColorThreshold = FRAGTHRESHDEFAULT;
  80. m_bMemAllocFailed = FALSE;
  81. // init basic variables.
  82. MftZoneStart = InMftZoneStart;
  83. MftZoneEnd = InMftZoneEnd;
  84. Clusters = InClusters;
  85. // cluster map
  86. ClusterArraySize = Clusters / 2 + Clusters % 2; // one cluster per nibble
  87. #if ANALYZE_MEM_FAIL // TEMP TEMP
  88. pClusterArray = new char [ClusterArraySize * 10000];
  89. #else
  90. pClusterArray = new char [ClusterArraySize];
  91. #endif
  92. EH(pClusterArray);
  93. // fill the array initially with free space.
  94. if (pClusterArray) {
  95. FillMemory(pClusterArray, ClusterArraySize, (FreeSpaceColor << 4) | FreeSpaceColor);
  96. }
  97. else {
  98. // new failed, keep class consistent
  99. m_bMemAllocFailed = TRUE;
  100. Clusters = 0;
  101. ClusterArraySize = 0;
  102. }
  103. InitFragColorThreshold();
  104. CLASSINVARIANT();
  105. }
  106. /*
  107. METHOD: DiskView::InitFragColorThreshold
  108. DESCRIPTION:
  109. Get the threshold percentage of fragmented clusters that it takes to cause
  110. a line to display in the fragmented color. If it is not in the registry at
  111. all then we don't set it. Otherwise it will be defaulted by the constructor.
  112. */
  113. void DiskView::InitFragColorThreshold()
  114. {
  115. // get frag color threshold percent from registry
  116. TCHAR cRegValue[100];
  117. HKEY hValue = NULL;
  118. DWORD dwRegValueSize = sizeof(cRegValue);
  119. // get the free space error threshold from the registry
  120. long ret = GetRegValue(
  121. &hValue,
  122. TEXT("SOFTWARE\\Microsoft\\Dfrg"),
  123. TEXT("FragColorThreshold"),
  124. cRegValue,
  125. &dwRegValueSize);
  126. RegCloseKey(hValue);
  127. // convert it and apply range limits
  128. if (ret == ERROR_SUCCESS) {
  129. m_FragColorThreshold = (UINT) _ttoi(cRegValue);
  130. // > 50 does not make sense!
  131. if (m_FragColorThreshold > 50)
  132. m_FragColorThreshold = 50;
  133. // < 0 does not either!
  134. if (m_FragColorThreshold < 1)
  135. m_FragColorThreshold = 0;
  136. }
  137. }
  138. /*
  139. METHOD: DiskView::DiskView (Copy Contructor)
  140. DESCRIPTION:
  141. Copies a DiskView class.
  142. RETURN:
  143. New Class reference.
  144. */
  145. DiskView::DiskView(const DiskView& InDiskView)
  146. {
  147. EH_ASSERT(InDiskView.Invariant());
  148. require(InDiskView.HasMapMemory());
  149. ::InitializeCriticalSection(&m_CriticalSection);
  150. // copy over some basic variables from the input DiskView.
  151. Clusters = InDiskView.Clusters;
  152. ClusterArraySize = Clusters / 2 + Clusters % 2; // one cluster per nibble
  153. NumLines = InDiskView.NumLines;
  154. if (NumLines > 0)
  155. ClusterFactor = (Clusters / NumLines) + ((Clusters % NumLines) ? 1 : 0);
  156. else
  157. ClusterFactor = 0;
  158. EH_ASSERT(ClusterFactor == InDiskView.ClusterFactor);
  159. MftZoneEnd = InDiskView.MftZoneEnd;
  160. MftZoneStart = InDiskView.MftZoneStart;
  161. m_bIsDataSent = FALSE;
  162. m_bMemAllocFailed = FALSE;
  163. m_IsActive = InDiskView.m_IsActive;
  164. m_FragColorThreshold = InDiskView.m_FragColorThreshold;
  165. // cluster map
  166. #if DEFRAG_MEM_FAIL // TEMP TEMP
  167. pClusterArray = new char [ClusterArraySize * 10000];
  168. #else
  169. pClusterArray = new char [ClusterArraySize];
  170. #endif
  171. EH(pClusterArray);
  172. // copy over the cluster array.
  173. if (pClusterArray) {
  174. CopyMemory(pClusterArray, InDiskView.pClusterArray, ClusterArraySize);
  175. }
  176. else {
  177. // new failed, keep class consistent
  178. m_bMemAllocFailed = TRUE;
  179. Clusters = 0;
  180. ClusterArraySize = 0;
  181. }
  182. // line array
  183. if (NumLines > 0) {
  184. pLineArray = new char [NumLines];
  185. EH(pLineArray);
  186. if (pLineArray) {
  187. FillMemory(pLineArray, NumLines, DirtyColor);
  188. }
  189. else {
  190. // new failed, keep class consistent
  191. m_bMemAllocFailed = TRUE;
  192. NumLines = 0;
  193. }
  194. }
  195. else {
  196. pLineArray = NULL;
  197. }
  198. CLASSINVARIANT();
  199. }
  200. /*
  201. METHOD: DiskView::operator= (Assignment Operator)
  202. DESCRIPTION:
  203. Makes the Lvalue a duplicate of the Rvalue.
  204. */
  205. DiskView& DiskView::operator=(const DiskView& InDiskView)
  206. {
  207. // check for assignment to self
  208. if (this == &InDiskView) {
  209. return *this;
  210. }
  211. EH_ASSERT(InDiskView.Invariant());
  212. require(InDiskView.HasMapMemory());
  213. __try
  214. {
  215. ::EnterCriticalSection(&m_CriticalSection);
  216. // copy over some basic variables from the input DiskView.
  217. MftZoneEnd = InDiskView.MftZoneEnd;
  218. MftZoneStart = InDiskView.MftZoneStart;
  219. m_bIsDataSent = FALSE;
  220. m_bMemAllocFailed = FALSE;
  221. m_IsActive = InDiskView.m_IsActive;
  222. m_FragColorThreshold = InDiskView.m_FragColorThreshold;
  223. // if the number of clusters in the cluster array are not identical, realloc the array.
  224. if (Clusters != InDiskView.Clusters) {
  225. // get the new size for the cluster array.
  226. Clusters = InDiskView.Clusters;
  227. ClusterArraySize = Clusters / 2 + Clusters % 2; // one cluster per nibble
  228. // redimension the cluster array.
  229. if (pClusterArray)
  230. delete [] pClusterArray;
  231. #if DEFRAG_MEM_FAIL // TEMP TEMP
  232. pClusterArray = new char [ClusterArraySize * 10000];
  233. #else
  234. pClusterArray = new char [ClusterArraySize];
  235. #endif
  236. EH(pClusterArray);
  237. }
  238. // copy over the cluster array.
  239. if (pClusterArray) {
  240. CopyMemory(pClusterArray, InDiskView.pClusterArray, ClusterArraySize);
  241. }
  242. else {
  243. // new failed, keep class consistent
  244. m_bMemAllocFailed = TRUE;
  245. Clusters = 0;
  246. ClusterArraySize = 0;
  247. }
  248. // line array
  249. NumLines = InDiskView.NumLines;
  250. if (NumLines > 0)
  251. ClusterFactor = (Clusters / NumLines) + ((Clusters % NumLines) ? 1 : 0);
  252. else
  253. ClusterFactor = 0;
  254. if (NumLines > 0) {
  255. pLineArray = new char [NumLines];
  256. EH(pLineArray);
  257. if (pLineArray) {
  258. FillMemory(pLineArray, NumLines, DirtyColor);
  259. }
  260. else {
  261. // new failed, keep class consistent
  262. m_bMemAllocFailed = TRUE;
  263. NumLines = 0;
  264. }
  265. }
  266. else {
  267. pLineArray = NULL;
  268. }
  269. CLASSINVARIANT();
  270. }
  271. __finally
  272. {
  273. ::LeaveCriticalSection(&m_CriticalSection);
  274. }
  275. return *this;
  276. }
  277. /*
  278. METHOD: DiskView::~DiskView (Destructor)
  279. */
  280. DiskView::~DiskView()
  281. {
  282. CLASSINVARIANT();
  283. ::DeleteCriticalSection(&m_CriticalSection);
  284. if (pClusterArray)
  285. delete [] pClusterArray;
  286. if (pLineArray)
  287. delete [] pLineArray;
  288. }
  289. /**********************************************************************************
  290. Implementation
  291. **********************************************************************************/
  292. void DiskView::SetClusterCount(const int InClusters)
  293. {
  294. require(InClusters > 0);
  295. __try
  296. {
  297. ::EnterCriticalSection(&m_CriticalSection);
  298. m_IsActive = TRUE;
  299. Clusters = InClusters;
  300. // cluster map
  301. ClusterArraySize = Clusters / 2 + Clusters % 2; // one cluster per nibble
  302. #if ANALYZE_MEM_FAIL // TEMP TEMP
  303. pClusterArray = new char [ClusterArraySize * 10000];
  304. #else
  305. pClusterArray = new char [ClusterArraySize];
  306. #endif
  307. EH(pClusterArray);
  308. // fill the array initially with free space.
  309. if (pClusterArray) {
  310. FillMemory(pClusterArray, ClusterArraySize, (FreeSpaceColor << 4) | FreeSpaceColor);
  311. }
  312. else {
  313. // new failed, keep class consistent
  314. m_bMemAllocFailed = TRUE;
  315. Clusters = 0;
  316. ClusterArraySize = 0;
  317. }
  318. CLASSINVARIANT();
  319. }
  320. __finally
  321. {
  322. ::LeaveCriticalSection(&m_CriticalSection);
  323. }
  324. }
  325. void DiskView::SetMftZone(const int InZoneStart, const int InZoneEnd)
  326. {
  327. require(InZoneEnd >= InZoneStart);
  328. __try
  329. {
  330. ::EnterCriticalSection(&m_CriticalSection);
  331. MftZoneStart = InZoneStart;
  332. MftZoneEnd = InZoneEnd;
  333. CLASSINVARIANT();
  334. }
  335. __finally
  336. {
  337. ::LeaveCriticalSection(&m_CriticalSection);
  338. }
  339. }
  340. /*
  341. METHOD: DiskView::SetNumLines
  342. DESCRIPTION:
  343. Called to update the number of lines (pixels) that are displayed on the UI
  344. */
  345. void DiskView::SetNumLines(const int inNumLines)
  346. {
  347. if (NumLines != inNumLines && inNumLines > 0 && pClusterArray != NULL) {
  348. __try
  349. {
  350. ::EnterCriticalSection(&m_CriticalSection);
  351. CLASSINVARIANT();
  352. NumLines = inNumLines;
  353. ClusterFactor = (Clusters / NumLines) + ((Clusters % NumLines) ? 1 : 0);
  354. EH(ClusterFactor > 0);
  355. if (pLineArray)
  356. delete [] pLineArray;
  357. pLineArray = new char [NumLines];
  358. EH(pLineArray);
  359. if (pLineArray) {
  360. FillMemory(pLineArray, NumLines, DirtyColor);
  361. }
  362. else {
  363. // new failed, keep class consistent
  364. m_bMemAllocFailed = TRUE;
  365. NumLines = 0;
  366. }
  367. CLASSINVARIANT();
  368. }
  369. __finally
  370. {
  371. ::LeaveCriticalSection(&m_CriticalSection);
  372. }
  373. }
  374. }
  375. /*
  376. METHOD: DiskView::GetLineArray
  377. DESCRIPTION:
  378. Makes LineArray available outside of the class so it can be passed to DiskDisplay.
  379. */
  380. BOOL DiskView::GetLineArray(char ** ppOutLineArray, DWORD *pNumLines)
  381. {
  382. BOOL bReturn = TRUE;
  383. // initialize outputs
  384. *ppOutLineArray = NULL;
  385. *pNumLines = 0;
  386. if (!m_IsActive || pClusterArray == NULL){
  387. bReturn = FALSE;
  388. } else
  389. {
  390. // see if we have a line array
  391. if (pLineArray != NULL && NumLines > 0) {
  392. __try
  393. {
  394. ::EnterCriticalSection(&m_CriticalSection);
  395. CLASSINVARIANT();
  396. // update the line array from the cluster array
  397. TransferToLineArray();
  398. // allocate space for a copy of the line array
  399. *ppOutLineArray = new char[NumLines];
  400. // if we got memory, set the outputs
  401. if (*ppOutLineArray) {
  402. CopyMemory(*ppOutLineArray, pLineArray, NumLines);
  403. *pNumLines = (DWORD) NumLines;
  404. }
  405. m_bIsDataSent = TRUE;
  406. }
  407. __finally
  408. {
  409. ::LeaveCriticalSection(&m_CriticalSection);
  410. bReturn = TRUE;
  411. }
  412. }
  413. else {
  414. bReturn = FALSE;
  415. }
  416. }
  417. return bReturn;
  418. }
  419. /*
  420. METHOD: DiskView::UpdateClusterArray
  421. DESCRIPTION:
  422. Updates portions of the cluster array from extent data about the disk. (An extent
  423. is a series of adjacent clusters that are part of the same file -- or sometimes in
  424. our program, part of no file.) The extents are passed in as a series of EXTENT_LIST
  425. structures with a LONGLONG header. The first 7 bytes of the LONGLONG contain the
  426. number of EXTENT_LIST structures following, the last byte of the LONGLONG contains
  427. the color code of the extents (meaning a series of extents all represent the same
  428. type of data: contiguous files, fragmented files, etc.) After the last EXTENT_LIST
  429. structure, there may be another LONGLONG identifying that there is another series of
  430. EXTENT_LIST's. Eventually there will be a zeroed out LONGLONG indicating there is
  431. no more data. UpdateClusterArray goes through each of these extents and updates the
  432. appropriate clusters in ClusterArray. It then re-evaluates those specific lines in
  433. the LineArray that would be affected by the changes in ClusterArray.
  434. INPUT + OUTPUT:
  435. pBuffer - The buffer holding the EXTENT_LIST's and their LONGLONG headers.
  436. */
  437. void DiskView::UpdateClusterArray(PBYTE pBuffer)
  438. {
  439. LONGLONG StartingLcn;
  440. BYTE Color;
  441. int ClusterCount;
  442. EXTENT_LIST* pUpdateArray;
  443. LONGLONG Extents = 0;
  444. LONGLONG Extent = 0;
  445. int TotalRunLength = 0;
  446. BYTE * pTempBuffer = pBuffer;
  447. if (!m_IsActive || pClusterArray == NULL){
  448. return;
  449. }
  450. __try
  451. {
  452. ::EnterCriticalSection(&m_CriticalSection);
  453. CLASSINVARIANT();
  454. //Indefinite length loop that goes through all the series of EXTENT_LIST's
  455. //until there are no more.
  456. while(TRUE){
  457. //Get the number of extents.
  458. Extents = *(LONGLONG*)pBuffer & 0x0FFFFFFFFFFF;
  459. if(Extents == 0){
  460. break;
  461. }
  462. //Point to the EXTENT_LIST's.
  463. pBuffer += sizeof(LONGLONG);
  464. //Get the color code.
  465. Color = pBuffer[-1];
  466. //Get a movable pointer to the EXTENT_LIST's
  467. pUpdateArray = (EXTENT_LIST*)pBuffer;
  468. //Set the high nibble to have the same color code as the low nibble of color.
  469. //Color = (Low nibble) | (High nibble which is low nibble shifted)
  470. Color = (Color & 0x0F) | (Color << 4);
  471. //Go through each extent and
  472. //update the ClusterArray and LineArray for that extent.
  473. for(Extent = 0; Extent < Extents; pUpdateArray ++, Extent ++) {
  474. //Get the data for this extent and validate it is correct
  475. //(doesn't run of the end of the disk)
  476. StartingLcn = pUpdateArray->StartingLcn;
  477. ClusterCount = (UINT)pUpdateArray->ClusterCount;
  478. if ((StartingLcn < 0) || (ClusterCount <= 0) ||
  479. (StartingLcn + ClusterCount > Clusters)) {
  480. __leave;
  481. }
  482. if (pLineArray != NULL && NumLines > 0) {
  483. // mark the affected lines in the line array dirty
  484. UINT nStartLine = (UINT) (StartingLcn / ClusterFactor);
  485. UINT nEndLine = (UINT) ((StartingLcn + ClusterCount - 1) / ClusterFactor);
  486. for (UINT ii = nStartLine; ii <= nEndLine; ii++) {
  487. //sks bug#206244
  488. if(ii >= (UINT) NumLines)
  489. {
  490. __leave;
  491. }
  492. pLineArray[ii] = DirtyColor;
  493. }
  494. }
  495. //Set the ClusterArray nibbles to the appropriate color for this extent.
  496. //If the extent starts on an odd number,
  497. //then the first cluster is a high nibble of one byte.
  498. if(StartingLcn % 2){
  499. //Clear out that high nibble.
  500. pClusterArray[StartingLcn / 2] &= 0x0F;
  501. //Put our color in it.
  502. pClusterArray[StartingLcn / 2] |= (Color & 0xF0);
  503. //Change the counters to reflect that we wrote this cluster.
  504. ClusterCount --;
  505. StartingLcn ++;
  506. }
  507. //Fill in the middle range that consists of whole bytes
  508. //(high and low nibbles) needing to be set.
  509. if(ClusterCount != 0){
  510. FillMemory(pClusterArray + (StartingLcn / 2), ClusterCount / 2, Color);
  511. }
  512. //If the extent ends on an odd number,
  513. //then the last cluster is a low nibble of one byte.
  514. if ((ClusterCount % 2) && (ClusterCount != 0)) {
  515. //Update counter to point to it after previous writes.
  516. StartingLcn += ClusterCount - 1;
  517. //Clear out that low nibble.
  518. pClusterArray[StartingLcn / 2] &= 0xF0;
  519. //Put our color in it.
  520. pClusterArray[StartingLcn / 2] |= (Color & 0x0F);
  521. }
  522. }
  523. //Point to the next series of extents (since the for loop we just exited exits
  524. //when all the extents in that series have been done).
  525. pBuffer = (PBYTE)pUpdateArray;
  526. }
  527. }
  528. __finally
  529. {
  530. ::LeaveCriticalSection(&m_CriticalSection);
  531. }
  532. }
  533. /*
  534. METHOD: DiskView::TransferToLineArray
  535. DESCRIPTION:
  536. Create the compressed line array from the current data in the cluster array.
  537. RETURN:
  538. TRUE=ok, FALSE=error.
  539. */
  540. BOOL DiskView::TransferToLineArray()
  541. {
  542. // make sure we have the arrays
  543. if (!m_IsActive || pClusterArray == NULL || pLineArray == NULL) {
  544. return FALSE;
  545. }
  546. EF_ASSERT(ClusterFactor > 0);
  547. EF_ASSERT(NumLines > 0);
  548. __try
  549. {
  550. ::EnterCriticalSection(&m_CriticalSection);
  551. CLASSINVARIANT();
  552. // loop variables
  553. int nClust; // nClust = cluster number
  554. int nClustByte; // nClustByte = byte in cluster array
  555. // (nClust / 2, bytes to nibbles)
  556. BOOL bHighNibble; // bHighNibble = TRUE for high nibble and FALSE for low nibble
  557. // (stored one cluster per nibble)
  558. int nLine; // nLine = line number
  559. char cClustColor; // current cluster's color
  560. UINT nUsed; // number of used clusters in this line
  561. UINT nFree; // number of free clusters in this line
  562. UINT nFrag; // fragmented cluster(s) in this line
  563. UINT nNonMovable; // number of non movable clusters in this line
  564. BOOL bNonMovable; // system file cluster(s) in this line
  565. BOOL bMftFragmented; // MFT in this line sks added MFT defrag
  566. BOOL bMftUnFragmented; // MFT in this line sks added MFT defrag
  567. // loop through line array
  568. for (nLine = 0; nLine < NumLines; nLine++) {
  569. // if this item is not dirty, move on
  570. if (pLineArray[nLine] != DirtyColor) {
  571. continue;
  572. }
  573. // initialize line variables
  574. nUsed = 0;
  575. nFree = 0;
  576. nFrag = 0;
  577. nNonMovable = 0; //bug#184739 sks 9/18/2000
  578. bNonMovable = FALSE;
  579. bMftFragmented = FALSE;
  580. bMftUnFragmented = FALSE;
  581. // reset to the starting point for this line
  582. nClust = nLine * ClusterFactor;
  583. // loop through the clusters in this line
  584. for (int ii = 0; ii < ClusterFactor && nClust < Clusters; ii++, nClust++) {
  585. // set loop variables
  586. nClustByte = nClust / 2; // cluster array byte index
  587. bHighNibble = (nClust % 2) ? TRUE : FALSE; // which nibble in byte?
  588. // get the current cluster's color
  589. // (the >> 4 extracts the high nibble, the & 0x0F extracts the low nibble)
  590. if(bHighNibble) {
  591. cClustColor = pClusterArray[nClustByte] >> 4;
  592. }
  593. else {
  594. cClustColor = pClusterArray[nClustByte] & 0x0F;
  595. }
  596. // evaluate the color
  597. switch (cClustColor) {
  598. case SystemFileColor:
  599. case PageFileColor:
  600. nNonMovable++; //bug#184739 sks 9/18/2000
  601. break;
  602. case FragmentColor:
  603. nFrag++;
  604. break;
  605. case UsedSpaceColor:
  606. case DirectoryColor:
  607. nUsed++;
  608. break;
  609. case FreeSpaceColor:
  610. nFree++;
  611. break;
  612. default:
  613. __leave;
  614. break;
  615. }
  616. //bug#184739 sks 9/18/2000
  617. // system file overrides all, break out of inner loop
  618. } // end inner loop: clusters in current line
  619. //
  620. // #243245 changing the color scheme as follows
  621. //
  622. // Add the current file counts for each type to our running
  623. // total. Think of this running total as "the file-counts of each
  624. // type that were ignored in the previous lines displayed."
  625. //
  626. // For each line, then test which running total is more:
  627. // contiguous, unmovable, fragmented files or free space.
  628. //
  629. // Whoever is greater wins, (if all are equal, fragmented wins)
  630. // Subtract the ClusterFactor from the running count for the
  631. // winner (since this line is his)
  632. //
  633. m_nFreeDelta += nFree;
  634. m_nFragDelta += nFrag;
  635. m_nNonMovableDelta += nNonMovable;
  636. m_nUsedDelta += nUsed;
  637. if((m_nFragDelta > m_nNonMovableDelta) &&
  638. (m_nFragDelta > m_nFreeDelta) &&
  639. (m_nFragDelta > m_nUsedDelta)
  640. ) {
  641. //
  642. // Fragmented is greatest
  643. //
  644. m_nFragDelta -= ClusterFactor;
  645. pLineArray[nLine] = FragmentColor;
  646. }
  647. else if ((m_nUsedDelta > m_nFreeDelta) &&
  648. (m_nUsedDelta > m_nNonMovableDelta) &&
  649. (m_nUsedDelta > m_nFragDelta)
  650. ) {
  651. //
  652. // Used is greatest
  653. //
  654. m_nUsedDelta -= ClusterFactor;
  655. pLineArray[nLine] = UsedSpaceColor;
  656. }
  657. else if ((m_nFreeDelta > m_nUsedDelta) &&
  658. (m_nFreeDelta > m_nNonMovableDelta) &&
  659. (m_nFreeDelta > m_nFragDelta)
  660. ) {
  661. //
  662. // Free is greatest
  663. //
  664. m_nFreeDelta -= ClusterFactor;
  665. pLineArray[nLine] = FreeSpaceColor;
  666. }
  667. else if ((m_nNonMovableDelta > m_nUsedDelta) &&
  668. (m_nNonMovableDelta > m_nFreeDelta) &&
  669. (m_nNonMovableDelta > m_nFragDelta)
  670. ) {
  671. //
  672. // Nonmovable is greatest
  673. //
  674. m_nNonMovableDelta -= ClusterFactor;
  675. pLineArray[nLine] = SystemFileColor;
  676. }
  677. else {
  678. //
  679. // They're all equal--use Fragmented colour
  680. //
  681. m_nFragDelta -= ClusterFactor;
  682. pLineArray[nLine] = FragmentColor;
  683. }
  684. } // end outer loop: lines
  685. }
  686. __finally
  687. {
  688. ::LeaveCriticalSection(&m_CriticalSection);
  689. }
  690. return TRUE;
  691. }
  692. /*
  693. METHOD: DiskView::Invariant
  694. DESCRIPTION:
  695. Check the internal state of a DiskView instance.
  696. */
  697. BOOL DiskView::Invariant() const
  698. {
  699. // clusters
  700. EF((pClusterArray == NULL && Clusters == 0) ||
  701. (pClusterArray != NULL && Clusters > 0));
  702. EF(ClusterArraySize == Clusters / 2 + Clusters % 2); // one cluster per nibble
  703. // lines
  704. EF((pLineArray == NULL && NumLines == 0) ||
  705. (pLineArray != NULL && NumLines > 0));
  706. EF((NumLines == 0 && ClusterFactor == 0) ||
  707. (NumLines > 0 && ClusterFactor > 0));
  708. // MFT zone
  709. EF(MftZoneEnd >= MftZoneStart);
  710. return TRUE;
  711. }
  712. /*
  713. METHOD: DiskView::HasMapMemory
  714. DESCRIPTION:
  715. Check if the DiskView has memory for the cluster array
  716. (and line array if applicable).
  717. */
  718. BOOL DiskView::HasMapMemory() const
  719. {
  720. return !m_bMemAllocFailed;
  721. }
  722. /*
  723. METHOD: DiskView::EnterMyCriticalSection()
  724. DESCRIPTION:
  725. Enter the critical section, so that when we terminate thread was have the critical section
  726. bug #26213 sks .
  727. */
  728. void DiskView::EnterMyCriticalSection()
  729. {
  730. ::EnterCriticalSection(&m_CriticalSection);
  731. }
  732. /*
  733. METHOD: DiskView::LeaveMyCriticalSection()
  734. DESCRIPTION:
  735. Leave the critical section, so that when we terminate thread was have the critical section
  736. bug #26213 sks .
  737. */
  738. void DiskView::LeaveMyCriticalSection()
  739. {
  740. ::LeaveCriticalSection(&m_CriticalSection);
  741. }