Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

668 lines
16 KiB

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include <io.h>
#include <ntioapi.h>
#include <ntdddisk.h>
#define CB_LINE 16
//#define SECSIZE 512
#define CB_INPUT 2
#define CB_INPUTLINE 8
#define CB_CMDLINE 256
typedef UCHAR BYTE;
typedef BYTE* PBYTE;
//BYTE abSector[SECSIZE];
BYTE abInput[CB_INPUT];
char szCommand[CB_CMDLINE];
BOOLEAN fBatch = FALSE;
ULONG SectorSize;
PBYTE DataBuffer;
PBYTE SectorData;
BOOLEAN IsSepChar( int *pc )
{
switch( *pc ) {
case ',':
*pc = ' ';
return TRUE;
case '\n':
*pc = '\r';
return TRUE;
case ' ':
if( fBatch )
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( fBatch ) {
int c;
while( (c = getchar()) == ' ' );
return c;
} else {
return _getch();
}
}
void PromptUsr( void )
{
if( !fBatch )
printf( "\n$ " );
}
BOOLEAN
OpenFile(
PSZ DosDriveName,
PHANDLE Handle
)
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING NtDriveName;
PWSTR WideCharDosName;
IO_STATUS_BLOCK status_block;
int CharsInName, i;
// Create a wide-character string with the DOS drive name. Assume
// that all DOS drive names are ASCII, to simplify this process.
CharsInName = strlen( DosDriveName );
WideCharDosName = malloc ( (CharsInName+1) * sizeof(WCHAR) );
if( WideCharDosName == NULL ) {
return FALSE;
}
for( i = 0; i < CharsInName; i++ ) {
WideCharDosName[i] = DosDriveName[i];
}
WideCharDosName[CharsInName] = 0;
// OK, now get the corresponding NT name, in wide characters:
if( !RtlDosPathNameToNtPathName_U( WideCharDosName,
&NtDriveName,
NULL,
NULL ) ) {
printf( "RtlDosPathNameToNtPathName failed.\n" );
exit(1);
}
// BUGBUG billmc -- why is this necessary?
CharsInName = NtDriveName.Length / sizeof(WCHAR);
if( NtDriveName.Buffer[CharsInName-1] == '\\' ) {
NtDriveName.Buffer[CharsInName-1] == 0;
NtDriveName.Length -= sizeof(WCHAR);
}
InitializeObjectAttributes( &oa,
&NtDriveName,
OBJ_CASE_INSENSITIVE,
0,
0
);
if (!NT_SUCCESS(NtOpenFile(Handle,
SYNCHRONIZE | FILE_READ_DATA |
FILE_WRITE_DATA,
&oa,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT))) {
return FALSE;
}
// BUGBUG billmc -- memory leak through NtDriveName?
// BUGBUG billmc -- memory leak through NtDriveName?
return TRUE;
}
BOOLEAN
QueryVolumeInformation(
HANDLE Handle,
PULONG AlignmentMask,
PULONG SectorSize
)
{
FILE_ALIGNMENT_INFORMATION AlignmentInfo;
DISK_GEOMETRY DiskGeometry;
IO_STATUS_BLOCK status_block;
NTSTATUS status;
status = NtQueryInformationFile( Handle,
&status_block,
&AlignmentInfo,
sizeof( AlignmentInfo ),
FileAlignmentInformation );
if( !NT_SUCCESS(status) ) {
return FALSE;
}
*AlignmentMask = AlignmentInfo.AlignmentRequirement;
status = NtDeviceIoControlFile( Handle,
0,
NULL,
NULL,
&status_block,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&DiskGeometry,
sizeof( DiskGeometry ) );
if( !NT_SUCCESS(status) ) {
return FALSE;
}
*SectorSize = DiskGeometry.BytesPerSector;
return TRUE;
}
BOOLEAN
CloseFile(
HANDLE Handle
)
{
if( !NT_SUCCESS(NtClose( Handle )) ) {
return FALSE;
} else {
return TRUE;
}
}
BOOLEAN
LockVolume(
HANDLE Handle
)
{
IO_STATUS_BLOCK IoStatusBlock;
if( !NT_SUCCESS(NtFsControlFile( Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
FSCTL_LOCK_VOLUME,
NULL,
0,
NULL,
0 )) ) {
printf( "Unable to lock volume.\n" );
return FALSE;
}
return TRUE;
}
BOOLEAN
UnlockVolume(
HANDLE Handle
)
{
IO_STATUS_BLOCK IoStatusBlock;
if( !NT_SUCCESS(NtFsControlFile( Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
FSCTL_UNLOCK_VOLUME,
NULL,
0,
NULL,
0 )) ) {
printf( "Unable to unlock volume.\n" );
return FALSE;
}
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,
SectorSize,
&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,
SectorSize,
&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( abInput ) &&
(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;
}
abInput[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 + abInput[j];
}
return (i != 0);
}
void _CRTAPI1 main( int cArgs, char *szArg[] )
{
HANDLE Handle;
int i, j, k;
BOOLEAN fMore = FALSE;
ULONG cbRead;
char c, chLastCmd;
ULONG lsn;
BOOLEAN fModify = FALSE;
ULONG AlignmentMask;
/* See if we are connected to CON */
fBatch = !isatty( 0 );
switch( cArgs ) {
case 2:
/* Nothing to do for level 2 */
break;
case 3:
if( strcmp( _strupr(szArg[2]), "/E" ) == 0 ) {
fModify = TRUE;
fprintf( stderr,
"Warning: Opening drive %s for write access!\n", szArg[1] );
break;
} else {
fprintf(stderr, "%s: Invalid option '%s'\n", szArg[0], szArg[2]);
}
/* Note fall through to default: (usage case) */
default:
if( cArgs > 3 )
fprintf( stderr, "%s: Too many arguments\n", szArg[0] );
fprintf( stderr, "usage: %s drive_or_file [/e]\n", szArg[0] );
exit(-1);
break;
}
if( !OpenFile( szArg[1], &Handle ) ){
fprintf( stderr, "%s: Unable to open %s\n", szArg[0], szArg[1] );
exit(1);
}
if( !QueryVolumeInformation( Handle, &AlignmentMask, &SectorSize ) ) {
fprintf( stderr, "Cannot determine volume information.\n" );
exit(1);
}
// Allocate a buffer to read and write sectors. Note that this
// buffer has to satisfy the device's alignment restrictions.
DataBuffer = (PBYTE)malloc( SectorSize + AlignmentMask );
if( DataBuffer == NULL ) {
fprintf( stderr, "Out of memory.\n" );
exit(1);
}
SectorData = (PBYTE)(((ULONG)(DataBuffer) + AlignmentMask) & ~AlignmentMask);
//
/* check if we want to do writes with dasd */
if( fModify && szArg[1][1] == '\\' && szArg[1][2] == ':' ) {
// 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" );
exit(1);
}
}
/* default to sector 0 */
lsn = 0;
PromptUsr();
while( fgets(szCommand, sizeof( szCommand ), stdin) ){
if( (i = sscanf( szCommand, "%c %li", &c, &lsn )) > 1 ) {
/*
* The user entered a lsn as well as a command,
* convert it to byte seek pos
*/
lsn *= SectorSize;
}
fMore = FALSE;
c = (char)tolower( (int)c );
/* pre process command */
if( c == 'q' )
break;
switch( c ) {
case 'b':
if( i == 1 && chLastCmd == c ) {
/* same command with no new lsn, use the next one on disk */
lsn -= cbRead;
}
break;
case 'm':
case 'd':
case 'e':
if( i == 1 && chLastCmd == c ) {
/* same command with no new lsn, use the next one on disk */
lsn += cbRead;
}
break;
default:
fprintf(stderr,"Unknown command '%c'\n", c );
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," 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"
);
PromptUsr();
continue;
}
/* remember last command */
chLastCmd = c;
cbRead = 0;
if( !ReadSector( Handle, lsn, SectorData, &cbRead ) ) {
printf( "Unable to read sector %lx\n", lsn );
} else {
printf( "\n lsn:0x%lX bytes read:%d\n",
lsn / SectorSize, cbRead );
switch( c ) {
case 'm':
/*
* More
*/
fMore = TRUE;
/* fall through to Dump */
case 'd':
case 'b':
/*
* Dump
*/
k = 0;
for( i = 0; i < cbRead; i += CB_LINE ) {
if( fMore && k++ == 20 ) {
printf( "\n--MORE--" );
MyGetChr();
printf( "\r" );
k = 0;
}
printf("\n%04X ", i );
for( j = 0; j < CB_LINE && (j + i) < cbRead; j++ ) {
printf( "%02X ", (BYTE)SectorData[i + j] );
}
printf( " " );
for( j = 0; j < CB_LINE && (j + i) < cbRead; j++ ) {
if( (c = SectorData[i + j]) >= ' ' && c <= '\177' )
putchar( c );
else
putchar( '.' );
}
}
putchar( '\n' );
break;
case 'e':
/*
* Edit
*/
if( !fModify ) {
printf( "Can not edit, restart with /e option\n" );
} else {
for( i = 0; i < cbRead; i++ ) {
if( (i % CB_INPUTLINE) == 0 ) {
/* print line header */
printf("\n%04X\t", i );
}
printf( "%02X.", (BYTE)SectorData[i] );
if( MyGetInput( &j, &c ) ) {
SectorData[i] = (BYTE)j;
} else {
printf( "%02X", (BYTE)SectorData[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, SectorData ) ) {
fprintf( stderr,
"Write failed\n" );
} else {
/* indicate success */
printf( "\t[Done]\n" );
}
} else {
/* user chickened out */
printf( "No....\t[Nothing written]\n" );
}
}
break;
}
}
PromptUsr();
}
/* if this was a dasd open, then unlock the drive */
if( fModify ) {
UnlockVolume( Handle );
}
CloseFile( Handle );
exit(0);
}