223 lines
4.9 KiB
C++
223 lines
4.9 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1991-2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
diskcopy.cxx
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Utility to duplicate a disk
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Norbert P. Kusters (norbertk) 10-May-1991
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#define _NTAPI_ULIB_
|
||
|
|
||
|
#include "ulib.hxx"
|
||
|
#include "arg.hxx"
|
||
|
#include "array.hxx"
|
||
|
#include "smsg.hxx"
|
||
|
#include "rtmsg.h"
|
||
|
#include "wstring.hxx"
|
||
|
#include "system.hxx"
|
||
|
#include "ifssys.hxx"
|
||
|
#include "supera.hxx"
|
||
|
#include "hmem.hxx"
|
||
|
#include "cmem.hxx"
|
||
|
#include "ulibcl.hxx"
|
||
|
#include "mldcopy.hxx"
|
||
|
|
||
|
INT __cdecl
|
||
|
main(
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Main program for DISKCOPY.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
0 - Copy was successful.
|
||
|
1 - A nonfatal read/write error occured.
|
||
|
3 - Fatal hard error.
|
||
|
4 - Initialization error.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
STREAM_MESSAGE msg;
|
||
|
PMESSAGE message;
|
||
|
ARGUMENT_LEXEMIZER arglex;
|
||
|
ARRAY lex_array;
|
||
|
ARRAY arg_array;
|
||
|
STRING_ARGUMENT progname;
|
||
|
STRING_ARGUMENT drive_arg1;
|
||
|
STRING_ARGUMENT drive_arg2;
|
||
|
FLAG_ARGUMENT slashv;
|
||
|
FLAG_ARGUMENT helparg;
|
||
|
FLAG_ARGUMENT genvalue;
|
||
|
DSTRING dossource;
|
||
|
DSTRING dosdest;
|
||
|
DSTRING ntsource;
|
||
|
DSTRING ntdest;
|
||
|
DSTRING currentdrive;
|
||
|
PWSTRING pwstring;
|
||
|
DSTRING colon;
|
||
|
INT result;
|
||
|
|
||
|
if (!msg.Initialize(Get_Standard_Output_Stream(),
|
||
|
Get_Standard_Input_Stream())) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
message = &msg;
|
||
|
|
||
|
if (!lex_array.Initialize() || !arg_array.Initialize()) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (!arglex.Initialize(&lex_array)) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
arglex.SetCaseSensitive(FALSE);
|
||
|
|
||
|
if (!arglex.PrepareToParse()) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (!progname.Initialize("*") ||
|
||
|
!drive_arg1.Initialize("*:") ||
|
||
|
!drive_arg2.Initialize("*:") ||
|
||
|
!slashv.Initialize("/v") ||
|
||
|
!helparg.Initialize("/?") ||
|
||
|
!genvalue.Initialize("/machinetoken")) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (!arg_array.Put(&progname) ||
|
||
|
!arg_array.Put(&drive_arg1) ||
|
||
|
!arg_array.Put(&drive_arg2) ||
|
||
|
!arg_array.Put(&slashv) ||
|
||
|
!arg_array.Put(&helparg) ||
|
||
|
!arg_array.Put(&genvalue)) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (!arglex.DoParsing(&arg_array)) {
|
||
|
message->Set(MSG_INVALID_PARAMETER);
|
||
|
message->Display("%W", pwstring = arglex.QueryInvalidArgument());
|
||
|
DELETE(pwstring);
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (genvalue.QueryFlag()) {
|
||
|
message->Set(MSG_ONE_STRING_NEWLINE);
|
||
|
message->Display("%X", QueryMachineUniqueToken());
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (helparg.QueryFlag()) {
|
||
|
message->Set(MSG_DCOPY_INFO);
|
||
|
message->Display();
|
||
|
message->Set(MSG_DCOPY_USAGE);
|
||
|
message->Display();
|
||
|
message->Set(MSG_DCOPY_SLASH_V);
|
||
|
message->Display();
|
||
|
message->Set(MSG_DCOPY_INFO_2);
|
||
|
message->Display();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!colon.Initialize(":")) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (drive_arg1.IsValueSet()) {
|
||
|
if (!dossource.Initialize(drive_arg1.GetString()) ||
|
||
|
!dossource.Strcat(&colon) ||
|
||
|
!dossource.Strupr()) {
|
||
|
return 4;
|
||
|
}
|
||
|
} else {
|
||
|
if (!SYSTEM::QueryCurrentDosDriveName(&dossource)) {
|
||
|
return 4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (drive_arg2.IsValueSet()) {
|
||
|
if (!dosdest.Initialize(drive_arg2.GetString()) ||
|
||
|
!dosdest.Strcat(&colon) ||
|
||
|
!dosdest.Strupr()) {
|
||
|
return 4;
|
||
|
}
|
||
|
} else {
|
||
|
if (!SYSTEM::QueryCurrentDosDriveName(&dosdest)) {
|
||
|
return 4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SYSTEM::QueryDriveType(&dossource) != RemovableDrive) {
|
||
|
message->Set(MSG_DCOPY_INVALID_DRIVE);
|
||
|
message->Display();
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (SYSTEM::QueryDriveType(&dosdest) != RemovableDrive) {
|
||
|
message->Set(MSG_DCOPY_INVALID_DRIVE);
|
||
|
message->Display();
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (!SYSTEM::QueryCurrentDosDriveName(¤tdrive) ||
|
||
|
currentdrive == dosdest) {
|
||
|
|
||
|
message->Set(MSG_CANT_LOCK_CURRENT_DRIVE);
|
||
|
message->Display();
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(&dossource, &ntsource)) {
|
||
|
message->Set(MSG_DCOPY_INVALID_DRIVE);
|
||
|
message->Display();
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(&dosdest, &ntdest)) {
|
||
|
message->Set(MSG_DCOPY_INVALID_DRIVE);
|
||
|
message->Display();
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
for (;;) {
|
||
|
|
||
|
result = DiskCopyMainLoop(&ntsource, &ntdest, &dossource, &dosdest,
|
||
|
slashv.QueryFlag(), message);
|
||
|
|
||
|
if (result > 1) {
|
||
|
message->Set(MSG_DCOPY_ENDED);
|
||
|
message->Display();
|
||
|
}
|
||
|
|
||
|
message->Set(MSG_DCOPY_ANOTHER);
|
||
|
message->Display();
|
||
|
|
||
|
if (!message->IsYesResponse(FALSE)) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|