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.

388 lines
9.2 KiB

  1. #include <mytypes.h>
  2. #include <diskio.h>
  3. #include <misclib.h>
  4. #include <makepart.h>
  5. #include <partimag.h>
  6. #include <msgfile.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <memory.h>
  10. #include <dos.h>
  11. #include <share.h>
  12. #include <string.h>
  13. #include "makemast.h"
  14. PARTITION_IMAGE PartitionImage;
  15. ULONG TotalSectorsToTransfer;
  16. ULONG TotalSectorsDone;
  17. BOOL
  18. TransferNonClusterData(
  19. IN HDISK DiskHandle,
  20. IN unsigned FileHandle,
  21. IN ULONG TargetStart
  22. );
  23. BOOL
  24. ExpandClusters(
  25. IN HDISK DiskHandle,
  26. IN unsigned FileHandle,
  27. IN ULONG TargetStart
  28. );
  29. BOOL
  30. InitializeClusterMap(
  31. IN unsigned FileHandle
  32. );
  33. BOOL
  34. GetClusterRun(
  35. IN unsigned FileHandle,
  36. OUT ULONG *StartCluster,
  37. OUT ULONG *ClusterCount
  38. );
  39. BOOL
  40. ApplyImage(
  41. IN HDISK DiskHandle,
  42. IN ULONG TargetStart,
  43. IN ULONG MaxSize,
  44. IN BYTE SectorsPerTrack,
  45. IN USHORT Heads
  46. )
  47. {
  48. unsigned FileHandle;
  49. unsigned Read;
  50. printf("\n");
  51. printf(textTransferringFile,CmdLineArgs.ImageFile,0);
  52. printf("\r");
  53. //
  54. // Open the source file, read the image header, and validate it.
  55. //
  56. if(_dos_open(CmdLineArgs.ImageFile,SH_DENYWR,&FileHandle)) {
  57. fprintf(stderr,"\n%s\n",textCantAccessImageFile);
  58. return(FALSE);
  59. }
  60. if(_dos_read(FileHandle,&PartitionImage,sizeof(PARTITION_IMAGE),&Read)
  61. || (Read != sizeof(PARTITION_IMAGE))
  62. || (PartitionImage.Signature != PARTITION_IMAGE_SIGNATURE)
  63. || (PartitionImage.Size != sizeof(PARTITION_IMAGE))) {
  64. _dos_close(FileHandle);
  65. fprintf(stderr,"\n%s\n",textInvalidImageFile);
  66. return(FALSE);
  67. }
  68. //
  69. // Make sure we've got the space.
  70. //
  71. if(PartitionImage.TotalSectorCount > MaxSize) {
  72. _dos_close(FileHandle);
  73. fprintf(stderr,"\n");
  74. fprintf(stderr,textImageFileTooBig,PartitionImage.TotalSectorCount,MaxSize);
  75. fprintf(stderr,"\n");
  76. return(FALSE);
  77. }
  78. TotalSectorsToTransfer = PartitionImage.NonClusterSectors
  79. + (PartitionImage.SectorsPerCluster*PartitionImage.UsedClusterCount);
  80. TotalSectorsDone = 0;
  81. //
  82. // Transfer non-cluster data from the image.
  83. //
  84. if(!TransferNonClusterData(DiskHandle,FileHandle,TargetStart)) {
  85. _dos_close(FileHandle);
  86. return(FALSE);
  87. }
  88. //
  89. // Expand out cluster data from the image.
  90. //
  91. if(!ExpandClusters(DiskHandle,FileHandle,TargetStart)) {
  92. _dos_close(FileHandle);
  93. return(FALSE);
  94. }
  95. //
  96. // Fix up BPB.
  97. //
  98. if(!ReadDisk(DiskHandle,TargetStart,1,IoBuffer)) {
  99. _dos_close(FileHandle);
  100. fprintf(stderr,"\n");
  101. fprintf(stderr,textDiskReadError,TargetStart);
  102. fprintf(stderr,"\n");
  103. return(FALSE);
  104. }
  105. *(FPUSHORT)&((FPBYTE)IoBuffer)[24] = SectorsPerTrack;
  106. *(FPUSHORT)&((FPBYTE)IoBuffer)[26] = Heads;
  107. *(FPULONG)&((FPBYTE)IoBuffer)[28] = TargetStart;
  108. if(!WriteDisk(DiskHandle,TargetStart,1,IoBuffer)) {
  109. _dos_close(FileHandle);
  110. fprintf(stderr,"\n");
  111. fprintf(stderr,textDiskWriteError,TargetStart);
  112. fprintf(stderr,"\n");
  113. return(FALSE);
  114. }
  115. _dos_close(FileHandle);
  116. return(TRUE);
  117. }
  118. BOOL
  119. TransferNonClusterData(
  120. IN HDISK DiskHandle,
  121. IN unsigned FileHandle,
  122. IN ULONG TargetStart
  123. )
  124. {
  125. ULONG NonClusterSectorsDone;
  126. ULONG Count;
  127. unsigned Read;
  128. //
  129. // Seek past partition image header
  130. //
  131. if(DosSeek(FileHandle,512,DOSSEEK_START) != 512) {
  132. fprintf(stderr,"\n%s\n",textCantAccessImageFile);
  133. return(FALSE);
  134. }
  135. //
  136. // Now transfer the non-cluster data
  137. //
  138. NonClusterSectorsDone = 0;
  139. while(NonClusterSectorsDone < PartitionImage.NonClusterSectors) {
  140. Count = PartitionImage.NonClusterSectors - NonClusterSectorsDone;
  141. if(Count > 63) {
  142. Count = 63;
  143. }
  144. if(_dos_read(FileHandle,IoBuffer,(unsigned)Count*512,&Read) || (Read != ((unsigned)Count*512))) {
  145. fprintf(stderr,"\n%s\n",textCantAccessImageFile);
  146. return(FALSE);
  147. }
  148. if(!WriteDisk(DiskHandle,TargetStart,(BYTE)Count,IoBuffer)) {
  149. fprintf(stderr,"\n");
  150. fprintf(stderr,textDiskWriteError,TargetStart);
  151. fprintf(stderr,"\n");
  152. return(FALSE);
  153. }
  154. TargetStart += Count;
  155. NonClusterSectorsDone += Count;
  156. TotalSectorsDone += Count;
  157. printf(textTransferringFile,CmdLineArgs.ImageFile,100*TotalSectorsDone/TotalSectorsToTransfer);
  158. printf("\r");
  159. }
  160. return(TRUE);
  161. }
  162. BOOL
  163. ExpandClusters(
  164. IN HDISK DiskHandle,
  165. IN unsigned FileHandle,
  166. IN ULONG TargetStart
  167. )
  168. {
  169. ULONG Start,Count;
  170. ULONG TargetSector;
  171. BYTE u;
  172. unsigned Read;
  173. if(!InitializeClusterMap(FileHandle)) {
  174. return(FALSE);
  175. }
  176. //
  177. // Seek to start of cluster data in input file.
  178. //
  179. Start = (1 + PartitionImage.NonClusterSectors) * 512;
  180. if(DosSeek(FileHandle,Start,DOSSEEK_START) != Start) {
  181. fprintf(stderr,"\n%s\n",textCantAccessImageFile);
  182. return(FALSE);
  183. }
  184. //
  185. // Get a run of clusters. If there are no more clusters left, we're done.
  186. //
  187. nextrun:
  188. if(!GetClusterRun(FileHandle,&Start,&Count)) {
  189. return(FALSE);
  190. }
  191. if(!Count) {
  192. return(TRUE);
  193. }
  194. Count *= PartitionImage.SectorsPerCluster;
  195. //
  196. // Calculate the offset of the data in the source file and
  197. // the starting sector number of the target.
  198. //
  199. TargetSector = TargetStart + PartitionImage.NonClusterSectors + (Start*PartitionImage.SectorsPerCluster);
  200. while(Count) {
  201. u = (BYTE)((Count > 63L) ? 63L : Count);
  202. if(_dos_read(FileHandle,IoBuffer,u*512U,&Read) || (Read != (u*512U))) {
  203. fprintf(stderr,"\n%s\n",textCantAccessImageFile);
  204. return(FALSE);
  205. }
  206. if(!WriteDisk(DiskHandle,TargetSector,u,IoBuffer)) {
  207. fprintf(stderr,"\n");
  208. fprintf(stderr,textDiskWriteError,TargetSector);
  209. fprintf(stderr,"\n");
  210. return(FALSE);
  211. }
  212. TargetSector += u;
  213. Count -= u;
  214. TotalSectorsDone += u;
  215. printf(textTransferringFile,CmdLineArgs.ImageFile,100*TotalSectorsDone/TotalSectorsToTransfer);
  216. printf("\r");
  217. }
  218. //
  219. // Process additional clusters.
  220. //
  221. goto nextrun;
  222. }
  223. ////////////////////////////////////////////////////
  224. ULONG _ClusterSectorFileOffset;
  225. ULONG _NextClusterToExamine;
  226. ULONG _ClusterBufferBase;
  227. BYTE _ClusterBuffer[512];
  228. extern BYTE BitValue[8];
  229. BOOL
  230. InitializeClusterMap(
  231. IN unsigned FileHandle
  232. )
  233. {
  234. unsigned read;
  235. //
  236. // Figure out where in the file the cluster bitmap starts.
  237. //
  238. _ClusterSectorFileOffset = PartitionImage.NonClusterSectors
  239. + (PartitionImage.UsedClusterCount * PartitionImage.SectorsPerCluster)
  240. + 1;
  241. _ClusterSectorFileOffset *= 512;
  242. //
  243. // Read the first sector of the cluster bitmap. Read into IoBuffer to avoid
  244. // DMA boundary issues.
  245. //
  246. if((DosSeek(FileHandle,_ClusterSectorFileOffset,DOSSEEK_START) != _ClusterSectorFileOffset)
  247. || _dos_read(FileHandle,IoBuffer,512,&read) || (read != 512)) {
  248. fprintf(stderr,"\n%s\n",textCantAccessImageFile);
  249. return(FALSE);
  250. }
  251. memmove(_ClusterBuffer,IoBuffer,512);
  252. _NextClusterToExamine = 0;
  253. _ClusterBufferBase = 0;
  254. return(TRUE);
  255. }
  256. BOOL
  257. GetClusterRun(
  258. IN unsigned FileHandle,
  259. OUT ULONG *StartCluster,
  260. OUT ULONG *ClusterCount
  261. )
  262. {
  263. ULONG Offset;
  264. UINT cluster;
  265. BOOL b;
  266. *ClusterCount = 0;
  267. //
  268. // Locate the next 1 bit in the map.
  269. //
  270. while(_NextClusterToExamine <= PartitionImage.LastUsedCluster) {
  271. //
  272. // Reload the cluster buffer if necessary. Preserve file pointer!
  273. //
  274. if(_NextClusterToExamine && !(_NextClusterToExamine % (8*512))) {
  275. _ClusterSectorFileOffset += 512;
  276. if(((Offset = DosSeek(FileHandle,0,DOSSEEK_CURRENT)) == (ULONG)(-1))
  277. || (DosSeek(FileHandle,_ClusterSectorFileOffset,DOSSEEK_START) != _ClusterSectorFileOffset)
  278. || _dos_read(FileHandle,IoBuffer,512,&cluster)
  279. || (cluster != 512)
  280. || (DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)) {
  281. fprintf(stderr,"\n%s\n",textCantAccessImageFile);
  282. return(FALSE);
  283. }
  284. memmove(_ClusterBuffer,IoBuffer,512);
  285. _ClusterBufferBase += 8*512;
  286. }
  287. cluster = (UINT)(_NextClusterToExamine - _ClusterBufferBase);
  288. //
  289. // See if this bit is one, which starts a run of used clusters.
  290. // To simplify things, we won't return a run that spans sectors
  291. // in the cluster bitmap.
  292. //
  293. b = FALSE;
  294. while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
  295. && (cluster < (8*512))
  296. && (_NextClusterToExamine <= PartitionImage.LastUsedCluster)) {
  297. if(!b) {
  298. *StartCluster = _NextClusterToExamine;
  299. b = TRUE;
  300. }
  301. *ClusterCount += 1;
  302. cluster++;
  303. _NextClusterToExamine++;
  304. }
  305. if(b) {
  306. return(TRUE);
  307. }
  308. _NextClusterToExamine++;
  309. }
  310. return(TRUE);
  311. }