summaryrefslogtreecommitdiffstats
path: root/private/sdktools/simbad
diff options
context:
space:
mode:
Diffstat (limited to 'private/sdktools/simbad')
-rw-r--r--private/sdktools/simbad/makefile6
-rw-r--r--private/sdktools/simbad/simbad.c1245
-rw-r--r--private/sdktools/simbad/sources28
3 files changed, 1279 insertions, 0 deletions
diff --git a/private/sdktools/simbad/makefile b/private/sdktools/simbad/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/sdktools/simbad/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/sdktools/simbad/simbad.c b/private/sdktools/simbad/simbad.c
new file mode 100644
index 000000000..da3041f08
--- /dev/null
+++ b/private/sdktools/simbad/simbad.c
@@ -0,0 +1,1245 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ simbad.c (formerly simbad.cxx)
+
+Abstract:
+
+ This module contains the main function of SimBad, which
+ allows the user to to ask the device driver to simulate
+ bad sectors.
+
+Author:
+
+ Bill McJohn (billmc) 16-Aug-1991
+ Lars Opstad (a-larso) 6-Feb-1993
+
+Environment:
+
+ ULIB, User Mode
+
+Revision History:
+
+ 4.Apr.92 - BobRi - Minor fix to list function (device control interface)
+ 9.Apr.92 - BobRi - Modified (with BillMc's help) to support the access
+ triggers on when block numbers are to fail.
+
+ 29.Jan.93 - LarsOp - Major changes to change to allow redirected console
+ input. This required lots of changes because of
+ dependencies on cxx libraries -> convert to C.
+
+ Also added functionality on Sanjay's request for
+ supporting file input with multiple lists of bad
+ sectors.
+
+ 5.Feb.93 - Larsop - Added new function - orphan device. Any accesses to
+ the indicated partition will fail with a status of
+ STATUS_IO_DEVICE_ERROR.
+
+ 20.May.93 - mglass - Add support for VERIFY access type. This will allow
+ SIMBAD to test the format utiltiy.
+
+ 21.Jul.93 - mglass - Define access bit to fail attempt to reassign blocks.
+ 12.May.94 - Venkat - Added code to drop of writes to DISK (CHKDSK testing)
+ 22.Nov.94 - kpeery - Added code to force hardware reset (for restarts)
+--*/
+#include "stdlib.h"
+#include "stdio.h"
+#include "nt.h"
+#include "ntrtl.h"
+#include "ntdddisk.h"
+#include <simbad.h>
+
+//
+// Constants for command line arguments
+//
+#define HD_SPEC 'h'
+#define PART_SPEC 'p'
+#define LIST 'l'
+#define ZERO_OFF 'z'
+#define MAP 'm'
+#define ADD_ALL 'a'
+#define ADD_READ 'r'
+#define ADD_WRITE 'w'
+#define ADD_VERIFY 'v'
+#define DO_NOT_MAP 'x'
+#define ENABLE 'e'
+#define DISABLE 'd'
+#define ORPHAN 'o'
+#define CLEAR 'c'
+#define FROM_FILE 'f'
+#define RANDOM 'n'
+#define BUGCHECK 'b'
+#define FIRMWARE_RESET 't'
+
+#define MAX_DEV_NAME 128
+
+
+char devname[MAX_DEV_NAME]="\\Device\\HardDisk0\\Partition1";
+char *filename;
+WCHAR whattodo=LIST;
+ULONG Seed, accessType=0;
+int hdnum=0, partnum=1;
+ULONG sectors[MAXIMUM_SIMBAD_SECTORS];
+
+
+VOID
+InputSectorList (
+ OUT PULONG sectors,
+ OUT PULONG count
+ )
+/*++
+
+Routine Description:
+
+ This function reads the sector list from stdin. The list is
+ terminated by end of file (max bad sectors entered).
+
+Arguments:
+
+ sectors -- receives array of sectors
+ count -- receives number of sectors read from stdin
+
+Return value:
+
+ None.
+
+--*/
+{
+ //
+ // loop until end-of-file or count exceeds max sectors
+ //
+ while (!feof(stdin) && (*count) < MAXIMUM_SIMBAD_SECTORS) {
+
+ fscanf(stdin, "%lx", &(sectors[(*count)++]));
+
+ } // while
+
+ //
+ // if count is less than MAX_BAD_SECTORS,
+ // the last read was an EOF => decrement count.
+ //
+ if (*count < MAXIMUM_SIMBAD_SECTORS) {
+
+ (*count)--;
+
+ } // if
+} // InputSectorList()
+
+VOID
+ShowUsage (
+ )
+/*++
+
+Routine Description:
+
+ This function displays command line options for Simbad.
+
+Arguments:
+
+ None.
+
+Return value:
+
+ None.
+
+--*/
+{
+ printf("\nUsage: Simbad DeviceSpecifier /command /options\n"
+ "or Simbad /f file /options\n"
+ "\nwhere DeviceSpecifier is in one of the following formats:\n"
+ "\t\\Device\\HardDisk#\\Partition#\n"
+ "\t\\DosDevices\\C:\n"
+ "\t/h <hard disk #> /p <partition #>\n"
+ "\nand command is one of the following:\n"
+ "\ta Fail all access (enter sector list)\n"
+ "\tr Fail read access (enter sector list)\n"
+ "\tw Fail write access (enter sector list)\n"
+ "\tv Fail verify access (enter sector list)\n"
+ "\to Orphan entire device (return DEVICE FAILURE)\n"
+ "\tn Dropping writes randomly\n"
+ "\tb BugChecks the system\n"
+ "\tt Reset the system\n"
+ "\te Enable (previously entered) bad sectors\n"
+ "\td Disable (previously enabled) bad sectors\n"
+ "\tl List bad sectors\n"
+ "\tc Clear bad sectors\n"
+ "\nand options includes any of the following:\n"
+ "\tm Pass block reassignments to lower driver\n"
+ "\tz Failures report zero offset\n"
+ "\tx Fail block reassignment\n"
+ "\nNote: /h and /p have been added. The following cmd lines are equivalent:\n\n"
+ "\tSimbad \\Device\\HardDisk0\\Partition1 /l\n"
+ "\tSimbad /h 0 /p 1 /l\n"
+ "\nThe format of the file used with the /f option is as follows:\n\n"
+ "\\Device\\HardDisk#\\Partition#\n"
+ "R:0 8 a ...\n"
+ "W:...\n"
+ "A:...\n\n"
+ "This file can contain lists for multiple devices.\n"
+ "The bad sector emulation is not enabled until the /e option is entered.\n"
+ );
+ exit(-1);
+} // ShowUsage();
+
+
+VOID
+ParseCmdArgs (
+ IN int argc,
+ IN char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ This function sets some global variables based on the command line
+ arguments given to main (and passed here).
+
+ The globals that are set are as follows:
+
+ devname -- name of device to simulate bad sectors on
+ accessType -- fail on READ or WRITE, reassign, zero offset
+ whattodo -- which action (add, list, enable/disable, readfromfile)
+ filename -- which filename to use for FROM_FILE action
+
+Arguments:
+
+ argc -- supplies number of arguments
+ argv -- supplies list of arguments
+
+Return value:
+
+ None.
+
+--*/
+{
+ int i=1;
+
+ //
+ // if no arguments, just show usage.
+ //
+ if (argc==1) {
+
+ ShowUsage();
+
+ } // if
+
+ //
+ // check each argument
+ //
+ while (i<argc) {
+
+ //
+ // check first character
+ //
+ switch (argv[i][0]) {
+
+ //
+ // if first character is - or /, it is a switch.
+ //
+ case '-':
+ case '/':
+
+ //
+ // switch value is the second character
+ //
+ switch (tolower(argv[i][1])) {
+
+ //
+ // specify harddisk, sprintf devname
+ //
+ case HD_SPEC:
+
+ hdnum=atoi(argv[++i]);
+
+ sprintf(devname,
+ "\\Device\\HardDisk%d\\Partition%d",
+ hdnum,
+ partnum);
+
+ i++;
+ break;
+
+ //
+ // specify partition, sprintf devname
+ //
+ case PART_SPEC:
+
+ partnum=atoi(argv[++i]);
+
+ sprintf(devname,
+ "\\Device\\HardDisk%d\\Partition%d",
+ hdnum,
+ partnum);
+
+ i++;
+ break;
+
+ //
+ // set action to FROM_FILE and set filename
+ //
+ case FROM_FILE:
+
+ whattodo=argv[i++][1];
+ filename=argv[i++];
+ break;
+
+ //
+ // set zero offset bit in accessMode
+ //
+ // This means a failed io will return the beginning
+ // of the io instead of the failing sector.
+ //
+ case ZERO_OFF:
+
+ accessType|=SIMBAD_ACCESS_ERROR_ZERO_OFFSET;
+ whattodo=ADD_ALL;
+ i++;
+ break;
+
+ //
+ // set reassign bit in accessMode
+ //
+ // This allows simbad to reassign sectors on this device.
+ // Basically, simbad just removes the sector from the list
+ // on a reassign request.
+ //
+ case MAP:
+
+ accessType|=SIMBAD_ACCESS_CAN_REASSIGN_SECTOR;
+ whattodo=ADD_ALL;
+ i++;
+ break;
+
+ //
+ // Fail device control requests to reassign a bad block.
+ //
+ case DO_NOT_MAP:
+ accessType|=SIMBAD_ACCESS_FAIL_REASSIGN_SECTOR;
+ whattodo=ADD_ALL;
+ i++;
+ break;
+
+ //
+ // set fail-on-read bit in access mode (action is ADD)
+ //
+ case ADD_READ:
+
+ accessType|=SIMBAD_ACCESS_READ;
+ whattodo=ADD_ALL;
+ i++;
+ break;
+
+ //
+ // set fail-on-write bit in access mode (action is ADD)
+ //
+ case ADD_WRITE:
+
+ accessType|=SIMBAD_ACCESS_WRITE;
+ whattodo=ADD_ALL;
+ i++;
+ break;
+
+ //
+ // set fail-on-verify bit in access mode (action is ADD)
+ //
+ case ADD_VERIFY:
+
+ accessType|=SIMBAD_ACCESS_VERIFY;
+ whattodo=ADD_ALL;
+ i++;
+ break;
+
+ //
+ // set fail-on-read and fail-on-write bit in access mode
+ //
+ // Since ADD_ALL is the intended action, fall through to
+ // the next case which just sets the action to whatever
+ // character the switch is.
+ //
+ case ADD_ALL:
+
+ accessType|=(SIMBAD_ACCESS_READ|SIMBAD_ACCESS_WRITE|SIMBAD_ACCESS_VERIFY);
+
+ //
+ // NOTE: break intentionally left out (fall through to next)
+ //
+
+ //
+ // for list, enable, disable and clear, the action is the
+ // switch value
+ //
+ case LIST:
+ case ORPHAN:
+ case BUGCHECK:
+ case FIRMWARE_RESET:
+ case ENABLE:
+ case DISABLE:
+ case CLEAR:
+
+ whattodo=argv[i++][1];
+ break;
+
+ case RANDOM:
+ whattodo=argv[i++][1];
+ if ( i< argc ){
+ sscanf( argv[i++],"%lu", &Seed);
+ }else{
+ Seed=100;
+ }
+ break;
+
+ //
+ // any other switch, show usage
+ //
+ default:
+
+ ShowUsage();
+
+ } // switch (second character)
+ break;
+
+ //
+ // if first char is \, it is a device name
+ //
+ case '\\':
+
+ strcpy(devname,argv[i++]);
+ break;
+
+
+ //
+ // anything else, show usage
+ //
+ default:
+
+ ShowUsage();
+
+ } // switch (first character)
+
+ } // while
+
+} // ParseCmdArgs()
+
+
+//
+// Some of this code was taken directly from simbad.cxx (older version)
+// and PLBN needed to be defined for some of the older routines.
+//
+#define PLBN PULONG
+
+BOOLEAN
+OpenDrive(
+ IN char *psz_string,
+ OUT PHANDLE _phandle
+ )
+/*++
+
+Routine Description:
+
+ This routine opens the specified drive and passes back the handle.
+
+Arguments:
+
+ psz_string -- supplies the device name (format "\harddiskX\partitionY")
+ _phandle -- receives the handle to the opened device
+
+Return value:
+
+ Returns whether the open was successful.
+
+--*/
+{
+ OBJECT_ATTRIBUTES oa;
+ IO_STATUS_BLOCK status_block;
+ NTSTATUS _last_status;
+ ANSI_STRING ans_string;
+ UNICODE_STRING uni_string;
+
+ //
+ // Build unicode string
+ //
+ RtlInitAnsiString(&ans_string, psz_string);
+ RtlAnsiStringToUnicodeString(&uni_string, &ans_string, TRUE);
+
+
+ //
+ // setup object attributes for openfile
+ //
+ InitializeObjectAttributes( &oa,
+ &uni_string,
+ OBJ_CASE_INSENSITIVE,
+ 0,
+ 0 );
+
+ _last_status = NtOpenFile(_phandle,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ &oa, &status_block,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+
+ //
+ // Deallocate unicode string
+ //
+ RtlFreeUnicodeString(&uni_string);
+ //RtlFreeAnsiString(&ans_string); // BUG BUG This causes access viol, why?
+
+ return NT_SUCCESS(_last_status);
+} // OpenDrive()
+
+#ifndef SIMBAD_ORPHAN
+#define SIMBAD_ORPHAN 0x00000005
+#endif
+//
+// Bugchecks the system
+//
+
+BOOLEAN
+BugCheckOrResetTheSystem(HANDLE _handle, ULONG simbadFunction)
+
+/*++
+
+Routine Description:
+
+ This routine will setup SIMBAD for bug checking or reseting the system.
+
+Arguments:
+ _handle - a device handle
+ simbadFunction - the desired function to call in the driver
+
+Return Value:
+
+ TRUE upon successful completion.
+
+--*/
+{
+ SIMBAD_DATA SimbadData;
+ IO_STATUS_BLOCK StatusBlock;
+ NTSTATUS Status;
+
+ SimbadData.Function = simbadFunction;
+
+ Status= NtDeviceIoControlFile(_handle,
+ 0,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_DISK_SIMBAD,
+ &SimbadData,
+ sizeof(SIMBAD_DATA),
+ NULL,
+ 0);
+
+ if ((BOOLEAN)NT_SUCCESS(Status)){
+ return TRUE;
+ }else{
+ fprintf(stderr,
+ "BugCheckOrResetTheSystem(0x%08x) function %s failed (%lX)\n",
+ simbadFunction, devname, Status);
+ return FALSE;
+ }
+
+} //BugCheckOrRestTheSystem
+
+
+//
+// Drops of writes to disk. Purpose to corrupt the disk.
+//
+
+BOOLEAN
+RandomWriteFailure(
+ HANDLE _handle
+ )
+/*++
+
+Routine Description:
+
+ This routine causes io to the specified device to fail writes randomly.
+
+Arguments:
+
+Return Value:
+
+ TRUE upon successful completion.
+
+--*/
+{
+ SIMBAD_DATA SimbadData;
+ IO_STATUS_BLOCK StatusBlock;
+ NTSTATUS Status;
+ SimbadData.Count = Seed;
+ SimbadData.Function = SIMBAD_RANDOM_WRITE_FAIL;
+
+ Status= NtDeviceIoControlFile(_handle,
+ 0,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_DISK_SIMBAD,
+ &SimbadData,
+ sizeof(SIMBAD_DATA),
+ NULL,
+ 0);
+
+ if ((BOOLEAN)NT_SUCCESS(Status)){
+ return TRUE;
+ }else{
+ fprintf(stderr,
+ "RandomWriteFailure disk on %s failed (%lX)\n",
+ devname, Status);
+ return FALSE;
+ }
+
+
+
+} //RandomWriteFailure
+
+
+BOOLEAN
+OrphanDisk(
+ HANDLE _handle
+ )
+/*++
+
+Routine Description:
+
+ This routine causes io to the specified device to return DEVICE_FAILURE
+
+Arguments:
+
+Return Value:
+
+ TRUE upon successful completion.
+
+--*/
+{
+ SIMBAD_DATA SimbadData;
+ IO_STATUS_BLOCK StatusBlock;
+
+ SimbadData.Count = 0;
+ SimbadData.Function = SIMBAD_ORPHAN;
+
+ return (BOOLEAN)
+ NT_SUCCESS( NtDeviceIoControlFile(_handle,
+ 0,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_DISK_SIMBAD,
+ &SimbadData,
+ sizeof(SIMBAD_DATA),
+ NULL,
+ 0) );
+} // OrphanDisk()
+
+BOOLEAN
+EnableBadSectorSimulation(
+ HANDLE _handle,
+ BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ This routine turns bad sector simulation on or off.
+
+Arguments:
+
+ Enable -- supplies whether to turn simulation on (TRUE) or
+ off (FALSE)
+
+Return Value:
+
+ TRUE upon successful completion.
+
+--*/
+{
+ SIMBAD_DATA SimbadData;
+ IO_STATUS_BLOCK StatusBlock;
+
+ SimbadData.Count = 0;
+ SimbadData.Function = Enable ? SIMBAD_ENABLE : SIMBAD_DISABLE;
+
+ return (BOOLEAN)
+ NT_SUCCESS( NtDeviceIoControlFile(_handle,
+ 0,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_DISK_SIMBAD,
+ &SimbadData,
+ sizeof(SIMBAD_DATA),
+ NULL,
+ 0) );
+} // EnableBadSectorSimulation()
+
+BOOLEAN
+ClearBadSectors(
+ HANDLE _handle
+ )
+/*++
+
+Routine Description:
+
+ This routine turns bad sector simulation on or off.
+
+Arguments:
+
+ _handle - something with which to grip
+
+Return Value:
+
+ TRUE upon successful completion.
+
+--*/
+{
+ SIMBAD_DATA SimbadData;
+ IO_STATUS_BLOCK StatusBlock;
+
+ SimbadData.Count = 0;
+ SimbadData.Function = SIMBAD_CLEAR;
+
+ return (BOOLEAN)
+ NT_SUCCESS( NtDeviceIoControlFile(_handle,
+ 0,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_DISK_SIMBAD,
+ &SimbadData,
+ sizeof(SIMBAD_DATA),
+ NULL,
+ 0) );
+} // ClearBadSectors()
+
+BOOLEAN
+SimulateBadSectors(
+ HANDLE _handle,
+ BOOLEAN Add,
+ ULONG Count,
+ PLBN SectorArray,
+ NTSTATUS Status,
+ ULONG AccessType
+ )
+/*++
+
+Routine Description:
+
+ This function adds sectors to or removes sectors from the
+ bad sector simulation list.
+
+Arguments:
+
+ Add -- supplies a flag indicating whether to add (TRUE)
+ or remove (FALSE) sectors
+ Count -- supplies the number of sectors in the sector array
+ SectorArray -- supplies the array of sectors to mark as bad.
+ (May be NULL if Count is zero.)
+ Status -- supplies the status to associate with these sectors.
+ AccessType -- supplies the type of access that will trigger the error
+ for all sectors in the SectorArray.
+
+Return Value:
+
+ TRUE upon successful completion.
+
+--*/
+{
+ SIMBAD_DATA SimbadData;
+ IO_STATUS_BLOCK StatusBlock;
+ ULONG i;
+
+ if( Count > MAXIMUM_SIMBAD_SECTORS ) {
+
+ return FALSE;
+
+ } // if
+
+ SimbadData.Function = Add ? SIMBAD_ADD_SECTORS : SIMBAD_REMOVE_SECTORS;
+ SimbadData.Count = Count;
+
+ for( i = 0; i < Count; i++ ) {
+
+ SimbadData.Sector[i].BlockAddress = SectorArray[i];
+ SimbadData.Sector[i].AccessType = AccessType;
+ SimbadData.Sector[i].Status = Status;
+
+ } // for
+
+ for( i = Count; i < MAXIMUM_SIMBAD_SECTORS; i++ ) {
+
+ SimbadData.Sector[i].BlockAddress = 0;
+ SimbadData.Sector[i].AccessType = 0;
+ SimbadData.Sector[i].Status = 0;
+
+ } // for
+
+ return (BOOLEAN)
+ NT_SUCCESS( NtDeviceIoControlFile(_handle,
+ 0,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_DISK_SIMBAD,
+ &SimbadData,
+ sizeof(SIMBAD_DATA),
+ NULL,
+ 0) );
+} // SimulateBadSectors()
+
+BOOLEAN
+QuerySimulatedBadSectors(
+ IN HANDLE _handle,
+ OUT PULONG Count,
+ IN ULONG MaximumLbnsInBuffer,
+ OUT PLBN SectorArray,
+ OUT PULONG AccessTypeArray
+ )
+/*++
+
+Routine Description:
+
+ This method retrieves the sectors in the bad sector simulation list.
+
+Arguments:
+
+ Count -- receives the number of returned sectors
+ MaximumLbnsInBuffer -- supplies the length of the buffer
+ SectorArray -- receives the bad sector list
+ AccessTypeArray -- receives the list of access types that trigger
+ the error.
+
+Return Value:
+
+ TRUE upon successful completion
+
+--*/
+{
+ SIMBAD_DATA SimbadData;
+ IO_STATUS_BLOCK StatusBlock;
+ ULONG ReturnedCount;
+ ULONG i;
+
+
+ SimbadData.Function = SIMBAD_LIST_BAD_SECTORS;
+
+ if( !NT_SUCCESS( NtDeviceIoControlFile(_handle,
+ 0,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_DISK_SIMBAD,
+ &SimbadData,
+ sizeof(SIMBAD_DATA),
+ &SimbadData,
+ sizeof(SIMBAD_DATA)) ) ) {
+
+ return FALSE;
+ } // if
+
+ ReturnedCount = (SimbadData.Count < MaximumLbnsInBuffer) ?
+ SimbadData.Count :
+ MaximumLbnsInBuffer;
+
+ for( i = 0; i < ReturnedCount; i++ ) {
+
+ SectorArray[i] = SimbadData.Sector[i].BlockAddress;
+ AccessTypeArray[i] = SimbadData.Sector[i].AccessType;
+
+ } // for
+
+ *Count = ReturnedCount;
+
+ return TRUE;
+} // QuerySimulatedBadSectors()
+
+//
+// HEX_DIGITS is a string used to search for hex values in the input string
+// in ReadFromFile().
+//
+#define HEX_DIGITS "0123456789abcdefABCDEF"
+
+VOID
+ReadFromFile (
+ )
+/*++
+
+Routine Description:
+
+ This routine reads the list(s) of bad sectors for 1 or more devices
+ and adds the sectors from that file.
+
+Arguments:
+
+ None; filename is set in ParseCmdArgs as a global.
+
+Return value:
+
+ None.
+
+--*/
+{
+ FILE * thefile;
+ HANDLE _handle=0;
+ ULONG count;
+ ULONG access;
+ char Buffer[MAX_DEV_NAME*8],
+ *curptr; // curptr is current location in buffer
+
+ //
+ // if able to open the filename (specified on command line), parse it
+ //
+ if(thefile=fopen(filename,"r")) {
+
+ //
+ // read until file is done
+ //
+ while (!feof(thefile)) {
+
+ //
+ // if able to read a string, parse it.
+ //
+ if(fgets(Buffer, MAX_DEV_NAME*8, thefile)) {
+
+ curptr=Buffer;
+
+ //
+ // Always start with the global access type value in case
+ // user specified an option, e.g. -x.
+ //
+
+ access = accessType;
+
+ //
+ // switch based on the beginning of the buffer
+ //
+ switch (Buffer[0]) {
+
+ //
+ // if \ is first char, Buffer is a device name
+ //
+ case '\\':
+
+ //
+ // if there is an open handle, close it.
+ //
+ if(_handle) {
+
+ NtClose(_handle);
+ _handle=0;
+
+ } // if(_handle)
+
+ //
+ // trim Buffer and use as devname for OpenDrive()
+ //
+ sscanf(Buffer, "%s", devname);
+ OpenDrive(devname, &_handle);
+ break;
+
+ //
+ // r means Buffer is a list of read-failing sectors
+ //
+ case 'r':
+ case 'R':
+
+ access |= SIMBAD_ACCESS_READ;
+ goto commonRead;
+
+ //
+ // w means Buffer is a list of write-failing sectors
+ //
+ case 'w':
+ case 'W':
+
+ access |= SIMBAD_ACCESS_WRITE;
+ goto commonRead;
+
+ //
+ // v means Buffer is a list of verify-failing sectors
+ //
+ case 'v':
+ case 'V':
+
+ access |= SIMBAD_ACCESS_VERIFY;
+ goto commonRead;
+
+ //
+ // a means Buffer is a list of verify-failing sectors
+ //
+ case 'a':
+ case 'A':
+
+ access |= SIMBAD_ACCESS_VERIFY |
+ SIMBAD_ACCESS_READ |
+ SIMBAD_ACCESS_WRITE;
+commonRead:
+ //
+ // if there is an open drive
+ //
+ if (_handle) {
+
+ count=0;
+ curptr+=2; // Move past token:
+
+ //
+ // loop until no more sectors > MAX
+ //
+ while (0 < sscanf(curptr,"%lx", &(sectors[count]))
+ && count<MAXIMUM_SIMBAD_SECTORS) {
+
+ //
+ // scan to first hex digit
+ //
+ curptr=&(curptr[strcspn(curptr,HEX_DIGITS)]);
+
+ count++;
+
+ //
+ // scan to first non hex char
+ //
+ curptr=&(curptr[strspn(curptr,HEX_DIGITS)]);
+
+ } // while
+
+ if (!SimulateBadSectors(_handle,
+ TRUE,
+ count,
+ sectors,
+ STATUS_DEVICE_DATA_ERROR,
+ access)) {
+
+ printf("Add failed \n");
+
+ } // if (!SimulateBadSectors())
+
+ } // if (_handle)
+ break;
+
+ //
+ // any other first character, do nothing
+ //
+ default:
+ ;
+ } // switch
+ } // if (fgets())
+ } // while (!feof())
+
+ //
+ // if there is an open handle at the end, close it
+ //
+ if(_handle) {
+
+ NtClose(_handle);
+
+ } // if (_handle)
+ } // if (fopen())
+} // ReadFromFile()
+
+VOID _CRTAPI1
+main (
+ IN int argc,
+ IN char * argv[]
+ )
+/*++
+
+Routine Description:
+
+ This routine is the entry point for simbad. It parses the command
+ arguments and then performs the action specified on the command line.
+ (The action and accessmode are set in SetCmdArgs()).
+
+Arguments:
+
+ argc -- supplies the number of cmd line arguments
+ argv -- supplies the array of cmd line arguments
+
+Return value:
+
+ None.
+
+--*/
+{
+ ULONG accarr[MAXIMUM_SIMBAD_SECTORS];
+ HANDLE _handle;
+ ULONG count, i;
+
+ //
+ // ParseCmdArgs and set whattodo, devname and accessmode
+ //
+ ParseCmdArgs(argc, argv);
+
+ if (whattodo==FROM_FILE) {
+
+ ReadFromFile();
+
+ } else { // NOT from file, read from stdin
+
+ //
+ // if able to open drive, perform action
+ //
+ if (OpenDrive(devname, &_handle)) {
+
+ //
+ // perform an action based on whattodo
+ //
+ switch (tolower(whattodo)) {
+
+ //
+ // LIST calls QuerySimulatedBadSectors and displays on stdout
+ //
+ case LIST:
+
+ if (!QuerySimulatedBadSectors(_handle,
+ &count,
+ MAXIMUM_SIMBAD_SECTORS,
+ sectors,
+ accarr )) {
+
+ printf("List failed %lx\n", GetLastError());
+
+ } else {
+
+ for (i=0; i<count; i++) {
+
+ printf("Sector: %lx\tAccess: %lx\n",
+ sectors[i],
+ accarr[i] );
+
+ } // for
+ } // if
+ break;
+
+ //
+ // ADD gets a list of sectors from InputSectorList and adds them
+ //
+ case ADD_ALL:
+
+ count=0;
+ InputSectorList(sectors, &count);
+
+ if (!SimulateBadSectors(_handle,
+ TRUE,
+ count,
+ sectors,
+ STATUS_DEVICE_DATA_ERROR,
+ accessType )) {
+
+ printf("Unable to add sectors to %s (%lx)\n",
+ devname,
+ GetLastError());
+
+ } // if
+ break;
+
+ //
+ // ORPHAN causes the partition to return DEVICE_FAILUR
+ //
+ case ORPHAN:
+
+ if (!OrphanDisk(_handle)) {
+
+ printf ("Orphan disk on %s failed (%lx)\n",
+ devname,
+ GetLastError());
+
+ } // if
+ break;
+
+
+ //
+ // ENABLE turns on the bad sector simulation
+ //
+ case ENABLE:
+
+ if (!EnableBadSectorSimulation(_handle, TRUE)) {
+
+ printf("Enable bad sectors on %s failed (%lx)\n",
+ devname,
+ GetLastError());
+ } // if
+ break;
+
+ //
+ // DISABLE turns off the bad sector simulation
+ //
+ case DISABLE:
+
+ if (!EnableBadSectorSimulation(_handle, FALSE)) {
+
+ printf("Disable bad sectors on %s failed %lx\n",
+ devname,
+ GetLastError());
+
+ } // if
+ break;
+
+ //
+ // CLEAR clears bad sector list in driver
+ //
+ case CLEAR:
+
+ if (!ClearBadSectors(_handle)) {
+
+ printf("Clear bad sectors on %s failed %lx\n",
+ devname,
+ GetLastError());
+ } // if
+ break;
+
+ //
+ // RANDOM causes the partition to drop writes randomly
+ //
+ case RANDOM:
+
+ if (!RandomWriteFailure(_handle )) {
+
+ printf ("RandomWriteFailure disk on %s failed (%lx)\n",
+ devname,
+ GetLastError());
+
+ } // if
+ break;
+
+ //
+ // BUGCHECK sets up the system for bug check
+ //
+
+ case BUGCHECK:
+ if (!BugCheckOrResetTheSystem(_handle, SIMBAD_BUG_CHECK)){
+ printf ("BugCheckTheSystem function failed.\n");
+ } // if
+ break;
+
+ //
+ // FIRMWARE_RESET setup for firmware reset when enabled.
+ //
+
+ case FIRMWARE_RESET:
+ if (!BugCheckOrResetTheSystem(_handle, SIMBAD_FIRMWARE_RESET)){
+ printf ("ResetTheSystem function failed.\n");
+ } // if
+ break;
+
+ // any other action, just close the handle and show usage
+ //
+
+ default:
+
+ NtClose(_handle);
+ ShowUsage();
+
+ } // switch (whattodo)
+
+
+ NtClose(_handle);
+ } else {
+
+ printf("Open %s failed %lx\n", devname, GetLastError());
+
+ } // if (OpenDrive())
+ } // if (whattodo==FROM_FILE)
+} // main()
diff --git a/private/sdktools/simbad/sources b/private/sdktools/simbad/sources
new file mode 100644
index 000000000..e26e7c025
--- /dev/null
+++ b/private/sdktools/simbad/sources
@@ -0,0 +1,28 @@
+MAJORCOMP=disktools
+MINORCOMP=simbad
+
+TARGETNAME=simbad
+TARGETPATH=obj
+TARGETTYPE=UMAPPL_NOLIB
+
+SOURCES=
+
+!IFDEF NTDEBUG
+!IFDEF NOMEMLEAK
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX -DDBG=1 -DUNICODE=1
+!ELSE
+!IFDEF STACK_TRACE
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX -DDBG=1 -DMEMLEAK -DSTACK_TRACE -DUNICODE=1
+!ELSE
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX -DDBG=1 -DMEMLEAK -DUNICODE=1
+!ENDIF
+!ENDIF
+!ELSE # NTDEBUG
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX -DDBG=0 -DUNICODE=1
+!ENDIF # NTDEBUG
+
+UMLIBS=$(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+UMTYPE=console
+
+UMAPPL=simbad