769 lines
19 KiB
C
769 lines
19 KiB
C
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <ntdddisk.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <conio.h>
|
|||
|
#include <ctype.h>
|
|||
|
#include <string.h>
|
|||
|
#include <io.h>
|
|||
|
|
|||
|
#define CB_LINE 16
|
|||
|
#define SECSIZE 512
|
|||
|
#define CB_INPUT 2
|
|||
|
#define CB_INPUTLINE 8
|
|||
|
#define CB_CMDLINE 256
|
|||
|
|
|||
|
typedef UCHAR BYTE,*PBYTE;
|
|||
|
|
|||
|
BYTE Sector[SECSIZE];
|
|||
|
BYTE Input[CB_INPUT];
|
|||
|
char Command[CB_CMDLINE];
|
|||
|
UCHAR HexLine[80];
|
|||
|
UCHAR CharLine[40];
|
|||
|
BOOLEAN Batch = FALSE;
|
|||
|
|
|||
|
#define LoadWORD(x) ((ULONG)( (USHORT)(* (PBYTE)(x) ) \
|
|||
|
| ((USHORT)(*((PBYTE)(x) + 1)) << 8) ))
|
|||
|
|
|||
|
#define LoadDWORD(x) ((LoadWORD((PBYTE)(x)+2) << 16) | LoadWORD(x))
|
|||
|
|
|||
|
typedef struct {
|
|||
|
BYTE BootIndicator;
|
|||
|
BYTE StartHead;
|
|||
|
BYTE StartSector;
|
|||
|
BYTE StartCylinder;
|
|||
|
BYTE SysID;
|
|||
|
BYTE EndHead;
|
|||
|
BYTE EndSector;
|
|||
|
BYTE EndCylinder;
|
|||
|
BYTE Relative0;
|
|||
|
BYTE Relative1;
|
|||
|
BYTE Relative2;
|
|||
|
BYTE Relative3;
|
|||
|
BYTE SectorCount0;
|
|||
|
BYTE SectorCount1;
|
|||
|
BYTE SectorCount2;
|
|||
|
BYTE SectorCount3;
|
|||
|
} PTE,*PPTE;
|
|||
|
|
|||
|
#define PARTITIONTABLE_OFFSET 0x1be
|
|||
|
#define SIGNATURE_OFFSET 0x1fe
|
|||
|
|
|||
|
typedef struct {
|
|||
|
BYTE BootCode[PARTITIONTABLE_OFFSET];
|
|||
|
PTE PartitionTable[4];
|
|||
|
BYTE Signature[2];
|
|||
|
} BOOTSECTOR,*PBOOTSECTOR;
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
IsSepChar(
|
|||
|
int *Pc
|
|||
|
)
|
|||
|
{
|
|||
|
switch (*Pc) {
|
|||
|
case ',':
|
|||
|
*Pc = ' ';
|
|||
|
return TRUE;
|
|||
|
|
|||
|
case '\n':
|
|||
|
*Pc = '\r';
|
|||
|
return TRUE;
|
|||
|
|
|||
|
case ' ':
|
|||
|
if( Batch )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
// else fall thru to '\r' case
|
|||
|
|
|||
|
case '\r':
|
|||
|
return TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// if didn't return above, must not be separator
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
int MyGetChr( void )
|
|||
|
{
|
|||
|
if (Batch) {
|
|||
|
int c;
|
|||
|
|
|||
|
while ((c = getchar()) == ' ')
|
|||
|
;
|
|||
|
return c;
|
|||
|
} else {
|
|||
|
return _getch();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void PromptUsr( void )
|
|||
|
{
|
|||
|
if (!Batch)
|
|||
|
printf("\n$ ");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
OpenFile(
|
|||
|
PSZ DriveNumber,
|
|||
|
PHANDLE Handle
|
|||
|
)
|
|||
|
{
|
|||
|
OBJECT_ATTRIBUTES oa;
|
|||
|
STRING ntDriveName;
|
|||
|
UNICODE_STRING uniDriveName;
|
|||
|
IO_STATUS_BLOCK ioStatusBlock;
|
|||
|
int charsInName;
|
|||
|
char driveName[50];
|
|||
|
NTSTATUS nts;
|
|||
|
|
|||
|
|
|||
|
sprintf(driveName, "\\Device\\Harddisk%s\\Partition0", DriveNumber);
|
|||
|
|
|||
|
charsInName = strlen(driveName);
|
|||
|
|
|||
|
ntDriveName.Length = (USHORT)charsInName;
|
|||
|
ntDriveName.MaximumLength = (USHORT)charsInName;
|
|||
|
ntDriveName.Buffer = driveName;
|
|||
|
|
|||
|
printf( "NT drive name = %s\n", ntDriveName.Buffer );
|
|||
|
|
|||
|
RtlAnsiStringToUnicodeString(&uniDriveName, &ntDriveName, TRUE);
|
|||
|
|
|||
|
memset(&oa, 0, sizeof(OBJECT_ATTRIBUTES));
|
|||
|
oa.Length = sizeof(OBJECT_ATTRIBUTES);
|
|||
|
oa.ObjectName = &uniDriveName;
|
|||
|
oa.Attributes = OBJ_CASE_INSENSITIVE;
|
|||
|
|
|||
|
if (!NT_SUCCESS(nts = NtOpenFile(Handle,
|
|||
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|||
|
&oa,
|
|||
|
&ioStatusBlock,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
FILE_SYNCHRONOUS_IO_ALERT))) {
|
|||
|
|
|||
|
printf("NtOpenFile status %x\n", nts);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RtlFreeUnicodeString(&uniDriveName);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CloseFile(
|
|||
|
HANDLE Handle
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS nts;
|
|||
|
|
|||
|
if (!NT_SUCCESS(nts = NtClose(Handle))) {
|
|||
|
|
|||
|
printf("NtClose status %x\n");
|
|||
|
return FALSE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
LockVolume(
|
|||
|
HANDLE Handle
|
|||
|
)
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK ioStatusBlock;
|
|||
|
NTSTATUS nts;
|
|||
|
|
|||
|
if (!NT_SUCCESS(nts = NtFsControlFile(Handle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&ioStatusBlock,
|
|||
|
FSCTL_LOCK_VOLUME,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0))) {
|
|||
|
|
|||
|
printf("Unable to lock volume (%x).\n",
|
|||
|
nts);
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
UnlockVolume(
|
|||
|
HANDLE Handle
|
|||
|
)
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK ioStatusBlock;
|
|||
|
NTSTATUS nts;
|
|||
|
|
|||
|
if (!NT_SUCCESS(nts = NtFsControlFile(Handle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&ioStatusBlock,
|
|||
|
FSCTL_UNLOCK_VOLUME,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0))) {
|
|||
|
|
|||
|
printf("Unable to unlock volume (%x).\n",
|
|||
|
nts);
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ReadSector(
|
|||
|
HANDLE Handle,
|
|||
|
ULONG Lsn,
|
|||
|
PVOID Buffer,
|
|||
|
PULONG BytesRead
|
|||
|
)
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK ioStatusBlock;
|
|||
|
LARGE_INTEGER byteOffset;
|
|||
|
NTSTATUS nts;
|
|||
|
|
|||
|
byteOffset.HighPart = 0;
|
|||
|
byteOffset.LowPart = Lsn;
|
|||
|
|
|||
|
ioStatusBlock.Status = 0;
|
|||
|
ioStatusBlock.Information = 0;
|
|||
|
|
|||
|
nts = NtReadFile(Handle,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&ioStatusBlock,
|
|||
|
Buffer,
|
|||
|
SECSIZE,
|
|||
|
&byteOffset,
|
|||
|
NULL);
|
|||
|
|
|||
|
if(!NT_SUCCESS(nts)) {
|
|||
|
|
|||
|
printf("Read failed.\n");
|
|||
|
printf(" Returned status: %lx\n", nts);
|
|||
|
printf(" Final status: %lx\n", ioStatusBlock.Status);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
*BytesRead = ioStatusBlock.Information;
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
WriteSector(
|
|||
|
HANDLE Handle,
|
|||
|
ULONG Offset,
|
|||
|
PVOID Buffer
|
|||
|
)
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK ioStatusBlock;
|
|||
|
LARGE_INTEGER byteOffset;
|
|||
|
|
|||
|
byteOffset.HighPart = 0;
|
|||
|
byteOffset.LowPart = Offset;
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtWriteFile(Handle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&ioStatusBlock,
|
|||
|
Buffer,
|
|||
|
SECSIZE,
|
|||
|
&byteOffset,
|
|||
|
NULL))) {
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* BOOLEAN MyGetInput( int *Pi, char *Pc )
|
|||
|
*
|
|||
|
* read hex input from line and convert into byte
|
|||
|
*
|
|||
|
* Returns TRUE if a number was entered
|
|||
|
* FALSE if number should not be changed.
|
|||
|
*
|
|||
|
* *Pi == new number
|
|||
|
* *Pc == terminating character (either ' ' or '\r')
|
|||
|
*/
|
|||
|
BOOLEAN
|
|||
|
MyGetInput(
|
|||
|
int *Pi,
|
|||
|
char *Pc
|
|||
|
)
|
|||
|
{
|
|||
|
int j,i = 0;
|
|||
|
int c;
|
|||
|
|
|||
|
for(;;) {
|
|||
|
c = MyGetChr();
|
|||
|
c = toupper(c);
|
|||
|
|
|||
|
if (IsSepChar(&c)) {
|
|||
|
// term char, exit loop
|
|||
|
break;
|
|||
|
|
|||
|
} else if (c == '\b' && i != 0) {
|
|||
|
// backspace over last char
|
|||
|
printf("\b \b");
|
|||
|
i--;
|
|||
|
} else if (i < sizeof(Input) &&
|
|||
|
(isdigit(c) || (c>= 'A' && c <= 'F'))) {
|
|||
|
// good hex digit, store it
|
|||
|
|
|||
|
putchar(c);
|
|||
|
if( isdigit(c) ) {
|
|||
|
// convert digit to hex val
|
|||
|
c -= '0';
|
|||
|
} else {
|
|||
|
// covert char to hex val
|
|||
|
c = (c - 'A') + 10;
|
|||
|
}
|
|||
|
|
|||
|
Input[i++] = (BYTE)c;
|
|||
|
|
|||
|
} else {
|
|||
|
// some sort of error
|
|||
|
//DosBeep( 1000, 250 );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*Pc = (char)c;
|
|||
|
*Pi = 0;
|
|||
|
|
|||
|
for (j = 0; j < i; j++) {
|
|||
|
*Pi = *Pi * 16 + Input[j];
|
|||
|
}
|
|||
|
|
|||
|
return ((BOOLEAN)(i != 0));
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
_CRTAPI1 main(
|
|||
|
int ArgC,
|
|||
|
char *ArgS[]
|
|||
|
)
|
|||
|
{
|
|||
|
HANDLE handle;
|
|||
|
ULONG bytesRead;
|
|||
|
ULONG lsn;
|
|||
|
int i;
|
|||
|
int j;
|
|||
|
int lines;
|
|||
|
char c;
|
|||
|
char lastCmd;
|
|||
|
char currentDrive[12];
|
|||
|
PPTE partitionTable;
|
|||
|
BOOLEAN modify = FALSE;
|
|||
|
BOOLEAN more = FALSE;
|
|||
|
|
|||
|
// Disable hard-error popups.
|
|||
|
SetErrorMode(TRUE);
|
|||
|
|
|||
|
// See if we are connected to CON
|
|||
|
Batch = (BOOLEAN)(!isatty(0));
|
|||
|
|
|||
|
switch (ArgC) {
|
|||
|
case 2:
|
|||
|
// Nothing to do for level 2
|
|||
|
break;
|
|||
|
|
|||
|
case 3:
|
|||
|
if (strcmp(_strupr(ArgS[2]), "/E") == 0) {
|
|||
|
modify = TRUE;
|
|||
|
fprintf(stderr,
|
|||
|
"Warning: Opening drive %s for write access!\n", ArgS[1]);
|
|||
|
break;
|
|||
|
} else {
|
|||
|
fprintf(stderr, "%s: Invalid option '%s'\n", ArgS[0], ArgS[2]);
|
|||
|
}
|
|||
|
|
|||
|
// Note fall through to default: (usage case)
|
|||
|
|
|||
|
default:
|
|||
|
if (ArgC > 3)
|
|||
|
fprintf(stderr, "%s: Too many arguments\n", ArgS[0]);
|
|||
|
|
|||
|
fprintf(stderr, "usage: %s diskno [/e]\n", ArgS[0]);
|
|||
|
|
|||
|
// Re-enable harderror popups.
|
|||
|
SetErrorMode(FALSE);
|
|||
|
|
|||
|
exit(-1);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
sprintf(currentDrive, "%s", ArgS[1]);
|
|||
|
|
|||
|
if (!OpenFile(currentDrive, &handle)) {
|
|||
|
|
|||
|
fprintf(stderr,
|
|||
|
"%s: Unable to open %s\n", ArgS[0], currentDrive);
|
|||
|
|
|||
|
// Re-enable harderror popups.
|
|||
|
SetErrorMode(FALSE);
|
|||
|
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
// check if we want to do writes with dasd
|
|||
|
if (modify) {
|
|||
|
|
|||
|
// This is a drive, and we want to modify it, so we need
|
|||
|
// to lock it.
|
|||
|
|
|||
|
if (!LockVolume(handle)) {
|
|||
|
|
|||
|
printf("Unable to lock volume.\n");
|
|||
|
|
|||
|
// Re-enable harderror popups.
|
|||
|
SetErrorMode(FALSE);
|
|||
|
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// default to sector 0
|
|||
|
lsn = 0;
|
|||
|
|
|||
|
while (1)
|
|||
|
{
|
|||
|
PromptUsr();
|
|||
|
|
|||
|
if (fgets(Command, sizeof(Command), stdin) == NULL)
|
|||
|
break;
|
|||
|
|
|||
|
if ((i = sscanf(Command, "%c %li", &c, &lsn)) > 1) {
|
|||
|
if ((c != 'c') && (c != 'C')) {
|
|||
|
/*
|
|||
|
* The user entered a lsn as well as an lsn based command,
|
|||
|
* convert it to byte seek pos
|
|||
|
*/
|
|||
|
lsn *= SECSIZE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
more = FALSE;
|
|||
|
c = (char)tolower((int)c);
|
|||
|
|
|||
|
// pre process command
|
|||
|
if (c == 'q')
|
|||
|
break;
|
|||
|
|
|||
|
if (c == '\n')
|
|||
|
c = lastCmd;
|
|||
|
|
|||
|
switch (c) {
|
|||
|
case 'b':
|
|||
|
if (i == 1 && lastCmd == c) {
|
|||
|
// same command with no new lsn, use the next one on disk
|
|||
|
lsn -= bytesRead;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 'c':
|
|||
|
// change drives.
|
|||
|
|
|||
|
if (i != 2) {
|
|||
|
fprintf(stderr,
|
|||
|
"You must specify a drive number to change drives.\n");
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
CloseFile(handle);
|
|||
|
sprintf(currentDrive, "%d", lsn);
|
|||
|
|
|||
|
if (!OpenFile(currentDrive, &handle)) {
|
|||
|
|
|||
|
fprintf(stderr,
|
|||
|
"%s: Unable to open %s\n", ArgS[0], currentDrive);
|
|||
|
|
|||
|
// Re-enable harderror popups.
|
|||
|
SetErrorMode(FALSE);
|
|||
|
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
// check if we want to do writes with dasd
|
|||
|
if (modify) {
|
|||
|
|
|||
|
// This is a drive, and we want to modify it, so we need
|
|||
|
// to lock it.
|
|||
|
|
|||
|
if (!LockVolume(handle)) {
|
|||
|
|
|||
|
printf("Unable to lock volume.\n");
|
|||
|
|
|||
|
// Re-enable harderror popups.
|
|||
|
SetErrorMode(FALSE);
|
|||
|
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// default to sector 0
|
|||
|
lsn = 0;
|
|||
|
continue;
|
|||
|
|
|||
|
case 'g':
|
|||
|
{
|
|||
|
DISK_GEOMETRY diskGeometry;
|
|||
|
IO_STATUS_BLOCK statusBlock;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
// Get and display drive geometry from system.
|
|||
|
|
|||
|
status = NtDeviceIoControlFile(handle,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&statusBlock,
|
|||
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&diskGeometry,
|
|||
|
sizeof(DISK_GEOMETRY));
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
printf("BytesPerSector: %d\n", diskGeometry.BytesPerSector);
|
|||
|
printf("SectorsPerTrack: %d\n", diskGeometry.SectorsPerTrack);
|
|||
|
printf("TracksPerCylinder: %d\n", diskGeometry.TracksPerCylinder);
|
|||
|
printf("NumberOfCylinders: %d\n", diskGeometry.Cylinders);
|
|||
|
} else {
|
|||
|
fprintf(stderr, "Could not get geometry %x\n", status);
|
|||
|
}
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
case 'm':
|
|||
|
case 'd':
|
|||
|
case 'e':
|
|||
|
case 'p':
|
|||
|
if (i == 1 && lastCmd == c) {
|
|||
|
// same command with no new lsn, use the next one on disk
|
|||
|
lsn += bytesRead;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
fprintf(stderr,"Unknown command '%c'\n", c);
|
|||
|
case 'h':
|
|||
|
case '?':
|
|||
|
fprintf(stderr," d [####]\tDump sector ####\n");
|
|||
|
fprintf(stderr," e [####]\tEdit sector ####\n");
|
|||
|
fprintf(stderr," m [####]\tDump sector with 'MORE'\n");
|
|||
|
fprintf(stderr," b [####]\tSame as 'd' but defaults to"
|
|||
|
" previous sector\n");
|
|||
|
fprintf(stderr," c [##]\tChange harddisk number\n");
|
|||
|
fprintf(stderr," p [####]\tDump partition table on sector ###\n");
|
|||
|
fprintf(stderr," q \tquit the program");
|
|||
|
fprintf(stderr,"\n"
|
|||
|
"\n If no new sector is given and the command is the same, the next"
|
|||
|
"\n sector on the disk is used. If no sector is given but the command"
|
|||
|
"\n is different from the previous command, the sector used in the"
|
|||
|
"\n last command will be used again.\n"
|
|||
|
);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// remember last command
|
|||
|
lastCmd = c;
|
|||
|
bytesRead = 0;
|
|||
|
|
|||
|
if(!ReadSector(handle, lsn, Sector, &bytesRead)) {
|
|||
|
|
|||
|
printf("Unable to read sector %lx\n", lsn);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
printf("\n lsn:0x%lX bytes read:%d\n", lsn / SECSIZE, bytesRead);
|
|||
|
|
|||
|
switch (c) {
|
|||
|
case 'm':
|
|||
|
/*
|
|||
|
* More
|
|||
|
*/
|
|||
|
more = TRUE;
|
|||
|
// fall through to Dump
|
|||
|
|
|||
|
case 'd':
|
|||
|
case 'b':
|
|||
|
/*
|
|||
|
* Dump
|
|||
|
*/
|
|||
|
lines = 0;
|
|||
|
HexLine[0] = '\0';
|
|||
|
CharLine[0] = '\0';
|
|||
|
i = 0;
|
|||
|
sprintf(HexLine, "%04X ", i);
|
|||
|
|
|||
|
for (i = 0; i < (int)bytesRead; i++) {
|
|||
|
|
|||
|
sprintf(HexLine, "%s%2x ", HexLine, Sector[i]);
|
|||
|
sprintf(CharLine, "%s%c", CharLine,
|
|||
|
(isprint(Sector[i])) ? Sector[i] : '.');
|
|||
|
|
|||
|
if ((i != 0) && ((i % 16) == 15))
|
|||
|
{
|
|||
|
printf("%s *%s*\n", HexLine, CharLine);
|
|||
|
HexLine[0] = '\0';
|
|||
|
sprintf(HexLine, "%04X ", i + 1);
|
|||
|
CharLine[0] = '\0';
|
|||
|
lines++;
|
|||
|
}
|
|||
|
|
|||
|
if (more && (lines == 20)) {
|
|||
|
printf("\n--MORE--");
|
|||
|
MyGetChr();
|
|||
|
printf("\r");
|
|||
|
lines = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
putchar('\n');
|
|||
|
break;
|
|||
|
|
|||
|
case 'p':
|
|||
|
/*
|
|||
|
* dump partition table
|
|||
|
*/
|
|||
|
|
|||
|
if (LoadWORD(&Sector[SIGNATURE_OFFSET]) == 0xaa55) {
|
|||
|
partitionTable = ((PBOOTSECTOR)Sector)->PartitionTable;
|
|||
|
|
|||
|
for (i = 0; i < 4; i++) {
|
|||
|
|
|||
|
printf("\nEntry #%u:\n",i);
|
|||
|
printf(" Boot flag : %u\n",
|
|||
|
partitionTable[i].BootIndicator);
|
|||
|
printf(" System ID : %u\n",
|
|||
|
partitionTable[i].SysID);
|
|||
|
printf(" Relative sectors: %u (0x%x)\n",
|
|||
|
LoadDWORD(&partitionTable[i].Relative0),
|
|||
|
LoadDWORD(&partitionTable[i].Relative0));
|
|||
|
printf(" Sector count : %u (0x%x) [%u MB]\n",
|
|||
|
LoadDWORD(&partitionTable[i].SectorCount0),
|
|||
|
LoadDWORD(&partitionTable[i].SectorCount0),
|
|||
|
(LoadDWORD(&partitionTable[i].SectorCount0) *
|
|||
|
SECSIZE) / (1024*1024));
|
|||
|
printf(" Start CHS : %u %u %u\n",
|
|||
|
partitionTable[i].StartCylinder |
|
|||
|
((partitionTable[i].StartSector & 0xc0) << 2),
|
|||
|
partitionTable[i].StartHead,
|
|||
|
partitionTable[i].StartSector & 0x3f);
|
|||
|
printf(" End CHS : %u %u %u\n",
|
|||
|
partitionTable[i].EndCylinder |
|
|||
|
((partitionTable[i].EndSector & 0xc0) << 2),
|
|||
|
partitionTable[i].EndHead,
|
|||
|
partitionTable[i].EndSector & 0x3f);
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
printf("\nSector %u is not a valid master boot sector.\n",
|
|||
|
lsn/SECSIZE);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 'e':
|
|||
|
/*
|
|||
|
* Edit
|
|||
|
*/
|
|||
|
if (!modify) {
|
|||
|
|
|||
|
printf("Can not edit, restart with /e option\n");
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
for (i = 0; i < (int)bytesRead; i++) {
|
|||
|
if ((i % CB_INPUTLINE) == 0) {
|
|||
|
// print line header
|
|||
|
printf("\n%04X\t", i);
|
|||
|
}
|
|||
|
|
|||
|
printf("%02X.", (BYTE)Sector[i]);
|
|||
|
|
|||
|
if (MyGetInput(&j, &c )) {
|
|||
|
|
|||
|
Sector[i] = (BYTE)j;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
printf("%02X", (BYTE)Sector[i]);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (c == '\r')
|
|||
|
break;
|
|||
|
|
|||
|
putchar('\t');
|
|||
|
}
|
|||
|
|
|||
|
printf("\nWrite new data to sector? (Y/N)");
|
|||
|
c = (char)MyGetChr();
|
|||
|
if ((c = (char)toupper(c)) == 'Y') {
|
|||
|
|
|||
|
// User wants to save the data
|
|||
|
printf("Yes....");
|
|||
|
|
|||
|
if (!WriteSector(handle, lsn, Sector)) {
|
|||
|
|
|||
|
fprintf(stderr, "Write failed\n");
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// indicate success
|
|||
|
printf("\t[Done]\n");
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// user chickened out
|
|||
|
printf("No....\t[Nothing written]\n");
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// if this was a dasd open, then unlock the drive
|
|||
|
if (modify) {
|
|||
|
UnlockVolume(handle);
|
|||
|
}
|
|||
|
|
|||
|
CloseFile(handle);
|
|||
|
|
|||
|
// Re-enable harderror popups.
|
|||
|
SetErrorMode(FALSE);
|
|||
|
|
|||
|
exit(0);
|
|||
|
}
|