272 lines
6.4 KiB
C
272 lines
6.4 KiB
C
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#define BUFFER_LENGTH 128
|
||
|
|
||
|
//
|
||
|
// This program is a hack until we have a proper GUI interface for mounting
|
||
|
// double space volumes.
|
||
|
//
|
||
|
// davidgoe [David Goebel] Oct 11, 1993.
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
__cdecl
|
||
|
main (argc, argv)
|
||
|
int argc;
|
||
|
char *argv[];
|
||
|
{
|
||
|
UCHAR DasdName[7] = "\\\\.\\";
|
||
|
UCHAR HostDrive[3];
|
||
|
UCHAR OemBuffer[13] = "DBLSPACE.";
|
||
|
ULONG SequenceNumber = 0;
|
||
|
BOOLEAN SetHostDrive = FALSE;
|
||
|
|
||
|
HANDLE Handle;
|
||
|
|
||
|
UCHAR TmpBuffer[BUFFER_LENGTH];
|
||
|
ULONG Length, i;
|
||
|
|
||
|
//
|
||
|
// Extract the parameters and check their validity.
|
||
|
//
|
||
|
|
||
|
if ((argc < 2) || (argc > 6) || ((argc & 1) != 0)) {
|
||
|
|
||
|
parameter_error:
|
||
|
|
||
|
printf("Syntax - %s Drive: [-h HostDrive:] [-s SequenceNumber]\n", argv[0]);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
argv[1][0] = toupper(argv[1][0]);
|
||
|
|
||
|
DasdName[4] = argv[1][0];
|
||
|
DasdName[5] = argv[1][1];
|
||
|
DasdName[6] = argv[1][2];
|
||
|
|
||
|
if ((DasdName[4] < 'A') || (DasdName[4] > 'Z') ||
|
||
|
(DasdName[5] != ':') ||
|
||
|
(DasdName[6] != 0)) {
|
||
|
|
||
|
goto parameter_error;
|
||
|
}
|
||
|
|
||
|
// temp, reject floppies.
|
||
|
/*
|
||
|
if (DasdName[4] < 'C') {
|
||
|
|
||
|
printf("%s does not currently support floppies.\n", argv[0]);
|
||
|
return;
|
||
|
}
|
||
|
*/
|
||
|
for (i = 2; i < (ULONG)argc; i+=2) {
|
||
|
|
||
|
if (argv[2][0] != '-') {
|
||
|
|
||
|
goto parameter_error;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
PUCHAR LeftOver;
|
||
|
|
||
|
if (argv[i][2] != 0) {
|
||
|
|
||
|
goto parameter_error;
|
||
|
}
|
||
|
|
||
|
switch(argv[i][1]) {
|
||
|
case 'h':
|
||
|
case 'H':
|
||
|
|
||
|
argv[i+1][0] = toupper(argv[i+1][0]);
|
||
|
strncpy(HostDrive, argv[i+1], 3);
|
||
|
|
||
|
if ((HostDrive[0] < 'A') || (HostDrive[0] > 'Z') ||
|
||
|
(HostDrive[1] != ':') ||
|
||
|
(HostDrive[2] != 0)) {
|
||
|
|
||
|
printf("Illegal argument for 'HostDrive:' of %s.\n\n", argv[i+1]);
|
||
|
goto parameter_error;
|
||
|
}
|
||
|
|
||
|
SetHostDrive = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 's':
|
||
|
case 'S':
|
||
|
|
||
|
SequenceNumber = strtol(argv[i+1], &LeftOver, 10);
|
||
|
|
||
|
if (*LeftOver != 0) {
|
||
|
|
||
|
printf("Illegal argument for 'SequenceNumber:' of %s.\n\n", argv[i+1]);
|
||
|
goto parameter_error;
|
||
|
}
|
||
|
|
||
|
if (SequenceNumber > 254) {
|
||
|
|
||
|
printf("Sequnce number must be in the range 0-254.\n");
|
||
|
goto parameter_error;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
printf("Illegal option %s specifed.\n", argv[i]);
|
||
|
goto parameter_error;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// First check for a conflict on the host drive letter.
|
||
|
//
|
||
|
|
||
|
if (SetHostDrive && (QueryDosDevice(HostDrive, &TmpBuffer[0], BUFFER_LENGTH) != 0)) {
|
||
|
|
||
|
printf("Conflict with host drive. Drive %s already exists.\n", HostDrive);
|
||
|
goto parameter_error;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Try to open the drive DASD.
|
||
|
//
|
||
|
|
||
|
Handle = CreateFile( DasdName,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
0 );
|
||
|
|
||
|
if (Handle == INVALID_HANDLE_VALUE) {
|
||
|
|
||
|
printf("Open of %s failed with error %d.\n", argv[1], GetLastError());
|
||
|
printf("You must be administrator to run dsmount.\n");
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now build the unicode filename and attempt the mount.
|
||
|
//
|
||
|
|
||
|
{
|
||
|
OEM_STRING OemCvfName;
|
||
|
UNICODE_STRING UnicodeCvfName;
|
||
|
|
||
|
PFILE_MOUNT_DBLS_BUFFER MountFsctl;
|
||
|
UCHAR MountBuffer[sizeof(FILE_MOUNT_DBLS_BUFFER) + 12*sizeof(WCHAR)];
|
||
|
|
||
|
RXSTATUS Status;
|
||
|
IO_STATUS_BLOCK IoStatus;
|
||
|
|
||
|
MountFsctl = (PFILE_MOUNT_DBLS_BUFFER)MountBuffer;
|
||
|
|
||
|
sprintf(&OemBuffer[9], "%03d", SequenceNumber);
|
||
|
|
||
|
OemCvfName.Length =
|
||
|
OemCvfName.MaximumLength = 12;
|
||
|
OemCvfName.Buffer = OemBuffer;
|
||
|
|
||
|
UnicodeCvfName.MaximumLength = 13*sizeof(WCHAR);
|
||
|
UnicodeCvfName.Buffer = &MountFsctl->CvfName[0];
|
||
|
|
||
|
Status = RtlOemStringToUnicodeString( &UnicodeCvfName, &OemCvfName, FALSE );
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
|
||
|
printf("Unicode conversion failed with error 0x%08lx.\n", Status);
|
||
|
CloseHandle( Handle);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
MountFsctl->CvfNameLength = UnicodeCvfName.Length;
|
||
|
|
||
|
//
|
||
|
// Now issue the DevIoCtrl.
|
||
|
//
|
||
|
|
||
|
Status = NtFsControlFile( Handle,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatus,
|
||
|
FSCTL_MOUNT_DBLS_VOLUME,
|
||
|
MountFsctl,
|
||
|
64,
|
||
|
NULL,
|
||
|
0 );
|
||
|
|
||
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status)) {
|
||
|
|
||
|
if (NT_SUCCESS(Status)) {
|
||
|
|
||
|
Status = IoStatus.Status;
|
||
|
}
|
||
|
|
||
|
printf("Mount failed with error 0x%08lx.\n", Status);
|
||
|
CloseHandle( Handle);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseHandle( Handle);
|
||
|
|
||
|
//
|
||
|
// First get the original base name.
|
||
|
//
|
||
|
|
||
|
Length = QueryDosDevice(argv[1], &TmpBuffer[0], BUFFER_LENGTH);
|
||
|
|
||
|
//
|
||
|
// Now make the host drive link.
|
||
|
//
|
||
|
|
||
|
if (SetHostDrive && !DefineDosDevice( DDD_RAW_TARGET_PATH, &HostDrive[0], &TmpBuffer[0] )) {
|
||
|
|
||
|
printf("Create Host Drive Failed with error: %d\n", GetLastError());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// and finally create the compressed drive link.
|
||
|
//
|
||
|
|
||
|
TmpBuffer[Length-2] = '.';
|
||
|
|
||
|
RtlCopyMemory( &TmpBuffer[Length-1], OemBuffer, 13 );
|
||
|
|
||
|
if (!DefineDosDevice( DDD_RAW_TARGET_PATH, argv[1], &TmpBuffer[0] )) {
|
||
|
|
||
|
printf("Create Compressed Drive Failed with error: %d\n", GetLastError());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Tell the user what we did.
|
||
|
//
|
||
|
|
||
|
printf("The compressed volume file %s\\DBLSPACE.%03d was mounted as %s.\n",
|
||
|
argv[1], SequenceNumber, argv[1]);
|
||
|
|
||
|
if (SetHostDrive) {
|
||
|
|
||
|
printf("The host drive %s contains the original uncompressed volume.\n",
|
||
|
HostDrive);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
printf("No host drive was specified, thus none was created.\n");
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|