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.

492 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. diskcomp.cxx
  5. Abstract:
  6. Utility to compare two disks
  7. Author:
  8. Norbert P. Kusters (norbertk) 10-May-1991
  9. Revision History:
  10. --*/
  11. #define _NTAPI_ULIB_
  12. #include "ulib.hxx"
  13. #include "arg.hxx"
  14. #include "array.hxx"
  15. #include "smsg.hxx"
  16. #include "rtmsg.h"
  17. #include "wstring.hxx"
  18. #include "system.hxx"
  19. #include "ifssys.hxx"
  20. #include "supera.hxx"
  21. #include "hmem.hxx"
  22. #include "cmem.hxx"
  23. #include "ulibcl.hxx"
  24. INT
  25. DiskComp(
  26. IN PCWSTRING SrcNtDriveName,
  27. IN PCWSTRING DstNtDriveName,
  28. IN PCWSTRING SrcDosDriveName,
  29. IN PCWSTRING DstDosDriveName,
  30. IN OUT PMESSAGE Message
  31. )
  32. /*++
  33. Routine Description:
  34. This routine copies on floppy diskette to another floppy diskette.
  35. Arguments:
  36. SrcNtDriveName - Supplies the NT style drive name for the source.
  37. DstNtDriveName - Supplies the NT style drive name for the destination.
  38. SrcDosDriveName - Supplies the DOS style drive name for the source.
  39. DstDosDriveName - Supplies the DOS style drive name for the destination.
  40. Message - Supplies an outlet for messages.
  41. Return Value:
  42. 0 - The disks are the same.
  43. 1 - The disks are different.
  44. 3 - A hard error occurred.
  45. 4 - An initialization error occurred.
  46. --*/
  47. {
  48. LOG_IO_DP_DRIVE src_drive;
  49. LOG_IO_DP_DRIVE dst_drive;
  50. HMEM src_hmem;
  51. HMEM dst_hmem;
  52. CONT_MEM src_cmem;
  53. PVOID mem_ptr;
  54. SECRUN src_secrun;
  55. SECRUN dst_secrun;
  56. SECTORCOUNT sec_per_track;
  57. ULONG total_tracks;
  58. ULONG grab; // number of tracks to grab at once.
  59. ULONG sector_size;
  60. BOOLEAN one_drive;
  61. ULONG src_top; // src track pointer -- next read
  62. ULONG dst_top; // dst track pointer -- next write
  63. PCHAR dst_pchar;
  64. PCHAR src_pchar;
  65. ULONG i;
  66. BOOLEAN the_same;
  67. ULONG heads;
  68. DSTRING fsname;
  69. #if defined(FE_SB) && defined(_X86_)
  70. MEDIA_TYPE AltMediaType;
  71. #endif
  72. one_drive = (*SrcDosDriveName == *DstDosDriveName);
  73. Message->Set(MSG_DCOMP_INSERT_FIRST);
  74. Message->Display("%W", SrcDosDriveName);
  75. if (!one_drive) {
  76. Message->Set(MSG_DCOMP_INSERT_SECOND);
  77. Message->Display("%W", DstDosDriveName);
  78. }
  79. Message->Set(MSG_PRESS_ENTER_WHEN_READY);
  80. Message->Display();
  81. Message->WaitForUserSignal();
  82. if (!src_drive.Initialize(SrcNtDriveName)) {
  83. // Verify that we can access the source drive:
  84. if (src_drive.QueryLastNtStatus() == STATUS_ACCESS_DENIED) {
  85. Message->Set(MSG_DASD_ACCESS_DENIED);
  86. Message->Display();
  87. return 4;
  88. }
  89. Message->Set(MSG_DCOMP_FIRST_DISK_BAD);
  90. Message->Display();
  91. return 3;
  92. }
  93. if (!src_drive.IsFloppy()) {
  94. Message->Set(MSG_DCOPY_INVALID_DRIVE);
  95. Message->Display();
  96. return 4;
  97. }
  98. if (src_drive.QueryMediaType() == Unknown) {
  99. Message->Set(MSG_DCOMP_FIRST_DISK_BAD);
  100. Message->Display();
  101. return 3;
  102. }
  103. Message->Set(MSG_DCOMP_COMPARING);
  104. Message->Display("%d%d%d", src_drive.QueryCylinders().GetLowPart(),
  105. src_drive.QuerySectorsPerTrack(),
  106. src_drive.QueryHeads());
  107. sec_per_track = src_drive.QuerySectorsPerTrack();
  108. sector_size = src_drive.QuerySectorSize();
  109. total_tracks = src_drive.QueryTracks().GetLowPart();
  110. heads = src_drive.QueryHeads();
  111. DebugAssert(src_drive.QuerySectors().GetHighPart() == 0);
  112. src_top = 0;
  113. if (!dst_hmem.Initialize()) {
  114. return 4;
  115. }
  116. the_same = TRUE;
  117. for (dst_top = 0; dst_top < total_tracks; dst_top++) {
  118. if (src_top == dst_top) {
  119. if (src_top && one_drive) {
  120. Message->Set(MSG_DCOMP_INSERT_FIRST);
  121. Message->Display("%W", SrcDosDriveName);
  122. Message->Set(MSG_PRESS_ENTER_WHEN_READY);
  123. Message->Display();
  124. Message->WaitForUserSignal();
  125. }
  126. // Allocate memory for read.
  127. for (grab = total_tracks - src_top;
  128. !src_hmem.Initialize() ||
  129. !(mem_ptr = src_hmem.Acquire(grab*sector_size*sec_per_track,
  130. src_drive.QueryAlignmentMask()));
  131. grab /= 2) {
  132. if (grab < 2) {
  133. Message->Set(MSG_CHK_NO_MEMORY);
  134. Message->Display();
  135. return 4;
  136. }
  137. }
  138. if (!src_cmem.Initialize(mem_ptr, grab*sector_size*sec_per_track)) {
  139. return 4;
  140. }
  141. // Read the source, track by track.
  142. for (i = 0; i < grab; i++) {
  143. if (!src_secrun.Initialize(&src_cmem, &src_drive,
  144. src_top*sec_per_track,
  145. sec_per_track)) {
  146. return 4;
  147. }
  148. if (!src_secrun.Read()) {
  149. if (src_drive.QueryLastNtStatus() == STATUS_NO_MEDIA_IN_DEVICE ||
  150. src_drive.QueryLastNtStatus() == STATUS_UNRECOGNIZED_MEDIA) {
  151. return 3;
  152. }
  153. Message->Set(MSG_DCOPY_READ_ERROR);
  154. Message->Display("%W%d%d", SrcDosDriveName,
  155. src_top%heads, src_top/heads);
  156. the_same = FALSE;
  157. }
  158. src_top++;
  159. }
  160. if (!src_cmem.Initialize(mem_ptr, grab*sector_size*sec_per_track)) {
  161. return 4;
  162. }
  163. if (one_drive) {
  164. Message->Set(MSG_DCOMP_INSERT_SECOND);
  165. Message->Display("%W", DstDosDriveName);
  166. Message->Set(MSG_PRESS_ENTER_WHEN_READY);
  167. Message->Display();
  168. Message->WaitForUserSignal();
  169. }
  170. if (!dst_top) {
  171. if (!dst_drive.Initialize(DstNtDriveName)) {
  172. // verify that we can access the destination drive:
  173. if (dst_drive.QueryLastNtStatus() == STATUS_ACCESS_DENIED) {
  174. Message->Set(MSG_DASD_ACCESS_DENIED);
  175. Message->Display( "" );
  176. return 4;
  177. }
  178. Message->Set(MSG_DCOMP_SECOND_DISK_BAD);
  179. Message->Display();
  180. return 3;
  181. }
  182. if (dst_drive.QueryMediaType() != src_drive.QueryMediaType()) {
  183. #if defined(FE_SB) && defined(_X86_)
  184. switch (src_drive.QueryMediaType()) {
  185. case F5_1Pt23_1024:
  186. AltMediaType = F3_1Pt23_1024;
  187. break;
  188. case F3_1Pt23_1024:
  189. AltMediaType = F5_1Pt23_1024;
  190. break;
  191. case F5_1Pt2_512:
  192. AltMediaType = F3_1Pt2_512;
  193. break;
  194. case F3_1Pt2_512:
  195. AltMediaType = F5_1Pt2_512;
  196. break;
  197. case F3_720_512:
  198. AltMediaType = F5_720_512;
  199. break;
  200. case F5_720_512:
  201. AltMediaType = F3_720_512;
  202. break;
  203. case F5_640_512:
  204. AltMediaType = F3_640_512;
  205. break;
  206. case F3_640_512:
  207. AltMediaType = F5_640_512;
  208. break;
  209. default:
  210. AltMediaType = src_drive.QueryMediaType();
  211. break;
  212. }
  213. // Second try with AltMediaType
  214. if (dst_drive.QueryMediaType() != AltMediaType) {
  215. #endif
  216. Message->Set(MSG_DCOMP_NOT_COMPATIBLE);
  217. Message->Display();
  218. return 4;
  219. #if defined(FE_SB) && defined(_X86_)
  220. }
  221. #endif
  222. }
  223. }
  224. }
  225. if (!dst_secrun.Initialize(&dst_hmem, &dst_drive,
  226. dst_top*sec_per_track, sec_per_track)) {
  227. return 4;
  228. }
  229. if (dst_secrun.Read()) {
  230. src_pchar = (PCHAR) src_cmem.Acquire(sector_size*sec_per_track);
  231. dst_pchar = (PCHAR) dst_secrun.GetBuf();
  232. if (!dst_top) {
  233. if ((src_pchar[0x26] == 0x28 || src_pchar[0x26] == 0x29) &&
  234. (dst_pchar[0x26] == 0x28 || dst_pchar[0x26] == 0x29)) {
  235. memcpy(src_pchar + 0x27, dst_pchar + 0x27, sizeof(ULONG));
  236. }
  237. }
  238. if (memcmp(src_pchar, dst_pchar, (UINT) (sector_size*sec_per_track))) {
  239. Message->Set(MSG_DCOMP_COMPARE_ERROR);
  240. Message->Display("%d%d", dst_top%heads, dst_top/heads);
  241. the_same = FALSE;
  242. }
  243. } else {
  244. if (dst_drive.QueryLastNtStatus() == STATUS_NO_MEDIA_IN_DEVICE ||
  245. dst_drive.QueryLastNtStatus() == STATUS_UNRECOGNIZED_MEDIA) {
  246. return 3;
  247. }
  248. Message->Set(MSG_DCOPY_READ_ERROR);
  249. Message->Display("%W%d%d", DstDosDriveName,
  250. dst_top%heads, dst_top/heads);
  251. the_same = FALSE;
  252. }
  253. }
  254. if (the_same) {
  255. Message->Set(MSG_DCOMP_OK);
  256. Message->Display();
  257. }
  258. return the_same ? 0 : 1;
  259. }
  260. INT __cdecl
  261. main(
  262. )
  263. /*++
  264. Routine Description:
  265. Main program for DISKCOMP.
  266. Arguments:
  267. None.
  268. Return Value:
  269. 0 - The disks are the same.
  270. 1 - The disks are different.
  271. 3 - Fatal hard error.
  272. 4 - Initialization error.
  273. --*/
  274. {
  275. STREAM_MESSAGE msg;
  276. PMESSAGE message;
  277. ARGUMENT_LEXEMIZER arglex;
  278. ARRAY lex_array;
  279. ARRAY arg_array;
  280. STRING_ARGUMENT progname;
  281. STRING_ARGUMENT drive_arg1;
  282. STRING_ARGUMENT drive_arg2;
  283. FLAG_ARGUMENT slashv;
  284. FLAG_ARGUMENT helparg;
  285. DSTRING dossource;
  286. DSTRING dosdest;
  287. DSTRING ntsource;
  288. DSTRING ntdest;
  289. PWSTRING pwstring;
  290. DSTRING colon;
  291. INT result;
  292. if (!msg.Initialize(Get_Standard_Output_Stream(),
  293. Get_Standard_Input_Stream())) {
  294. return 4;
  295. }
  296. message = &msg;
  297. if (!lex_array.Initialize() || !arg_array.Initialize()) {
  298. return 4;
  299. }
  300. if (!arglex.Initialize(&lex_array)) {
  301. return 4;
  302. }
  303. arglex.SetCaseSensitive(FALSE);
  304. if (!arglex.PrepareToParse()) {
  305. return 4;
  306. }
  307. if (!progname.Initialize("*") ||
  308. !drive_arg1.Initialize("*:") ||
  309. !drive_arg2.Initialize("*:") ||
  310. !helparg.Initialize("/?")) {
  311. return 4;
  312. }
  313. if (!arg_array.Put(&progname) ||
  314. !arg_array.Put(&drive_arg1) ||
  315. !arg_array.Put(&drive_arg2) ||
  316. !arg_array.Put(&helparg)) {
  317. return 4;
  318. }
  319. if (!arglex.DoParsing(&arg_array)) {
  320. message->Set(MSG_INVALID_PARAMETER);
  321. message->Display("%W", pwstring = arglex.QueryInvalidArgument());
  322. DELETE(pwstring);
  323. return 4;
  324. }
  325. if (helparg.QueryFlag()) {
  326. message->Set(MSG_DCOMP_INFO);
  327. message->Display();
  328. message->Set(MSG_DCOMP_USAGE);
  329. message->Display();
  330. return 0;
  331. }
  332. if (!colon.Initialize(":")) {
  333. return 4;
  334. }
  335. if (drive_arg1.IsValueSet()) {
  336. if (!dossource.Initialize(drive_arg1.GetString()) ||
  337. !dossource.Strcat(&colon) ||
  338. !dossource.Strupr()) {
  339. return 4;
  340. }
  341. } else {
  342. if (!SYSTEM::QueryCurrentDosDriveName(&dossource)) {
  343. return 4;
  344. }
  345. }
  346. if (drive_arg2.IsValueSet()) {
  347. if (!dosdest.Initialize(drive_arg2.GetString()) ||
  348. !dosdest.Strcat(&colon) ||
  349. !dosdest.Strupr()) {
  350. return 4;
  351. }
  352. } else {
  353. if (!SYSTEM::QueryCurrentDosDriveName(&dosdest)) {
  354. return 4;
  355. }
  356. }
  357. if (SYSTEM::QueryDriveType(&dossource) != RemovableDrive) {
  358. message->Set(MSG_DCOPY_INVALID_DRIVE);
  359. message->Display();
  360. return 4;
  361. }
  362. if (SYSTEM::QueryDriveType(&dosdest) != RemovableDrive) {
  363. message->Set(MSG_DCOPY_INVALID_DRIVE);
  364. message->Display();
  365. return 4;
  366. }
  367. if (!IFS_SYSTEM::DosDriveNameToNtDriveName(&dossource, &ntsource)) {
  368. message->Set(MSG_DCOPY_INVALID_DRIVE);
  369. message->Display();
  370. return 4;
  371. }
  372. if (!IFS_SYSTEM::DosDriveNameToNtDriveName(&dosdest, &ntdest)) {
  373. message->Set(MSG_DCOPY_INVALID_DRIVE);
  374. message->Display();
  375. return 4;
  376. }
  377. for (;;) {
  378. result = DiskComp(&ntsource, &ntdest, &dossource, &dosdest, message);
  379. if (result > 1) {
  380. message->Set(MSG_DCOMP_ENDED);
  381. message->Display();
  382. }
  383. message->Set(MSG_DCOMP_ANOTHER);
  384. message->Display();
  385. if (!message->IsYesResponse(FALSE)) {
  386. break;
  387. }
  388. }
  389. return result;
  390. }