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.

227 lines
4.7 KiB

  1. #include "imagpart.h"
  2. BOOL
  3. BuildClusterBitmap(
  4. IN FilesystemType FsType,
  5. IN HPARTITION PartitionHandle,
  6. IN UINT FileHandle,
  7. IN OUT PARTITION_IMAGE *PartitionImage
  8. )
  9. /*++
  10. Routine Description:
  11. This routine builds a bitmap representing all clusters in the
  12. source volume, 1 bit per cluster (0=unused, 1=used). The bitmap
  13. is written into a file.
  14. Arguments:
  15. FsType - supplies the type of the file system
  16. PartitionHandle - supplies handle to source partition
  17. FileHandle - supplies handle for output file. It is assumed that
  18. this file is empty. On output this file is rewound to offset 0.
  19. PartitionImage - supplies information about the source partition.
  20. On output, the following fields are filled in:
  21. LastUsedCluster
  22. UsedClusterCount
  23. Return Value:
  24. Boolean value indicating outcome. If false, a message will have been
  25. printed out explaining why.
  26. --*/
  27. {
  28. BOOL b;
  29. if(FsType == FilesystemFat) {
  30. b = FatBuildClusterBitmap(PartitionHandle,FileHandle,PartitionImage);
  31. } else {
  32. if(FsType == FilesystemNtfs) {
  33. b = NtfsBuildClusterBitmap(PartitionHandle,FileHandle,PartitionImage);
  34. } else {
  35. fprintf(stderr,"\n%s\n",textUnsupportedFs);
  36. b = FALSE;
  37. }
  38. }
  39. if(b) {
  40. DosSeek(FileHandle,0,DOSSEEK_START);
  41. }
  42. return(b);
  43. }
  44. FPBYTE _ClusterBuffer;
  45. ULONG _BaseCluster;
  46. UINT _ClusterFileHandle;
  47. ULONG _LastUsedCluster;
  48. ULONG _NextClusterToExamine;
  49. BYTE BitValue[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
  50. VOID
  51. InitClusterBuffer(
  52. IN FPBYTE _512ByteBuffer,
  53. IN UINT FileHandle
  54. )
  55. {
  56. _ClusterBuffer = _512ByteBuffer;
  57. _BaseCluster = 0L;
  58. _ClusterFileHandle = FileHandle;
  59. memset(_512ByteBuffer,0,512);
  60. }
  61. BOOL
  62. MarkClusterUsed(
  63. IN ULONG Cluster
  64. )
  65. {
  66. unsigned Written;
  67. BOOL NeedToZero;
  68. //
  69. // See if the cluster we're updating is past the end of what
  70. // we're currently buffering. Note that it could be way beyond.
  71. //
  72. NeedToZero = TRUE;
  73. while(Cluster >= _BaseCluster+(8*512)) {
  74. if(_dos_write(_ClusterFileHandle,_ClusterBuffer,512,&Written) || (Written != 512)) {
  75. fprintf(stderr,"\n%s\n",textFileWriteError);
  76. return(FALSE);
  77. }
  78. _BaseCluster += 8*512;
  79. if(NeedToZero) {
  80. memset(_ClusterBuffer,0,512);
  81. NeedToZero = FALSE;
  82. }
  83. }
  84. //
  85. // Set the relevent bit.
  86. //
  87. Cluster -= _BaseCluster;
  88. _ClusterBuffer[Cluster/8] |= BitValue[Cluster%8];
  89. return(TRUE);
  90. }
  91. BOOL
  92. FlushClusterBuffer(
  93. VOID
  94. )
  95. {
  96. unsigned Written;
  97. unsigned u;
  98. BOOL b;
  99. u = _dos_write(_ClusterFileHandle,_ClusterBuffer,512,&Written);
  100. b = (!u && (Written == 512));
  101. if(!b) {
  102. fprintf(stderr,"\n%s\n",textFileWriteError);
  103. }
  104. return(b);
  105. }
  106. BOOL
  107. InitClusterMap(
  108. OUT FPBYTE _512ByteBuffer,
  109. IN UINT FileHandle,
  110. IN ULONG LastUsedCluster
  111. )
  112. {
  113. unsigned Read;
  114. _ClusterBuffer = _512ByteBuffer;
  115. _ClusterFileHandle = FileHandle;
  116. _BaseCluster = 0L;
  117. _NextClusterToExamine = 0L;
  118. _LastUsedCluster = LastUsedCluster;
  119. if(_dos_read(FileHandle,_ClusterBuffer,512,&Read) || (Read != 512)) {
  120. fprintf(stderr,"\n%s\n",textFileReadFailed);
  121. return(FALSE);
  122. }
  123. return(TRUE);
  124. }
  125. BOOL
  126. GetNextClusterRun(
  127. OUT ULONG *StartCluster,
  128. OUT ULONG *ClusterCount
  129. )
  130. {
  131. UINT cluster;
  132. unsigned Read;
  133. BOOL b;
  134. *ClusterCount=0;
  135. //
  136. // Scan forward for the next 1 bit
  137. //
  138. while(_NextClusterToExamine <= _LastUsedCluster) {
  139. //
  140. // Reload the cluster buffer if necessary.
  141. //
  142. if(_NextClusterToExamine && !(_NextClusterToExamine % (512*8))) {
  143. if(_dos_read(_ClusterFileHandle,_ClusterBuffer,512,&Read) || (Read != 512)) {
  144. fprintf(stderr,"\n%s\n",textFileReadFailed);
  145. return(FALSE);
  146. }
  147. _BaseCluster += 512*8;
  148. }
  149. cluster = (UINT)(_NextClusterToExamine - _BaseCluster);
  150. //
  151. // To simplify things, the run will not span into the next sector
  152. // of the cluster map.
  153. //
  154. b = FALSE;
  155. while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
  156. && (cluster < (512*8)) && (_NextClusterToExamine <= _LastUsedCluster)) {
  157. if(!b) {
  158. *StartCluster = _NextClusterToExamine;
  159. b = TRUE;
  160. }
  161. *ClusterCount += 1;
  162. cluster++;
  163. _NextClusterToExamine++;
  164. }
  165. if(b) {
  166. return(TRUE);
  167. }
  168. _NextClusterToExamine++;
  169. }
  170. //
  171. // No more used clusters.
  172. //
  173. return(TRUE);
  174. }