summaryrefslogtreecommitdiffstats
path: root/private/sdktools/damage/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/sdktools/damage/io.c')
-rw-r--r--private/sdktools/damage/io.c612
1 files changed, 612 insertions, 0 deletions
diff --git a/private/sdktools/damage/io.c b/private/sdktools/damage/io.c
new file mode 100644
index 000000000..3255d4a4b
--- /dev/null
+++ b/private/sdktools/damage/io.c
@@ -0,0 +1,612 @@
+#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);
+}