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.

861 lines
23 KiB

  1. #include "enduser.h"
  2. VOID
  3. TransferNonClusterData(
  4. IN HDISK DiskHandle,
  5. IN OUT ULONG *SourceStart,
  6. IN OUT ULONG *TargetStart
  7. );
  8. VOID
  9. ExpandFromStart(
  10. IN HDISK DiskHandle,
  11. IN ULONG SourceStart,
  12. IN ULONG TargetStart
  13. );
  14. VOID
  15. ExpandFromEnd(
  16. IN HDISK DiskHandle,
  17. IN ULONG SourceStart,
  18. IN ULONG TargetStart
  19. );
  20. VOID
  21. InitializeClusterMapForward(
  22. IN HDISK DiskHandle
  23. );
  24. VOID
  25. InitializeClusterMapReverse(
  26. IN HDISK DiskHandle
  27. );
  28. VOID
  29. GetForwardClusterRun(
  30. IN HDISK DiskHandle,
  31. OUT ULONG *StartCluster,
  32. OUT ULONG *StartOffset,
  33. OUT ULONG *ClusterCount
  34. );
  35. VOID
  36. GetReverseClusterRun(
  37. IN HDISK DiskHandle,
  38. OUT ULONG *StartCluster,
  39. OUT ULONG *StartOffset,
  40. OUT ULONG *ClusterCount
  41. );
  42. VOID
  43. Fat32ExpandOneFat(
  44. IN HDISK DiskHandle,
  45. IN OUT ULONG *SourceStart,
  46. IN OUT ULONG *TargetStart,
  47. IN ULONG Fat32FatSectorCount,
  48. IN ULONG Fat32AdjustedFatSectorCount
  49. );
  50. VOID
  51. ExpandImage(
  52. IN HDISK DiskHandle,
  53. IN BYTE SectorsPerTrack,
  54. IN ULONG SourceStart,
  55. IN ULONG TargetStart
  56. )
  57. {
  58. //
  59. // Transfer non-cluster data to the start of the drive.
  60. //
  61. TransferNonClusterData(DiskHandle,&SourceStart,&TargetStart);
  62. //
  63. // Expand out data from the image moving forward until we either
  64. // run out of image or we would overwrite data in the image we
  65. // haven't used yet.
  66. //
  67. ExpandFromStart(DiskHandle,SourceStart,TargetStart);
  68. //
  69. // Expand out data from the image moving backwards until we
  70. // reach the point at which the forward transfer above stopped.
  71. //
  72. ExpandFromEnd(DiskHandle,SourceStart,TargetStart);
  73. }
  74. VOID
  75. TransferNonClusterData(
  76. IN HDISK DiskHandle,
  77. IN OUT ULONG *SourceStart,
  78. IN OUT ULONG *TargetStart
  79. )
  80. {
  81. ULONG Write;
  82. ULONG Count;
  83. ULONG Offset;
  84. ULONG Fat32FatSectorCount;
  85. ULONG Fat32AdjustedFatSectorCount;
  86. BOOL Xms;
  87. _Log("Transfer non cluster data, source = 0x%lx, target = 0x%lx\n",*SourceStart,*TargetStart);
  88. //
  89. // See if we've already done this step.
  90. //
  91. if(!CmdLineArgs.Test && (MasterDiskInfo.State >= MDS_DID_NONCLUSTER_DATA)) {
  92. _Log("Non cluster data already transferred\n");
  93. *SourceStart += PartitionImage.NonClusterSectors;
  94. *TargetStart += PartitionImage.NonClusterSectors;
  95. GaugeDelta(2*PartitionImage.NonClusterSectors);
  96. return;
  97. }
  98. //
  99. // this wil be zero if not resizing (FAT32)
  100. //
  101. if(PartitionImage.Fat32AdjustedSectorCount) {
  102. _Log("Non cluster data sectors previously processed = 0x%lx\n",MasterDiskInfo.NonClusterSectorsDone);
  103. GaugeDelta(2*MasterDiskInfo.NonClusterSectorsDone);
  104. //
  105. // Fat32 case
  106. //
  107. // BUGBUG We run into big problems if the image is located right at the beginning of the disk.
  108. // This needs to be prevented in makemast.
  109. //
  110. //
  111. // Get the old size of the FAT in sectors.
  112. //
  113. Fat32FatSectorCount = PartitionImage.Fat32OriginalFatTableSectCount;
  114. //
  115. // Calculate the new size of the FAT in sectors.
  116. //
  117. Fat32AdjustedFatSectorCount = PartitionImage.Fat32AdjustedFatTableEntryCount/(512/4);
  118. Fat32AdjustedFatSectorCount = (PartitionImage.Fat32AdjustedFatTableEntryCount%(512/4)) ?
  119. Fat32AdjustedFatSectorCount++: Fat32AdjustedFatSectorCount;
  120. Offset = 0;
  121. //
  122. // all right, restore the reserved sectors at the beginning of the disk
  123. // since the number of reserved sectors for FAT32 is small, just read
  124. // and write them all at once.
  125. //
  126. if( MasterDiskInfo.NonClusterSectorsDone < PartitionImage.Fat32ReservedSectors ) {
  127. //
  128. // if we haven't already done this
  129. //
  130. XmsIoDiskRead(
  131. DiskHandle,
  132. *SourceStart,
  133. PartitionImage.Fat32ReservedSectors,
  134. &Write,
  135. &Xms
  136. );
  137. XmsIoDiskWrite(DiskHandle,*TargetStart,Offset,Write,Xms);
  138. _Log("Restore %lu reserved sectors from 0x%lx\n",Write,*SourceStart);
  139. MasterDiskInfo.NonClusterSectorsDone += Write;
  140. if(!CmdLineArgs.Test) {
  141. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  142. }
  143. }
  144. *SourceStart += PartitionImage.Fat32ReservedSectors;
  145. *TargetStart += PartitionImage.Fat32ReservedSectors;
  146. //
  147. // now do the first FAT table
  148. //
  149. _Log("Restore FAT32 tables.\n");
  150. if( MasterDiskInfo.NonClusterSectorsDone <
  151. ( PartitionImage.Fat32ReservedSectors + Fat32FatSectorCount )) {
  152. //
  153. // if we haven't already done this
  154. //
  155. _Log("Restore first FAT.\n");
  156. Fat32ExpandOneFat( DiskHandle,
  157. SourceStart,
  158. TargetStart,
  159. Fat32FatSectorCount,
  160. Fat32AdjustedFatSectorCount
  161. );
  162. } else {
  163. _Log("First FAT already restored.\n");
  164. }
  165. //
  166. // now do the second FAT table
  167. //
  168. _Log("Restore second FAT.\n");
  169. Fat32ExpandOneFat( DiskHandle,
  170. SourceStart,
  171. TargetStart,
  172. Fat32FatSectorCount,
  173. Fat32AdjustedFatSectorCount
  174. );
  175. } else {
  176. //
  177. // Other file systems
  178. //
  179. _Log("Non cluster data sectors previously processed = 0x%lx\n",MasterDiskInfo.NonClusterSectorsDone);
  180. GaugeDelta(2*MasterDiskInfo.NonClusterSectorsDone);
  181. *SourceStart += MasterDiskInfo.NonClusterSectorsDone;
  182. *TargetStart += MasterDiskInfo.NonClusterSectorsDone;
  183. while(MasterDiskInfo.NonClusterSectorsDone < PartitionImage.NonClusterSectors) {
  184. XmsIoDiskRead(
  185. DiskHandle,
  186. *SourceStart,
  187. PartitionImage.NonClusterSectors - MasterDiskInfo.NonClusterSectorsDone,
  188. &Write,
  189. &Xms
  190. );
  191. _Log("Read %lu non-cluster sectors from 0x%lx\n",Write,*SourceStart);
  192. Offset = 0;
  193. while(Write) {
  194. //
  195. // Write as large a chunk as possible without overlap.
  196. //
  197. if((*TargetStart + Write) > *SourceStart) {
  198. Count = *SourceStart - *TargetStart;
  199. } else {
  200. Count = Write;
  201. }
  202. XmsIoDiskWrite(DiskHandle,*TargetStart,Offset,Count,Xms);
  203. Write -= Count;
  204. *SourceStart += Count;
  205. Offset += Count;
  206. MasterDiskInfo.NonClusterSectorsDone += Count;
  207. if(!CmdLineArgs.Test) {
  208. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  209. }
  210. _Log("Wrote %lu non-cluster sectors to 0x%lx\n",Count,*TargetStart);
  211. *TargetStart += Count;
  212. }
  213. }
  214. }
  215. //
  216. // Update master disk state to indicate that we're done with this step.
  217. //
  218. if(!CmdLineArgs.Test) {
  219. UpdateMasterDiskState(DiskHandle,MDS_DID_NONCLUSTER_DATA);
  220. }
  221. }
  222. VOID
  223. ExpandFromStart(
  224. IN HDISK DiskHandle,
  225. IN ULONG SourceStart,
  226. IN ULONG TargetStart
  227. )
  228. {
  229. ULONG Start,Offset,Count;
  230. ULONG SourceFirst;
  231. ULONG TargetFirst;
  232. ULONG SoFar;
  233. ULONG u;
  234. BOOL Xms;
  235. ULONG Write;
  236. //
  237. // See if we've already done this step.
  238. //
  239. if(!CmdLineArgs.Test && (MasterDiskInfo.State >= MDS_DID_XFER_FORWARD)) {
  240. _Log("Already did expand in forward direction\n");
  241. GaugeDelta(2*MasterDiskInfo.ForwardXferSectorCount);
  242. return;
  243. }
  244. _Log("\nStarting forward expansion, sectors previously done = 0x%lx\n",MasterDiskInfo.ForwardXferSectorCount);
  245. InitializeClusterMapForward(DiskHandle);
  246. SoFar = 0;
  247. //
  248. // Get a run of clusters and calculate the first and last sector
  249. // of the source and the target. If there are no more clusters left,
  250. // we're done.
  251. //
  252. nextrun:
  253. GetForwardClusterRun(DiskHandle,&Start,&Offset,&Count);
  254. if(!Count) {
  255. if(!CmdLineArgs.Test) {
  256. UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_FORWARD);
  257. }
  258. return;
  259. }
  260. Start *= PartitionImage.SectorsPerCluster;
  261. Offset *= PartitionImage.SectorsPerCluster;
  262. Count *= PartitionImage.SectorsPerCluster;
  263. _Log("\nSector run: start = 0x%lx, count = 0x%lx, offset = 0x%lx\n",Start,Count,Offset);
  264. //
  265. // See if we're already done this xfer or part of it on a previous pass.
  266. // Note that SoFar cannot ever be greater than
  267. // MasterDiskInfo.ForwardXFerSectorCount because we increment them both
  268. // by the same amount after a transfer. In most cases they will be equal.
  269. //
  270. if((SoFar+Count) <= MasterDiskInfo.ForwardXferSectorCount) {
  271. _Log("Already did this run, skipping\n");
  272. SoFar += Count;
  273. GaugeDelta(2*Count);
  274. goto nextrun;
  275. }
  276. if(u = (MasterDiskInfo.ForwardXferSectorCount - SoFar)) {
  277. //
  278. // We know that Count > MasterDiskInfo.ForwardXFerSectorCount - SoFar,
  279. // which means that if we get here, Count > u >= 1.
  280. //
  281. // Adjust the counts and fall through. Note that after this from now on
  282. // MasterDiskInfo.ForwardXFerSectorCount == SoFar, meaning neither this
  283. // nor the previous if clause will be triggered.
  284. //
  285. _Log("Already partially did this run, adjusting\n");
  286. SoFar += u;
  287. Start += u;
  288. Offset += u;
  289. Count -= u;
  290. GaugeDelta(2*u);
  291. }
  292. SourceFirst = SourceStart + Offset;
  293. TargetFirst = TargetStart + Start;
  294. //
  295. // If writing to the target would hose over data we haven't
  296. // read from the source yet, we're done with the forward expansion.
  297. //
  298. if(SourceFirst < TargetFirst) {
  299. _Log("Target passes source, done with forward expansion\n");
  300. if(!CmdLineArgs.Test) {
  301. UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_FORWARD);
  302. }
  303. return;
  304. }
  305. //
  306. // If the source and target are the same, nothing to do.
  307. // Otherwise, do our thing.
  308. //
  309. if(SourceFirst == TargetFirst) {
  310. _Log("Source is same as target\n");
  311. SoFar += Count;
  312. MasterDiskInfo.ForwardXferSectorCount += Count;
  313. if(!CmdLineArgs.Test) {
  314. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  315. }
  316. GaugeDelta(2*Count);
  317. } else {
  318. while(Count) {
  319. XmsIoDiskRead(DiskHandle,SourceFirst,Count,&Write,&Xms);
  320. _Log("Read %lu sectors from 0x%lx\n",Write,SourceFirst);
  321. Offset = 0;
  322. while(Write) {
  323. //
  324. // Write as large a run as possible without overlap.
  325. //
  326. if((TargetFirst+Write) > SourceFirst) {
  327. u = SourceFirst - TargetFirst;
  328. } else {
  329. u = Write;
  330. }
  331. _Log("Writing %lu sectors to 0x%lx\n",u,TargetFirst);
  332. XmsIoDiskWrite(DiskHandle,TargetFirst,Offset,u,Xms);
  333. //
  334. // Update vars
  335. //
  336. SoFar += u;
  337. SourceFirst += u;
  338. Offset += u;
  339. Write -= u;
  340. Count -= u;
  341. MasterDiskInfo.ForwardXferSectorCount += u;
  342. if(!CmdLineArgs.Test) {
  343. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  344. }
  345. _Log("Wrote %lu sectors to 0x%lx\n",u,TargetFirst);
  346. TargetFirst += u;
  347. }
  348. }
  349. }
  350. //
  351. // Process additional clusters.
  352. //
  353. goto nextrun;
  354. }
  355. VOID
  356. ExpandFromEnd(
  357. IN HDISK DiskHandle,
  358. IN ULONG SourceStart,
  359. IN ULONG TargetStart
  360. )
  361. {
  362. ULONG End,Offset,Count;
  363. ULONG SourceEnd;
  364. ULONG TargetEnd;
  365. ULONG SoFar;
  366. ULONG u;
  367. BOOL Xms;
  368. ULONG Write;
  369. //
  370. // See if we've already done this step.
  371. //
  372. if(!CmdLineArgs.Test && (MasterDiskInfo.State >= MDS_DID_XFER_REVERSE)) {
  373. _Log("Already did expand in reverse direction\n");
  374. GaugeDelta(2*MasterDiskInfo.ReverseXferSectorCount);
  375. return;
  376. }
  377. _Log("Starting reverse expansion, sectors previously done = 0x%lx\n",MasterDiskInfo.ReverseXferSectorCount);
  378. InitializeClusterMapReverse(DiskHandle);
  379. SoFar = 0;
  380. //
  381. // Get a run of clusters and calculate the first and last sector
  382. // of the source and the target. If there are no more clusters left,
  383. // we're done.
  384. //
  385. nextrun:
  386. GetReverseClusterRun(DiskHandle,&End,&Offset,&Count);
  387. if(!Count) {
  388. if(!CmdLineArgs.Test) {
  389. UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_REVERSE);
  390. }
  391. return;
  392. }
  393. End = (End + 1) * PartitionImage.SectorsPerCluster;
  394. Offset = (Offset + 1) * PartitionImage.SectorsPerCluster;
  395. Count *= PartitionImage.SectorsPerCluster;
  396. _Log("\nSector run: end = 0x%lx, count = 0x%lx, offset = 0x%lx\n",End,Count,Offset);
  397. //
  398. // See if we're already done this xfer or part of it on a previous pass.
  399. // Note that SoFar cannot ever be greater than
  400. // MasterDiskInfo.ReverseXFerSectorCount because we increment them both
  401. // by the same amount after a transfer. In most cases they will be equal.
  402. //
  403. if((SoFar+Count) <= MasterDiskInfo.ReverseXferSectorCount) {
  404. _Log("Already did this run, skipping\n");
  405. SoFar += Count;
  406. GaugeDelta(2*Count);
  407. goto nextrun;
  408. }
  409. if(u = (MasterDiskInfo.ReverseXferSectorCount - SoFar)) {
  410. //
  411. // We know that Count > MasterDiskInfo.ReverseXFerSectorCount - SoFar,
  412. // which means that if we get here, Count > u >= 1.
  413. //
  414. // Adjust the counts and fall through. Note that after this from now on
  415. // MasterDiskInfo.ReverseXFerSectorCount == SoFar, meaning neither this
  416. // nor the previous if clause will be triggered.
  417. //
  418. _Log("Already partially did this run, adjusting\n");
  419. SoFar += u;
  420. End -= u;
  421. Offset -= u;
  422. Count -= u;
  423. GaugeDelta(2*u);
  424. }
  425. SourceEnd = SourceStart + Offset;
  426. TargetEnd = TargetStart + End;
  427. //
  428. // If writing to the target would hose over data we haven't
  429. // read from the source yet, we're done.
  430. //
  431. if(TargetEnd < SourceEnd) {
  432. _Log("Target passes source, done with reverse expansion\n");
  433. if(!CmdLineArgs.Test) {
  434. UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_REVERSE);
  435. }
  436. return;
  437. }
  438. //
  439. // If the source and target are the same, nothing to do.
  440. // (Note: this case should not occur, since we would have
  441. // picked it up on the forward scan. But just in case,
  442. // we handle it anyway.)
  443. // Otherwise, do our thing.
  444. //
  445. if(SourceEnd == TargetEnd) {
  446. _Log("Source is same as target\n");
  447. SoFar += Count;
  448. MasterDiskInfo.ReverseXferSectorCount += Count;
  449. if(!CmdLineArgs.Test) {
  450. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  451. }
  452. GaugeDelta(2*Count);
  453. } else {
  454. while(Count) {
  455. XmsIoDiskRead(DiskHandle,SourceEnd-Count,Count,&Write,&Xms);
  456. _Log("Read %lu sectors from 0x%lx\n",Write,SourceEnd-Count);
  457. Offset = Write;
  458. while(Write) {
  459. //
  460. // Write as large a run as possible without overlap.
  461. //
  462. if((TargetEnd-Write) < SourceEnd) {
  463. u = TargetEnd - SourceEnd;
  464. } else {
  465. u = Write;
  466. }
  467. _Log("Writing %lu sectors to 0x%lx\n",u,TargetEnd-u);
  468. XmsIoDiskWrite(DiskHandle,TargetEnd-u,Offset-u,u,Xms);
  469. //
  470. // Update vars
  471. //
  472. SoFar += u;
  473. SourceEnd -= u;
  474. TargetEnd -= u;
  475. Offset -= u;
  476. Write -= u;
  477. Count -= u;
  478. MasterDiskInfo.ReverseXferSectorCount += u;
  479. if(!CmdLineArgs.Test) {
  480. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  481. }
  482. _Log("Wrote %lu sectors to 0x%lx\n",u,TargetEnd);
  483. }
  484. }
  485. }
  486. //
  487. // Process additional clusters.
  488. //
  489. goto nextrun;
  490. }
  491. ////////////////////////////////////////////////////
  492. ULONG _NextClusterToExamine;
  493. BYTE _ClusterBuffer[512];
  494. ULONG _BufferedClusterMapSector;
  495. ULONG _ClusterBufferBase;
  496. ULONG _ClusterOffset;
  497. BOOL _First;
  498. BYTE BitValue[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
  499. VOID
  500. InitializeClusterMapForward(
  501. IN HDISK DiskHandle
  502. )
  503. {
  504. //
  505. // Read the first sector of the cluster bitmap.
  506. //
  507. if(!ReadDisk(DiskHandle,MasterDiskInfo.ClusterBitmapStart,1,IoBuffer)) {
  508. FatalError(textReadFailedAtSector,1,MasterDiskInfo.ClusterBitmapStart);
  509. }
  510. memmove(_ClusterBuffer,IoBuffer,512);
  511. _BufferedClusterMapSector = MasterDiskInfo.ClusterBitmapStart;
  512. _NextClusterToExamine = 0;
  513. _ClusterBufferBase = 0;
  514. _ClusterOffset = 0;
  515. }
  516. VOID
  517. GetForwardClusterRun(
  518. IN HDISK DiskHandle,
  519. OUT ULONG *StartCluster,
  520. OUT ULONG *StartOffset,
  521. OUT ULONG *ClusterCount
  522. )
  523. {
  524. UINT cluster;
  525. BOOL b;
  526. *ClusterCount = 0;
  527. //
  528. // Locate the next 1 bit in the map.
  529. //
  530. while(_NextClusterToExamine <= PartitionImage.LastUsedCluster) {
  531. //
  532. // Reload the cluster buffer if necessary.
  533. //
  534. if(_NextClusterToExamine && !(_NextClusterToExamine % CLUSTER_BITS_PER_SECTOR)) {
  535. if(!ReadDisk(DiskHandle,++_BufferedClusterMapSector,1,IoBuffer)) {
  536. FatalError(textReadFailedAtSector,1,_BufferedClusterMapSector);
  537. }
  538. memmove(_ClusterBuffer,IoBuffer,512);
  539. _ClusterBufferBase += CLUSTER_BITS_PER_SECTOR;
  540. }
  541. cluster = (UINT)(_NextClusterToExamine - _ClusterBufferBase);
  542. //
  543. // See if this bit is one, which starts a run of used clusters.
  544. // To simplify things, we won't return a run that spans sectors
  545. // in the cluster bitmap.
  546. //
  547. b = FALSE;
  548. while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
  549. && (cluster < CLUSTER_BITS_PER_SECTOR)
  550. && (_NextClusterToExamine <= PartitionImage.LastUsedCluster)) {
  551. if(!b) {
  552. *StartOffset = _ClusterOffset;
  553. *StartCluster = _NextClusterToExamine;
  554. b = TRUE;
  555. }
  556. *ClusterCount += 1;
  557. cluster++;
  558. _NextClusterToExamine++;
  559. _ClusterOffset++;
  560. }
  561. if(b) {
  562. return;
  563. }
  564. _NextClusterToExamine++;
  565. }
  566. }
  567. VOID
  568. InitializeClusterMapReverse(
  569. IN HDISK DiskHandle
  570. )
  571. {
  572. ULONG Sector;
  573. //
  574. // Read the last sector of the cluster bitmap.
  575. //
  576. Sector = MasterDiskInfo.ClusterBitmapStart
  577. + (PartitionImage.LastUsedCluster/CLUSTER_BITS_PER_SECTOR);
  578. if(!ReadDisk(DiskHandle,Sector,1,IoBuffer)) {
  579. FatalError(textReadFailedAtSector,1,Sector);
  580. }
  581. memmove(_ClusterBuffer,IoBuffer,512);
  582. _BufferedClusterMapSector = Sector;
  583. _NextClusterToExamine = PartitionImage.LastUsedCluster;
  584. _ClusterBufferBase = (PartitionImage.LastUsedCluster / CLUSTER_BITS_PER_SECTOR)
  585. * CLUSTER_BITS_PER_SECTOR;
  586. _ClusterOffset = PartitionImage.UsedClusterCount-1;
  587. _First = TRUE;
  588. }
  589. VOID
  590. GetReverseClusterRun(
  591. IN HDISK DiskHandle,
  592. OUT ULONG *StartCluster,
  593. OUT ULONG *StartOffset,
  594. OUT ULONG *ClusterCount
  595. )
  596. {
  597. UINT cluster;
  598. BOOL b;
  599. *ClusterCount = 0;
  600. //
  601. // Locate the next 1 bit in the map.
  602. //
  603. while(_NextClusterToExamine != (ULONG)(-1)) {
  604. //
  605. // Reload the cluster buffer if necessary.
  606. //
  607. if(((_NextClusterToExamine % CLUSTER_BITS_PER_SECTOR) == (CLUSTER_BITS_PER_SECTOR-1)) && !_First) {
  608. if(!ReadDisk(DiskHandle,--_BufferedClusterMapSector,1,IoBuffer)) {
  609. FatalError(textReadFailedAtSector,1,_BufferedClusterMapSector);
  610. }
  611. memmove(_ClusterBuffer,IoBuffer,512);
  612. _ClusterBufferBase -= CLUSTER_BITS_PER_SECTOR;
  613. }
  614. _First = FALSE;
  615. cluster = (UINT)(_NextClusterToExamine - _ClusterBufferBase);
  616. //
  617. // See if this bit is one, which starts a run of used clusters.
  618. // To simplify things, we won't return a run that spans sectors
  619. // in the cluster bitmap.
  620. //
  621. b = FALSE;
  622. while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
  623. && (cluster != (UINT)(-1))
  624. && (_NextClusterToExamine != (ULONG)(-1))) {
  625. if(!b) {
  626. *StartCluster = _NextClusterToExamine;
  627. *StartOffset = _ClusterOffset;
  628. b = TRUE;
  629. }
  630. *ClusterCount += 1;
  631. cluster--;
  632. _NextClusterToExamine--;
  633. _ClusterOffset--;
  634. }
  635. if(b) {
  636. return;
  637. }
  638. _NextClusterToExamine--;
  639. }
  640. return;
  641. }
  642. VOID
  643. Fat32ExpandOneFat(
  644. IN HDISK DiskHandle,
  645. IN OUT ULONG *SourceStart,
  646. IN OUT ULONG *TargetStart,
  647. IN ULONG Fat32FatSectorCount,
  648. IN ULONG Fat32AdjustedFatSectorCount
  649. )
  650. {
  651. ULONG RemainingSectors;
  652. ULONG Counter;
  653. ULONG Write;
  654. ULONG Offset;
  655. BOOL Xms;
  656. RemainingSectors = Fat32FatSectorCount;
  657. Offset = 0;
  658. //
  659. // now restore the FAT table
  660. //
  661. while( RemainingSectors ) {
  662. XmsIoDiskRead(
  663. DiskHandle,
  664. *SourceStart,
  665. RemainingSectors,
  666. &Write,
  667. &Xms
  668. );
  669. XmsIoDiskWrite(DiskHandle,*TargetStart,Offset,Write,Xms);
  670. RemainingSectors -= Write;
  671. *SourceStart += Write;
  672. *TargetStart += Write;
  673. if(!CmdLineArgs.Test) {
  674. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  675. }
  676. MasterDiskInfo.NonClusterSectorsDone += Write; // the final update is delayed until we
  677. // fill the rest of the FAT with zeros.
  678. }
  679. //
  680. // zero out the rest of the FAT table.
  681. //
  682. memset(IoBuffer, 0, 512);
  683. for(Counter=0; Counter<Fat32AdjustedFatSectorCount-Fat32FatSectorCount; Counter++ ) {
  684. if(!CmdLineArgs.Test) {
  685. WriteDisk(DiskHandle,*TargetStart,1,IoBuffer);
  686. }
  687. (*TargetStart)++;
  688. }
  689. //
  690. // putting the final update here insures that we are done with zeroing the FAT out.
  691. //
  692. if(!CmdLineArgs.Test) {
  693. UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
  694. }
  695. return;
  696. }