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.

222 lines
4.9 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. diskcopy.cxx
  5. Abstract:
  6. Utility to duplicate a disk
  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. #include "mldcopy.hxx"
  25. INT __cdecl
  26. main(
  27. )
  28. /*++
  29. Routine Description:
  30. Main program for DISKCOPY.
  31. Arguments:
  32. None.
  33. Return Value:
  34. 0 - Copy was successful.
  35. 1 - A nonfatal read/write error occured.
  36. 3 - Fatal hard error.
  37. 4 - Initialization error.
  38. --*/
  39. {
  40. STREAM_MESSAGE msg;
  41. PMESSAGE message;
  42. ARGUMENT_LEXEMIZER arglex;
  43. ARRAY lex_array;
  44. ARRAY arg_array;
  45. STRING_ARGUMENT progname;
  46. STRING_ARGUMENT drive_arg1;
  47. STRING_ARGUMENT drive_arg2;
  48. FLAG_ARGUMENT slashv;
  49. FLAG_ARGUMENT helparg;
  50. FLAG_ARGUMENT genvalue;
  51. DSTRING dossource;
  52. DSTRING dosdest;
  53. DSTRING ntsource;
  54. DSTRING ntdest;
  55. DSTRING currentdrive;
  56. PWSTRING pwstring;
  57. DSTRING colon;
  58. INT result;
  59. if (!msg.Initialize(Get_Standard_Output_Stream(),
  60. Get_Standard_Input_Stream())) {
  61. return 4;
  62. }
  63. message = &msg;
  64. if (!lex_array.Initialize() || !arg_array.Initialize()) {
  65. return 4;
  66. }
  67. if (!arglex.Initialize(&lex_array)) {
  68. return 4;
  69. }
  70. arglex.SetCaseSensitive(FALSE);
  71. if (!arglex.PrepareToParse()) {
  72. return 4;
  73. }
  74. if (!progname.Initialize("*") ||
  75. !drive_arg1.Initialize("*:") ||
  76. !drive_arg2.Initialize("*:") ||
  77. !slashv.Initialize("/v") ||
  78. !helparg.Initialize("/?") ||
  79. !genvalue.Initialize("/machinetoken")) {
  80. return 4;
  81. }
  82. if (!arg_array.Put(&progname) ||
  83. !arg_array.Put(&drive_arg1) ||
  84. !arg_array.Put(&drive_arg2) ||
  85. !arg_array.Put(&slashv) ||
  86. !arg_array.Put(&helparg) ||
  87. !arg_array.Put(&genvalue)) {
  88. return 4;
  89. }
  90. if (!arglex.DoParsing(&arg_array)) {
  91. message->Set(MSG_INVALID_PARAMETER);
  92. message->Display("%W", pwstring = arglex.QueryInvalidArgument());
  93. DELETE(pwstring);
  94. return 4;
  95. }
  96. if (genvalue.QueryFlag()) {
  97. message->Set(MSG_ONE_STRING_NEWLINE);
  98. message->Display("%X", QueryMachineUniqueToken());
  99. return 0;
  100. }
  101. if (helparg.QueryFlag()) {
  102. message->Set(MSG_DCOPY_INFO);
  103. message->Display();
  104. message->Set(MSG_DCOPY_USAGE);
  105. message->Display();
  106. message->Set(MSG_DCOPY_SLASH_V);
  107. message->Display();
  108. message->Set(MSG_DCOPY_INFO_2);
  109. message->Display();
  110. return 0;
  111. }
  112. if (!colon.Initialize(":")) {
  113. return 4;
  114. }
  115. if (drive_arg1.IsValueSet()) {
  116. if (!dossource.Initialize(drive_arg1.GetString()) ||
  117. !dossource.Strcat(&colon) ||
  118. !dossource.Strupr()) {
  119. return 4;
  120. }
  121. } else {
  122. if (!SYSTEM::QueryCurrentDosDriveName(&dossource)) {
  123. return 4;
  124. }
  125. }
  126. if (drive_arg2.IsValueSet()) {
  127. if (!dosdest.Initialize(drive_arg2.GetString()) ||
  128. !dosdest.Strcat(&colon) ||
  129. !dosdest.Strupr()) {
  130. return 4;
  131. }
  132. } else {
  133. if (!SYSTEM::QueryCurrentDosDriveName(&dosdest)) {
  134. return 4;
  135. }
  136. }
  137. if (SYSTEM::QueryDriveType(&dossource) != RemovableDrive) {
  138. message->Set(MSG_DCOPY_INVALID_DRIVE);
  139. message->Display();
  140. return 4;
  141. }
  142. if (SYSTEM::QueryDriveType(&dosdest) != RemovableDrive) {
  143. message->Set(MSG_DCOPY_INVALID_DRIVE);
  144. message->Display();
  145. return 4;
  146. }
  147. if (!SYSTEM::QueryCurrentDosDriveName(&currentdrive) ||
  148. currentdrive == dosdest) {
  149. message->Set(MSG_CANT_LOCK_CURRENT_DRIVE);
  150. message->Display();
  151. return 4;
  152. }
  153. if (!IFS_SYSTEM::DosDriveNameToNtDriveName(&dossource, &ntsource)) {
  154. message->Set(MSG_DCOPY_INVALID_DRIVE);
  155. message->Display();
  156. return 4;
  157. }
  158. if (!IFS_SYSTEM::DosDriveNameToNtDriveName(&dosdest, &ntdest)) {
  159. message->Set(MSG_DCOPY_INVALID_DRIVE);
  160. message->Display();
  161. return 4;
  162. }
  163. for (;;) {
  164. result = DiskCopyMainLoop(&ntsource, &ntdest, &dossource, &dosdest,
  165. slashv.QueryFlag(), message);
  166. if (result > 1) {
  167. message->Set(MSG_DCOPY_ENDED);
  168. message->Display();
  169. }
  170. message->Set(MSG_DCOPY_ANOTHER);
  171. message->Display();
  172. if (!message->IsYesResponse(FALSE)) {
  173. break;
  174. }
  175. }
  176. return result;
  177. }