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.
 
 
 
 
 
 

612 lines
17 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>
#include <malloc.h>
#include "defs.h"
#include "types.h"
#include "globals.h"
HANDLE VolumeHandle;
const ULONG SectorSize = 512;
PVOID TransferBuffer = NULL;
PVOID TransferLocation = NULL;
BOOLEAN
open_disk(
char* DosDriveName,
BOOLEAN WriteAccess
)
/*++
Routine Description:
This function uses the NT native API to open a drive.
Arguments:
DosDriveName -- supplies the DOS name of the drive.
WriteAccess -- supplies a flag which indicates, if TRUE,
that the volume should be opened for write
access.
Return Value:
TRUE upon successful completion.
The handle is stored in VolumeHandle (local to this module).
Notes:
If the volume is opened for write access, it is also locked.
--*/
{
FILE_ALIGNMENT_INFORMATION AlignmentInfo;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING NtDriveName;
PWSTR WideCharDosName;
IO_STATUS_BLOCK status_block;
NTSTATUS status;
int CharsInName, i;
ULONG TransferOffset, BufferSize, AlignMask;
ACCESS_MASK AccessMask;
// Create a wide-character string with the DOS drive name.
// Note that I assume that the drive name is ASCII, and ignore
// multi-byte characters.
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 ) ) {
free( WideCharDosName );
return FALSE;
}
// If the NT drive name has a trailing backslash, remove it.
// 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);
CharsInName -= 1;
}
InitializeObjectAttributes( &oa,
&NtDriveName,
OBJ_CASE_INSENSITIVE,
0,
0 );
AccessMask = SYNCHRONIZE | FILE_READ_DATA;
if( WriteAccess ) {
AccessMask |= FILE_WRITE_DATA;
}
if( !NT_SUCCESS( NtOpenFile( &VolumeHandle,
AccessMask,
&oa,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT ) ) ) {
return FALSE;
}
// If we're opening for write access, lock it, too.
if( WriteAccess && !fUnsafe && !lock_disk() ) {
NtClose( VolumeHandle );
return FALSE;
}
// Get the volume's alignment factor, and allocate a
// properly-aligned transfer buffer.
status = NtQueryInformationFile( VolumeHandle,
&status_block,
&AlignmentInfo,
sizeof( AlignmentInfo ),
FileAlignmentInformation );
if( !NT_SUCCESS(status) ) {
NtClose( VolumeHandle );
return FALSE;
}
AlignMask = AlignmentInfo.AlignmentRequirement;
BufferSize = SectorSize * 4 + AlignMask + 1;
if( (TransferBuffer = malloc( BufferSize )) == NULL ) {
NtClose( VolumeHandle );
return FALSE;
}
if( (ULONG)TransferBuffer & AlignMask ) {
TransferOffset = AlignMask + 1 - ((ULONG)TransferBuffer & AlignMask);
} else {
// This buffer is properly aligned.
TransferOffset = 0;
}
TransferLocation = (PVOID)((PCHAR)TransferBuffer + TransferOffset);
// BUGBUG billmc -- memory leak through NtDriveName?
return TRUE;
}
BOOLEAN
read_scratch(
ULONG Lbn,
void* UserBuffer,
ULONG NumberOfSectors
)
{
IO_STATUS_BLOCK StatusBlock;
LARGE_INTEGER ByteOffset;
NTSTATUS Status;
ULONG ThisChunk, Offset;
ByteOffset.LowPart = SectorSize * Lbn;
ByteOffset.HighPart = 0;
Offset = 0;
while( NumberOfSectors ) {
ThisChunk = (NumberOfSectors < 4) ? NumberOfSectors : 4;
Status = NtReadFile( VolumeHandle,
0,
NULL,
NULL,
&StatusBlock,
TransferLocation,
SectorSize * ThisChunk,
&ByteOffset,
NULL );
if( !NT_SUCCESS(Status) ||
StatusBlock.Information != SectorSize * ThisChunk ) {
return FALSE;
}
memcpy( (PCHAR)UserBuffer + Offset,
TransferLocation,
ThisChunk * SectorSize );
NumberOfSectors -= ThisChunk;
ByteOffset.LowPart += ThisChunk * SectorSize;
Offset += ThisChunk * SectorSize;
}
return( TRUE );
}
BOOLEAN
write_scratch(
ULONG Lbn,
void* UserBuffer,
ULONG NumberOfSectors
)
{
IO_STATUS_BLOCK StatusBlock;
LARGE_INTEGER ByteOffset;
NTSTATUS Status;
ULONG ThisChunk, Offset;
ByteOffset.LowPart = SectorSize * Lbn;
ByteOffset.HighPart = 0;
Offset = 0;
while( NumberOfSectors ) {
ThisChunk = (NumberOfSectors < 4) ? NumberOfSectors : 4;
memcpy( TransferLocation,
(PCHAR)UserBuffer + Offset,
ThisChunk * SectorSize );
Status = NtWriteFile( VolumeHandle,
0,
NULL,
NULL,
&StatusBlock,
TransferLocation,
SectorSize * ThisChunk,
&ByteOffset,
NULL );
if( !NT_SUCCESS(Status) ||
StatusBlock.Information != SectorSize * ThisChunk ) {
return FALSE;
}
NumberOfSectors -= ThisChunk;
ByteOffset.LowPart += ThisChunk * SectorSize;
Offset += ThisChunk * SectorSize;
}
return( TRUE );
}
BOOLEAN
lock_disk(
)
/**+
Routine Description:
This function locks the disk. Note that the matching unlock_disk
function is not required, since the handle is automatically unlocked
when it is closed.
Arguments:
None.
Return Value:
None.
--*/
{
IO_STATUS_BLOCK IoStatusBlock;
if( !NT_SUCCESS(NtFsControlFile( VolumeHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
FSCTL_LOCK_VOLUME,
NULL,
0,
NULL,
0 )) ) {
return FALSE;
}
return TRUE;
}
VOID
close_disk(
)
/*++
Routine Description:
This function closes a previously-opened volume.
Arguments:
Handle -- supplies the volume handle.
Return Value:
None.
Notes:
This is currently just a wrapper for NtClose, but it creates
a channel where I can put piggyback stuff on open/close of
volumes.
--*/
{
NtClose( VolumeHandle );
}
/*** write_log -- append a field to a file
*
* This function appends a line of the form "set <string>=<field value>"
* to the file specified by the /L:<filename> command line switch.
* This allows the user to save information the DAMAGE found for later
* use.
*
* write_log(item)
*
* ENTRY item is the number of the field that the function is
* to save
*
* EXIT log file is modified
*
* WARNINGS none
*
* CALLS printf, log_gets, fprintf
*/
void
write_log(USHORT item)
{
UCHAR szVar[40];
UCHAR szValue[40];
UCHAR *get_time();
struct SuperSpare *s;
struct FNODE *f;
struct DIRBLK *d;
struct ALSEC *a;
union dp dp;
ULONG *l, offset;
UCHAR *p;
UCHAR szHex8[6];
UCHAR szHex4[5];
UCHAR szHex2[5];
UCHAR szStr[3];
strcpy(szHex8, "%08lx");
strcpy(szHex4, "%04x");
strcpy(szHex2, "%02x");
strcpy(szStr, "%s");
// get name to write
printf("Name of variable: ");
log_gets(szVar);
if (!strlen(szVar))
return;
// get field value
switch (currobj.type) {
case TYPE_SUPERB:
s = (struct SuperSpare *)currobj.mem;
if (currobj.offset == FIELDOFFSET (struct SuperSpare, spb)) {
if (item == iSPB_SIG1)
sprintf(szValue, szHex8, s->spb.SPB_SIG1);
else if (item == iSPB_SIG2)
sprintf(szValue, szHex8, s->spb.SPB_SIG2);
else if (item == iSPB_FLAG)
sprintf(szValue, szHex8, s->spb.SPB_FLAG);
else if (item == iSPB_HFSEC)
sprintf(szValue, szHex8, s->spb.SPB_HFSEC);
else if (item == iSPB_HFUSE)
sprintf(szValue, szHex8, s->spb.SPB_HFUSE);
else if (item == iSPB_HFMAX)
sprintf(szValue, szHex8, s->spb.SPB_HFMAX);
else if (item == iSPB_SDBCNT)
sprintf(szValue, szHex8, s->spb.SPB_SDBCNT);
else if (item == iSPB_SDBMAX)
sprintf(szValue, szHex8, s->spb.SPB_SDBMAX);
#ifdef CODEPAGE
else if (item == iSPB_CPSEC)
sprintf(szValue, szHex8, s->spb.SPB_CPSEC);
else if (item == iSPB_CPCNT)
sprintf(szValue, szHex8, s->spb.SPB_CPCNT);
else
sprintf(szValue,
szHex8, s->spb.SPB_SPARDB[item - iSPB_CPCNT + 1]);
#else
else
sprintf(szValue,
szHex8, s->spb.SPB_SPARDB[item - 9]);
#endif
}
else {
if (item == iSB_SIG1)
sprintf(szValue, szHex8, s->sb.SB_SIG1);
else if (item == iSB_SIG2)
sprintf(szValue, szHex8, s->sb.SB_SIG2);
else if (item == iSB_VER)
sprintf(szValue, szHex2, s->sb.SB_VER);
else if (item == iSB_FVER)
sprintf(szValue, szHex2, s->sb.SB_FVER);
else if (item == iSB_ROOT)
sprintf(szValue, szHex8, s->sb.SB_ROOT);
else if (item == iSB_SEC)
sprintf(szValue, szHex8, s->sb.SB_SEC);
else if (item == iSB_BSEC)
sprintf(szValue, szHex8, s->sb.SB_BSEC);
else if (item == iSB_BII_P)
sprintf(szValue, szHex8, s->sb.SB_BII.P);
else if (item == iSB_BBL_P)
sprintf(szValue, szHex8, s->sb.SB_BBL.P);
else if (item == iSB_CDDAT)
sprintf(szValue, szStr, get_time(s->sb.SB_CDDAT));
else if (item == iSB_DODAT)
sprintf(szValue, szStr, get_time(s->sb.SB_DODAT));
else if (item == iSB_DBSIZE)
sprintf(szValue, szHex8, s->sb.SB_DBSIZE);
else if (item == iSB_DBLOW)
sprintf(szValue, szHex8, s->sb.SB_DBLOW);
else if (item == iSB_DBHIGH)
sprintf(szValue, szHex8, s->sb.SB_DBHIGH);
else if (item == iSB_DBMAP)
sprintf(szValue, szHex8, s->sb.SB_DBMAP);
}
break;
case TYPE_BII:
l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
sprintf(szValue, "%3d) %08lx ", item, l[item - 1]);
break;
case TYPE_BBL:
l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
if (item == 1)
sprintf(szValue, szHex8, *(ULONG *)currobj.mem);
else
sprintf(szValue, szHex8, l[item - 2]);
break;
case TYPE_HFSEC:
l = ((ULONG *)currobj.mem) + currobj.offset + (item-1)/3;
if (!(item % 3))
sprintf(szValue, szHex8, *(l + 2*hfmax));
else if ((item % 3) == 1)
sprintf(szValue, szHex8, *(l + hfmax));
else
sprintf(szValue, szHex8, *l);
break;
case TYPE_FNODE:
f = (struct FNODE *)currobj.mem;
if (!currobj.offset) {
if (item == iFN_SIG)
sprintf(szValue, szHex8, f->FN_SIG);
else if (item == iFN_SRH)
sprintf(szValue, szHex8, f->FN_SRH);
else if (item == iFN_FRH)
sprintf(szValue, szHex8, f->FN_FRH);
else if (item == iFN_XXX)
sprintf(szValue, szHex8, f->FN_SIG);
else if (item == iFN_HCNT)
sprintf(szValue, szHex2, f->FN_HCNT);
else if (item == iFN_CONTFN)
sprintf(szValue, szHex8, f->FN_CONTFN);
else if (item == iFN_ACL_AI_DAL)
sprintf(szValue, szHex8, f->FN_AclDiskLength);
else if (item == iFN_ACL_AI_SEC)
sprintf(szValue, szHex8, f->FN_AclSector);
else if (item == iFN_ACL_AI_FNL)
sprintf(szValue, szHex4, f->FN_AclFnodeLength);
else if (item == iFN_ACL_AI_DAT)
sprintf(szValue, szHex2, f->FN_AclDataFlag);
else if (item == iFN_EA_AI_DAL)
sprintf(szValue, szHex8, f->FN_EaDiskLength);
else if (item == iFN_EA_AI_SEC)
sprintf(szValue, szHex8, f->FN_EaSector);
else if (item == iFN_EA_AI_FNL)
sprintf(szValue, szHex4, f->FN_EaFnodeLength);
else if (item == iFN_EA_AI_DAT)
sprintf(szValue, szHex2, f->FN_EaDataFlag);
}
else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_AB)) {
if (item == iAB_FLAG)
sprintf(szValue, szHex8, f->FN_AB.AB_FLAG);
else if (item == iAB_FCNT)
sprintf(szValue, szHex2, f->FN_AB.AB_FCNT);
else if (item == iAB_OCNT)
sprintf(szValue, szHex2, f->FN_AB.AB_OCNT);
else if (item == iAB_FREP)
sprintf(szValue, szHex4, f->FN_AB.AB_FREP);
}
else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_ALREC [0])) {
l = (ULONG *)f->FN_ALREC;
sprintf(szValue, szHex8, *(l + (item - 1)));
}
break;
case TYPE_DIRBLK:
d = (struct DIRBLK *)currobj.mem;
dp.p = (UCHAR *)currobj.mem + currobj.offset;
if (item == iDB_SIG)
sprintf(szValue, szHex8, d->DB_SIG);
else if (item == iDB_FREP)
sprintf(szValue, szHex8, d->DB_FREP);
else if (item == iDB_CCNT)
sprintf(szValue, szHex8, d->DB_CCNT);
else if (item == iDB_PAR)
sprintf(szValue, szHex8, d->DB_PAR);
else if (item == iDB_SEC)
sprintf(szValue, szHex8, d->DB_SEC);
else if (item == iDIR_ELEN)
sprintf(szValue, szHex4, dp.d->DIR_ELEN);
else if (item == iDIR_FLAG)
sprintf(szValue, szHex8, dp.d->DIR_FLAG);
else if (item == iDIR_FN)
sprintf(szValue, szHex8, dp.d->DIR_FN);
else if (item == iDIR_MTIM)
sprintf(szValue, szStr, get_time(dp.d->DIR_MTIM));
else if (item == iDIR_SIZE)
sprintf(szValue, szHex8, dp.d->DIR_SIZE);
else if (item == iDIR_ATIM)
sprintf(szValue, szStr, get_time(dp.d->DIR_ATIM));
else if (item == iDIR_CTIM)
sprintf(szValue, szStr, get_time(dp.d->DIR_CTIM));
else if (item == iDIR_EALEN)
sprintf(szValue, szHex8, dp.d->DIR_EALEN);
else if (item == iDIR_NAML)
sprintf(szValue, szHex2, dp.d->DIR_NAML);
else if (item == iDIR_NAMA) {
strncpy(scratch, &dp.d->DIR_NAMA, dp.d->DIR_NAML);
scratch[dp.d->DIR_NAML] = '\0';
sprintf(szValue, szStr, scratch);
}
else if (item == iDIR_BTP)
sprintf(szValue, szHex8, DOWN_PTR(dp));
break;
case TYPE_ALSEC:
a = (struct ALSEC *)currobj.mem;
if (!currobj.offset) {
if (item == iAS_SIG)
sprintf(szValue, szHex8, a->AS_SIG);
else if (item == iAS_SEC)
sprintf(szValue, szHex8, a->AS_SEC);
else if (item == iAS_RENT)
sprintf(szValue, szHex8, a->AS_RENT);
else if (item == iAS_ALBLK_AB_FLAG)
sprintf(szValue, szHex8, a->AS_ALBLK.AB_FLAG);
else if (item == iAS_ALBLK_AB_FCNT)
sprintf(szValue, szHex2, a->AS_ALBLK.AB_FCNT);
else if (item == iAS_ALBLK_AB_OCNT)
sprintf(szValue, szHex2, a->AS_ALBLK.AB_OCNT);
else if (item == iAS_ALBLK_AB_FREP)
sprintf(szValue, szHex4, a->AS_ALBLK.AB_FREP);
}
else {
l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
sprintf(szValue, szHex8, *(l + (item - 1)));
}
break;
default:
printf("log: unknown type\n");
}
// write to file
fprintf(fpLog, "set %s=%s\n", szVar, szValue);
}