summaryrefslogtreecommitdiffstats
path: root/private/sdktools/damage
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/sdktools/damage
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/sdktools/damage')
-rw-r--r--private/sdktools/damage/acl.h258
-rw-r--r--private/sdktools/damage/cdib.h260
-rw-r--r--private/sdktools/damage/cmd.c1762
-rw-r--r--private/sdktools/damage/codepage.h192
-rw-r--r--private/sdktools/damage/const.h201
-rw-r--r--private/sdktools/damage/damage.c218
-rw-r--r--private/sdktools/damage/defs.h260
-rw-r--r--private/sdktools/damage/dir.h138
-rw-r--r--private/sdktools/damage/display.c724
-rw-r--r--private/sdktools/damage/fnode.h183
-rw-r--r--private/sdktools/damage/glb.c468
-rw-r--r--private/sdktools/damage/globals.h85
-rw-r--r--private/sdktools/damage/io.c612
-rw-r--r--private/sdktools/damage/log.c55
-rw-r--r--private/sdktools/damage/makefile6
-rw-r--r--private/sdktools/damage/map.c283
-rw-r--r--private/sdktools/damage/sources60
-rw-r--r--private/sdktools/damage/superb.h243
-rw-r--r--private/sdktools/damage/types.h216
19 files changed, 6224 insertions, 0 deletions
diff --git a/private/sdktools/damage/acl.h b/private/sdktools/damage/acl.h
new file mode 100644
index 000000000..a73485c5d
--- /dev/null
+++ b/private/sdktools/damage/acl.h
@@ -0,0 +1,258 @@
+/********************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1987-1990 **/
+/********************************************************************/
+/** ACL.H - ACL Definitions
+ *
+ * ACL information is stored on a per file and per directory basis.
+ * In order to speed access, the first few ACL entries are stored
+ * in the directory.
+ *
+ */
+
+
+/** ACE field definitions
+ *
+ * 4 bytes
+ *
+ * 0: xxxx xxxx ACE type specific
+ *
+ * 1: x Inherit-only
+ * xxx ACE type
+ * xxxx ACE type specific
+ *
+ * 2: xxxx xxxx ACE specific
+ *
+ * 3: xxx ACE inheritance flags
+ * x xxxx ACE specific
+ */
+
+/* NOTE: the ACE type mask includes the "inherit-only" flag so that
+ * the AVR will automatically ignore inherit-only ACEs without requiring
+ * additional tests.
+ */
+#define ACE_TYPE_MSK 0x0000f000 /* type mask */
+#define ACE_TYPE_AA 0x00000000 /* access allowed */
+#define ACE_TYPE_AD 0x00002000 /* access denied */
+#define ACE_TYPE_SA 0x00004000 /* system audit */
+#define ACE_TYPE_SM 0x00006000 /* system alarm */
+
+#define ACE_TYPE_IHO 0x00008000 /* Inherit Only flag */
+
+#define ACE_IF_OI 0x80000000 /* Object Inherit */
+#define ACE_IF_CI 0x40000000 /* Container Inherit */
+#define ACE_IF_NPI 0x20000000 /* No propigate inherit */
+
+/* Access Allowed ACE Type (also Access Denied ACE)
+ *
+ * 4 bytes
+ *
+ * 0: xxxx xxxx small ID
+ *
+ * 1: x Inherit-only
+ * xxx ACE type
+ * xxxx reserved (used by AUDIT/ALARM ACE's)
+ *
+ * 2: xxxx xxxx specific access field
+ *
+ * 3: xxx ACE inheritance flags
+ * x xxx Standard Access field
+ * x specific access field
+ */
+
+/* Access Allowed Standard Access */
+
+#define ACE_AAST_DEL 0x10000000 /* Delete access */
+#define ACE_AAST_RCTL 0x08000000 /* read ACL */
+#define ACE_AAST_WDAC 0x04000000 /* write ACL */
+#define ACE_AAST_WOWN 0x02000000 /* write owner (chown) */
+
+/* Access ALlowed Specific Access */
+
+#define ACE_AASP_RDAT 0x00010000 /* Read Data FILES */
+#define ACE_AASP_WDAT 0x00020000 /* Write Data */
+#define ACE_AASP_ADAT 0x00040000 /* Append Data */
+#define ACE_AASP_REA 0x00080000 /* Read EA */
+#define ACE_AASP_WEA 0x00100000 /* Write EA */
+#define ACE_AASP_EXE 0x00200000 /* Execute */
+ /* 0x00400000 /* reserved */
+#define ACE_AASP_RATR 0x00800000 /* read DOS attribute */
+#define ACE_AASP_WATR 0x01000000 /* write DOS attribute */
+
+#define ACE_AASP_LDIR 0x00010000 /* list dir DIRs */
+#define ACE_AASP_ADDF 0x00020000 /* add file */
+#define ACE_AASP_ADDS 0x00040000 /* mkdir */
+#define ACE_AASP_REA 0x00080000 /* Read EA */
+#define ACE_AASP_WEA 0x00100000 /* Write EA */
+#define ACE_AASP_TRAV 0x00200000 /* traverse */
+#define ACE_AASP_CHDEL 0x00400000 /* child delete */
+#define ACE_AASP_RATR 0x00800000 /* read DOS attribute */
+#define ACE_AASP_WATR 0x01000000 /* write DOS attribute */
+
+/*
+ * Sytem Audit ACEs
+ *
+ * System audit ACEs are identical to Access Allowed ACEs
+ * with the addition of the 2 flags defined below, located
+ * in Byte 1.
+ */
+
+#define ACE_SA_AAFLAGS 0x00000300
+
+#define ACE_SAAF_SUCC 0x00000100 /* Audit successful access attempts */
+#define ACE_SAAF_FAIL 0x00000200 /* Audit failed access attempts */
+
+
+/* Short hand codes used internally in pinball (never stored on disk)
+ *
+ * These codes are passed to FindDir to indicate the kind of directory
+ * permission needed.
+ */
+
+#define ACESD_TRAV 0 /* traverse directory */
+#define ACESD_LIST 1 /* index directory */
+#define ACESD_MKDIR 2 /* create subdirectory */
+#define ACESD_MAX 3 /* valid codes < 3 */
+
+/* These codes are passed to OPEN_ by filesystem-internal callers
+ * to indicate special ACL checks. Must be non-zero.
+ */
+
+#define ACEOP_RACL 1 /* read ACLs */
+#define ACEOP_WACL 2 /* write ACLs */
+#define ACEOP_REA 3 /* read EAs */
+#define ACEOP_WEA 4 /* write EAs */
+
+#define ACEOP_NOAUDIT 8 /* suppress auditing when OR'd with above codes */
+
+
+/** SID Mapping Table
+ *
+ * In order to save room, some ACL records have a one byte short
+ * ID field in place of the 16 byte long ID field. The short ID
+ * field is used to index a per-volume mapping table to get the
+ * long ID field. To facilitiate translating long IDs into short
+ * ones, the mapping table of 255 16-byte entrys is split up into
+ * 255 dword entries - the first (most volitile) dword of each
+ * ID, followed by 255 12-byte entries which contains, in an identical
+ * order, the remaining 12 bytes. This allows us to do a SCASD
+ * lookup of ACL values.
+ *
+ */
+
+/* Small ID special values */
+
+#define ACE_SMID_FULL 0 /* ACE is followed by full 16 byte ID */
+
+#define RESV_SID 7 /* SID values 0 through 7 reserved */
+#define SID_WORLD 7 /* Last reserved SID is WORLD ID */
+
+#define SIDTABSIZ 249 /* SID table size (248 + WORLD) */
+#define SIDSECCNT 8 /* SIDTAB is 8 sectors */
+
+struct SIDTAB {
+ long SID_CNT; /* # of active entries */
+ long SID_1ST[SIDTABSIZ]; /* first dwords of the values. */
+ char SID_REM[SIDTABSIZ*12]; /* remaining 12 bytes */
+}; /* SIDTAB */
+
+
+/** World Identifier
+ *
+ * CODEWORK - Use real WID when its determined
+ */
+
+#define WORLD_ID0 0xFAFAFFFF
+#define WORLD_ID1 0x0000FAFA
+#define WORLD_ID2 0x00000000
+#define WORLD_ID3 0x00000000
+
+
+/** AVR work structure format
+ *
+ */
+
+struct avr_work {
+ unsigned long avr_remain; /* permission remaining to be aquired */
+ unsigned long avr_need; /* permission needed */
+ struct SIDTAB *avr_mapptr; /* ptr to short ID to GUID map table */
+ struct user_cache *avr_userinfo;/* ptr to user_cache struct (this is the */
+ /* "user descriptor" passed to the file */
+ /* system in ESI on path based calls) */
+ unsigned char avr_audit; /* != 0 if an audit ACE has been seen */
+ unsigned char avr_rsvd[3]; /* pad out to dword size */
+}; /* avr_work */
+
+
+/** Perm list Format
+ *
+ */
+
+struct PERM_LIST {
+ long pl_access; /* permission mask */
+ char pl_id[16]; /* GUID */
+}; /* PERM_LIST */
+
+struct SPERM_LIST { /* short perm list */
+ long spl_access; /* permission mask & id */
+}; /* SPERM_LIST */
+
+
+
+/* Access Control Masks
+ *
+ * These are DD values which are passed to the ACL verifier
+ * for particular operations
+ */
+
+/* permissions needed in a directory to: */
+
+ /* permission needed in directory to */
+ /* access something within it */
+#define ACB_TRAV ACE_AASP_TRAV
+
+ /* permission needed in a directory to */
+ /* list (find) a file within it */
+#define ACB_LIST ACE_AASP_LDIR
+
+#define ACB_CREF ACE_AASP_ADDF /* create file */
+#define ACB_CRED ACE_AASP_ADDS /* create directory */
+#define ACB_CREDF (ACE_AASP_ADDS OR ACE_AASP_ADDF)
+ /* create file or directory - used now because
+ * LANMAN doesn't set these seperately. This
+ * can be CREF or CRED; must fix when API
+ * exposes more function
+ */
+#define ACB_DELDIR ACE_AAST_DEL /* delete directory itself */
+#define ACB_DELCHLD ACE_AASP_CHDEL /* delete child directory */
+
+
+/* Permissions on a file */
+
+#define ACB_FREAD ACE_AASP_RDAT /* open for read */
+#define ACB_FWRITE ACE_AASP_WDAT /* open for write */
+ /* open for read & write */
+#define ACB_FREADWRITE (ACE_AASP_RDAT OR ACE_AASP_WDAT)
+#define ACB_EXEC ACE_AASP_EXE /* open for exec */
+#define ACB_RACL ACE_AAST_RCTL /* read ACL */
+#define ACB_WACL ACE_AAST_WDAC /* write ACL */
+#define ACB_REA ACE_AASP_REA /* read EA */
+#define ACB_WEA ACE_AASP_WEA /* write EA */
+#define ACB_DELETE ACE_AAST_DEL /* file delete */
+#define ACB_RATTR ACE_AASP_RATR /* read attributes */
+#define ACB_WATTR ACE_AASP_WATR /* write attributes */
+#define ACB_NONE 0 /* no permissions needed */
+
+
+/*
+ * LANMAN permission masks
+ */
+
+#define LM_READ 0x1
+#define LM_WRITE 0x2
+#define LM_CREATE 0x4
+#define LM_EXEC 0x8
+#define LM_DELETE 0x10
+#define LM_ATTR 0x20
+#define LM_PERM 0x40
+
diff --git a/private/sdktools/damage/cdib.h b/private/sdktools/damage/cdib.h
new file mode 100644
index 000000000..d3f3ee3b4
--- /dev/null
+++ b/private/sdktools/damage/cdib.h
@@ -0,0 +1,260 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1990 **/
+/*****************************************************************/
+/*static char *SCCSID = "@(#)cdib.h 12.2 88/05/09";*/
+
+/*
+ * Codepage Data Information Block
+ *
+ * 09/03/89 gregj - made h2inc'able (16-BIT H2INC ONLY!)
+ */
+
+/*
+ * Any pointer set to zero indicates that the section is nonexistent
+ */
+
+/*
+ * The following field follows the ROM resident font definitions:
+ */
+
+struct CDIB_dev_filename_section {
+char CDIB_dev_filename[128]; /* font file name */
+}; /* CDIB_dev_filename_section */
+
+/*
+ * The following 2 fields appear once for each ROM resident font:
+ */
+
+struct CDIB_dev_ROM_font_section {
+unsigned CDIB_dev_ROM_codepage; /* code page identifier */
+unsigned CDIB_dev_ROM_font; /* font identifier */
+}; /* CDIB_dev_ROM_font_section */
+
+/*
+ * Device Section
+ * This section appears once for each device (screen, keyboard,
+ * LPT1, LPT2, and LPT3) for which a DEVINFO= statement was
+ * specified in the CONFIG.SYS file
+ */
+
+struct CDIB_device_section {
+unsigned CDIB_dev_length; /* lenght of device
+ * section
+ */
+char CDIB_dev_subtype[8]; /* subtype */
+struct CDIB_dev_filename_section near *CDIB_dev_filename_ptr; /* offset to font
+ * file name
+ */
+unsigned CDIB_dev_number_ROM_fonts; /* number of ROM
+ * resident fonts
+ */
+struct CDIB_dev_ROM_font_section CDIB_dev_first_ROM_font; /* location of first
+ * ROM font section
+ * WARNING! This
+ * section may not
+ * exist, see warning
+ * for
+ * CDIB_cp_first_id
+ */
+}; /* CDIB_device_section */
+
+/*
+ * Country Section
+ * This section appears only once
+ */
+
+struct CDIB_country_section {
+unsigned CDIB_ct_length; /* length of country section */
+unsigned CDIB_ct_code; /* country code */
+char CDIB_ct_filename[128]; /* name of country information
+ * file
+ */
+}; /* CDIB_country_section */
+
+/*
+ * The following field appears once for each DBCS range:
+ */
+
+struct CDIB_DBCS_range_section {
+unsigned char CDIB_DBCS_start; /* start of range */
+unsigned char CDIB_DBCS_end; /* end of range */
+}; /* CDIB_DBCS_range_section */
+
+/*
+ * DBCS Environment Vector Section
+ * This section appears once for each prepared code page
+ */
+
+struct CDIB_DBCS_section {
+unsigned CDIB_DBCS_length; /* length of DBCS vector
+ * section
+ */
+struct CDIB_DBCS_range_section CDIB_DBCS_first_range; /* location of first DBCS
+ * range
+ */
+}; /* CDIB_DBCS_section */
+
+/*
+ * Case Map Table Section
+ * This section appears once for each prepared code page
+ */
+
+struct CDIB_casemap_section {
+unsigned CDIB_cm_length; /* length of case map section */
+char CDIB_cm_data[128]; /* upper case equivalent for each
+ * ASCII chracter from 80h to FFh
+ */
+}; /* CDIB_casemap_section */
+
+/*
+ * Collate Table Section
+ * This section appears once for each prepared code page
+ */
+
+struct CDIB_collate_section {
+unsigned CDIB_col_length; /* length of collate table section */
+unsigned char CDIB_col_weight[256]; /* weight in the collating sequence
+ * for each ASCII character
+ */
+}; /* CDIB_collate_section */
+
+/*
+ * Format Table Section
+ * This section appears once for each prepared code page
+ */
+
+struct CDIB_format_section {
+unsigned CDIB_fmt_length; /* length of format section */
+unsigned CDIB_fmt_date_format; /* date format */
+char CDIB_fmt_currency_symbol[5]; /* currency symbol, null terminated */
+char CDIB_fmt_thousands_separator[2]; /* thousands separator, null term. */
+char CDIB_fmt_decimal_separator[2]; /* decimal separator, null term. */
+char CDIB_fmt_date_separator[2]; /* date separator, null terminated */
+char CDIB_fmt_time_separator[2]; /* time separator, null terminated */
+unsigned char CDIB_fmt_currency_format; /* currency format flags
+ * .....0.0 = currency symbol
+ * preceeds money value
+ * .....0.1 = currency symbol
+ * follows money value
+ * .....00. = zero spaces between
+ * currency symbol
+ * and money value
+ * .....01. = one space between
+ * currency symbol
+ * and money value
+ * .....1.. = currency symbol
+ * replaces decimal
+ * separator
+ */
+unsigned char CDIB_fmt_decimal_places; /* # decimal places in money value */
+unsigned char CDIB_fmt_time_format; /* time format */
+unsigned long CDIB_fmt_monocase_routine; /* Monocase Routine */
+char CDIB_fmt_data_list_separator[2]; /* data list separator, null term. */
+unsigned CDIB_fmt_reserved[5]; /* reserved */
+}; /* CDIB_format_section */
+
+/*
+ * Values for CDIB_fmt_date_format (date format)
+ */
+
+#define CDIB_fmt_date_mmddyy 0 /* 0 = mm/dd/yy */
+#define CDIB_fmt_date_ddmmyy 1 /* 1 = dd/mm/yy */
+#define CDIB_fmt_date_yymmdd 2 /* 2 = yy/mm/dd */
+
+/*
+ * Values for CDIB_fmt_currency_format (currency format)
+ */
+
+#define CDIB_fmt_currency_cbm 0x05 /* currency symbol before money value,
+ * a non-zero AND test result indicates
+ * that this is not the correct flag
+ */
+#define CDIB_fmt_currency_mbc 0x01 /* currency symbol after money value,
+ * a non-zero AND test result indicates
+ * that this is the correct flag,
+ * this test should be preceeded by a
+ * zero AND test result against
+ * CDIB_fmt_currency_cbd
+ */
+#define CDIB_fmt_currency_zerosp 0x06 /* zero spaces between currency symbol
+ * and money value,
+ * a non-zero AND test result indicates
+ * that this is not the correct flag
+ */
+#define CDIB_fmt_currency_onesp 0x02 /* one space between currency symbol
+ * and money value,
+ * a non-zero AND test result indicates
+ * that this is the correct flag,
+ * this test should be preceeded by a
+ * zero AND test result against
+ * CDIB_fmt_currency_cbd
+ */
+#define CDIB_fmt_currency_currdec 0x04 /* currency symbol replaces decimal
+ * separator
+ * a non-zero AND test result indicates
+ * that this is the correct flag
+ */
+
+/*
+ * Code Page Data Section
+ * This section appears once for each prepared code page
+ */
+
+struct CDIB_codepage_data_section {
+unsigned CDIB_cpd_length; /* length of cp data sec. */
+struct CDIB_format_section near *CDIB_cpd_format_ptr; /* ptr to format section */
+struct CDIB_collate_section near *CDIB_cpd_collate_ptr; /* ptr to collate section */
+struct CDIB_casemap_section near *CDIB_cpd_casemap_ptr; /* ptr to casemap section */
+struct CDIB_DBCS_section near *CDIB_cpd_DBCS_ptr; /* ptr to DBCS vector sec.*/
+}; /* CDIB_codepage_data_section */
+
+/*
+ * The following section appears once for each prepared code page
+ */
+
+struct CDIB_cp_id_section {
+unsigned CDIB_cp_id; /* code page identifier */
+struct CDIB_codepage_data_section near *CDIB_cp_data_ptr; /* ptr to cp data sec. */
+}; /* CDIB_cp_id_section */
+
+/*
+ * Code Page Section
+ * This section appears once
+ */
+
+struct CDIB_codepage_section {
+unsigned CDIB_cp_length; /* length of code page section */
+unsigned CDIB_cp_number_codepages; /* number of prepared code pages */
+struct CDIB_cp_id_section CDIB_cp_first_id; /* location of first codepage id
+ * section. WARNING! This field
+ * may not exist; since an id
+ * section may exist with number
+ * codepages zero, check for
+ * existence by comparing cp length
+ * against size of codepage section
+ * if cp length < size, first id is
+ * not present
+ */
+}; /* CDIB_codepage_section */
+
+/*
+ * Base Section
+ *
+ * This Section appears once, at offset 0 of the CDIB segment
+ *
+ * Changed pointers to explicit near, so can use this file with
+ * large memory model.
+ */
+
+struct CDIB {
+unsigned CDIB_length; /* length of the CDIB */
+struct CDIB_codepage_section near *CDIB_codepage_ptr; /* offset to code page sec. */
+struct CDIB_country_section near *CDIB_country_ptr; /* offset to country sec. */
+struct CDIB_device_section near *CDIB_screen_ptr; /* offset to screen section */
+struct CDIB_device_section near *CDIB_keyboard_ptr; /* offset to kbd section */
+struct CDIB_device_section near *CDIB_lpt1_ptr; /* offset to LPT1 section */
+struct CDIB_device_section near *CDIB_lpt2_ptr; /* offset to LPT2 section */
+struct CDIB_device_section near *CDIB_lpt3_ptr; /* offset to LPT3 section */
+}; /* CDIB */
+
diff --git a/private/sdktools/damage/cmd.c b/private/sdktools/damage/cmd.c
new file mode 100644
index 000000000..459afb4ec
--- /dev/null
+++ b/private/sdktools/damage/cmd.c
@@ -0,0 +1,1762 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1990 **/
+/*****************************************************************/
+/*** CMD.C - Routines to get and process commands.
+ *
+ * DAMAGE
+ * Gregory A. Jones
+ *
+ * Modification history:
+ * G.A. Jones 09/07/88 Original for Pinball testing.
+ * G.A. Jones 09/08/88 Coded initial commands.
+ * G.A. Jones 09/09/88 Coded D, N, P, B cmds.
+ * G.A. Jones 09/09/88 Moved from DISPLAY.C.
+ * G.A. Jones 09/12/88 Added support for DIRBLKs.
+ * G.A. Jones 09/13/88 Added bitmap displays.
+ * G.A. Jones 09/13/88 Added data and pathname support.
+ * G.A. Jones 09/14/88 Added Help command.
+ * G.A. Jones 09/19/88 Removed DIR_UID, DIR_UPRM, etc.
+ * G.A. Jones 09/19/88 Added Change, Revert commands.
+ * G.A. Jones 09/20/88 Can change dates as ASCII, not time_t.
+ * G.A. Jones 09/21/88 Added hotfix list displays.
+ * G.A. Jones 10/12/88 Moved ATIM, CTIM from FNODE to DIRENT.
+ * G.A. Jones 10/19/88 Added dirblk banding support.
+ * G.A. Jones 10/21/88 Added ALSEC support.
+ * G.A. Jones 10/27/88 Added Copy command.
+ * S. Hern 02/06/89 Added ability to change the contents
+ * of an EA block and data block
+ * S. Hern 03/28/89 Added ability to change other that first
+ * character of DIR_NAMA for DIRENT
+ * S. Hern 04/20/89 Allow either redirection for input
+ * davidbro 04/20/89 changed /r redirection behavior
+ * S. Hern 04/25/89 Changed 13 to 12 to support FNODE
+ * field changes in functions "displayable"
+ * and "new_currobj"
+ * davidbro 05/21/89 added "mark_as_bad" and the M)ark
+ * command.
+ * davidbro 05/22/89 added L)og command
+ * davidbro 05/23/89 added U)nmark command
+ * P.A. Williams 05/31/89 Made sure didn't display off end of
+ * spare block for bad SPB_SDBMAX field
+ * S.A.Hern 06/22/89 Essentially more of what is listed above
+ * under the 4/25/89 change
+ * S.A.Hern 06/28/89 To new_currobj made assignment to
+ * filesize to account for EA data runs
+ * (used by next_field and previous_field)
+ * Fixed item + offset so that allocation
+ * sector data runs can be accessed.
+ * S.A.Hern 08/22/89 Fixed allocation sector data display
+ * (new_currobj "sec" and "len" fields if
+ * TYPE_ALSEC). Set "filesize" using
+ * FN_VLEN in new_currobj if TYPE_FNODE).
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "defs.h"
+#include "types.h"
+#include "globals.h"
+//#include <lw.h>
+
+
+
+/*** getcmdch - get a character and display corresponding command
+ *
+ * This function waits for a keystroke from the user. If the
+ * keystroke is a valid command, the corresponding command word
+ * (e.g. "Display") is printed and the character is returned.
+ * Otherwise zero is returned.
+ *
+ * getcmdch ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT Returns command character or zero if invalid
+ *
+ * CALLS log_getch
+ * printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS Waits for a character
+ */
+UCHAR getcmdch ()
+{
+ UCHAR ch;
+
+ ch = log_getch ();
+ switch (ch) {
+ case 'D': case 'd': printf ("Display\n"); return (ch);
+ case 'C': case 'c':
+ if (change) {
+ printf ("Change\n"); return (ch);
+ }
+ else return (0);
+ case 'R': case 'r':
+ if (change) {
+ printf ("Revert\n"); return (ch);
+ }
+ else return (0);
+ case 'O': case 'o':
+ if (change) {
+ printf ("Copy\n"); return (ch);
+ }
+ else return (0);
+ case 'F': case 'f':
+ if (change) {
+ printf ("Fence\n"); return (ch);
+ }
+ else return (0);
+ case 'M': case 'm':
+ if (change) {
+ printf("Mark as bad\n"); return (ch);
+ }
+ else return (0);
+ case 'U': case 'u':
+ if (change) {
+ printf("Unmark sector\n"); return (ch);
+ }
+ else return (0);
+ case 'L': case 'l':
+ if (szLogFile != NULL) {
+ printf ("Log\n"); return (ch);
+ }
+ else return (0);
+ case 'B': case 'b': printf ("Backout\n"); return (ch);
+ case 'N': case 'n': printf ("Next\n"); return (ch);
+ case 'P': case 'p': printf ("Previous\n"); return (ch);
+ case 'Q': case 'q': printf ("Quit\n"); return (ch);
+ case 'H': case 'h': case '?': printf ("Help\n"); return (ch);
+ default: return (0);
+ }
+}
+
+/*** new_currobj - build currobj from an item
+ *
+ * This function is called to "push into" an item in an object.
+ * It is passed the item number within the current object. That
+ * item is guaranteed to be "pushable"; for example, this function
+ * will never be asked to build a new currobj for the signature
+ * on an FNODE.
+ *
+ * The fields in an object are basically numbered from the top,
+ * starting with 1. So, for example, item 1 in the super block
+ * is SB_SIG1, etc.
+ *
+ * This function sets the "sec" and "len" fields in currobj to
+ * reflect the address and size of the desired object. Get_object
+ * is then called to read that object.
+ *
+ * The caller should push the old object onto the stack before
+ * calling new_currobj, since the contents of currobj are changed.
+ *
+ * new_currobj (item)
+ *
+ * ENTRY item - field number to push into
+ *
+ * EXIT No return value
+ * currobj filled in with new item
+ *
+ * CALLS get_object
+ *
+ * WARNINGS Do not call with a non-pushable item like a sig.
+ *
+ * EFFECTS Allocates memory
+ * Reads disk
+ */
+void new_currobj( USHORT item )
+{
+#ifdef TRACE
+ fprintf (stderr, "new_currobj (%d)\n", item);
+ fflush (stderr);
+#endif
+
+ switch (currobj.type) {
+ case TYPE_SUPERB:
+ {
+ struct SuperSpare *s = currobj.mem;
+ if (currobj.offset == FIELDOFFSET (struct SuperSpare, spb)) {
+ if (item == iSPB_HFSEC) {
+ currobj.type = TYPE_HFSEC;
+ currobj.sec = s->spb.SPB_HFSEC;
+ currobj.len = SECTORS_PER_BLOCK;
+ currobj.mem = NULL;
+ get_object ();
+ }
+#ifdef CODEPAGE
+ else if (item == iSPB_CPSEC) {
+ currobj.type = TYPE_CPSEC;
+ currobj.sec = s->spb.SPB_CPSEC;
+ currobj.len = SECTORS_PER_CODEPAGE;
+ currobj.mem = NULL;
+ get_object ();
+ }
+#endif
+ }
+ else {
+ if (item == iSB_ROOT) {
+ currobj.type = TYPE_FNODE;
+ currobj.sec = s->sb.SB_ROOT;
+ currobj.len = SECTORS_PER_FNODE;
+ currobj.mem = NULL;
+ get_object ();
+ }
+ else if (item == iSB_BII_P) {
+ currobj.type = TYPE_BII;
+ currobj.sec = s->sb.SB_BII.P;
+ currobj.len = SECTORS_PER_BLOCK;
+ currobj.mem = NULL;
+ get_object ();
+ }
+ else if (item == iSB_BBL_P) {
+ currobj.type = TYPE_BBL;
+ currobj.sec = s->sb.SB_BBL.P;
+ currobj.len = SECTORS_PER_BLOCK;
+ currobj.mem = NULL;
+ get_object ();
+ currobj.offset = 4;
+ }
+ else if (item == iSB_DBMAP) {
+ currobj.type = TYPE_DBBIT;
+ currobj.sec = s->sb.SB_DBMAP;
+ currobj.len = 2L;
+ currobj.mem = NULL;
+ get_object ();
+ }
+ }
+ }
+ break;
+ case TYPE_FNODE:
+ {
+ struct FNODE *f = currobj.mem;
+ ULONG *l = (ULONG *)f->FN_ALREC;
+
+#ifndef CODEPAGE
+ if (!currobj.offset && (item == 12) && f->FN_EaDiskLength) {
+#else
+ if (!currobj.offset && (item == iFN_EA_AI_SEC) && f->FN_EaDiskLength) {
+#endif
+ currobj.sec = f->FN_EaSector;
+ if (f->FN_EaDataFlag) {
+ currobj.type = TYPE_ALSEC;
+ currobj.len = SECTORS_PER_AB;
+ filesize = f->FN_EaDiskLength;
+ }
+ else {
+ currobj.type = TYPE_DATA;
+ currobj.len = (f->FN_EaDiskLength - 1) / 512L + 1;
+ filesize = f->FN_VLEN;
+ }
+ currobj.mem = NULL;
+ currobj.scratch = 0;
+ get_object ();
+ }
+ else if ((item == 3) && f->FN_ALREC [0].AL_POF && !f->FN_ALREC [0].AL_LEN) {
+ currobj.type = TYPE_DIRBLK;
+ currobj.sec = f->FN_ALREC [0].AL_POF;
+ currobj.len = SECTORS_PER_DIRBLK;
+ currobj.mem = NULL;
+ get_object ();
+ currobj.offset = FIELDOFFSET (struct DIRBLK, DB_START);
+ }
+ else if (f->FN_AB.AB_FLAG & ABF_NODE) {
+ currobj.type = TYPE_ALSEC;
+ currobj.sec = *(l+item-1);
+ currobj.len = SECTORS_PER_AB;
+ currobj.mem = NULL;
+ get_object ();
+ }
+ else {
+ currobj.type = TYPE_DATA;
+ currobj.sec = f->FN_ALREC [item / 3 - 1].AL_POF;
+ currobj.len = f->FN_ALREC [item / 3 - 1].AL_LEN;
+ currobj.mem = NULL;
+ currobj.scratch = 0;
+ get_object ();
+ }
+ }
+ break;
+ case TYPE_ALSEC:
+ {
+ struct ALSEC *a = currobj.mem;
+ ULONG *l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
+
+ if (a->AS_ALBLK.AB_FLAG & ABF_NODE) {
+ currobj.type = TYPE_ALSEC;
+ currobj.sec = *(l+item-1);
+ currobj.len = SECTORS_PER_AB;
+ currobj.mem = NULL;
+ get_object ();
+ }
+ else {
+ currobj.type = TYPE_DATA;
+ currobj.sec = *(l + (item / 3) - 1 + 2);
+ currobj.len = *(l + (item / 3) - 1 + 3);
+ currobj.mem = NULL;
+ currobj.scratch = 0;
+ get_object ();
+ }
+ }
+ break;
+ case TYPE_DIRBLK:
+ {
+ struct DIRBLK *d = currobj.mem;
+ union dp dp;
+
+ dp.p = (UCHAR *)currobj.mem + currobj.offset;
+ if (item == 8) {
+ filesize = dp.d->DIR_SIZE;
+ strcat (curpath, "\\");
+ strncat (curpath, &dp.d->DIR_NAMA, dp.d->DIR_NAML);
+ currobj.type = TYPE_FNODE;
+ currobj.sec = dp.d->DIR_FN;
+ currobj.len = SECTORS_PER_FNODE;
+ currobj.mem = NULL;
+ get_object ();
+ }
+#ifndef CODEPAGE
+ else if (item == 16) {
+#else
+ else if (item == iDIR_BTP) {
+#endif
+ currobj.type = TYPE_DIRBLK;
+ currobj.sec = DOWN_PTR (dp);
+ currobj.len = SECTORS_PER_DIRBLK;
+ currobj.mem = NULL;
+ get_object ();
+ currobj.offset = FIELDOFFSET (struct DIRBLK, DB_START);
+ }
+ }
+ break;
+ case TYPE_BII:
+ {
+ ULONG *l;
+
+ l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
+ currobj.type = TYPE_BITMAP;
+ currobj.sec = *(l + (item - 1)); /* items 1-100-->offsets 0-99 */
+ currobj.len = SECTORS_PER_BLOCK;
+ currobj.mem = NULL;
+ currobj.scratch = currobj.offset / 4 + item - 1;
+ get_object ();
+ }
+ break;
+ case TYPE_BBL:
+ currobj.sec = *(ULONG *)currobj.mem;
+ currobj.mem = NULL;
+ get_object ();
+ currobj.offset = 4;
+ break;
+ case TYPE_HFSEC:
+ {
+ ULONG *l;
+
+ l = ((ULONG *)currobj.mem) + currobj.offset + (item-1)/3;
+ if (!(item % 3)) { /* containing FNODE */
+ currobj.type = TYPE_FNODE;
+ currobj.sec = *(l + 2*hfmax); /* fetch from third array */
+ currobj.len = SECTORS_PER_FNODE;
+ currobj.mem = NULL;
+ get_object ();
+ break;
+ }
+ else if ((item % 3) == 1)
+ currobj.sec = *(l + hfmax);
+ else
+ currobj.sec = *l;
+ currobj.type = TYPE_DATA;
+ currobj.len = SECTORS_PER_BLOCK;
+ currobj.mem = NULL;
+ currobj.scratch = 0;
+ get_object ();
+ filesize = SECTORS_PER_BLOCK * BYTES_PER_SECTOR;
+ }
+ break;
+#ifdef CODEPAGE
+ case TYPE_CPSEC:
+ if (currobj.offset == FIELDOFFSET (CPINFOSEC, CP_INFO[0])) {
+
+ if (((item-iCPI_DATASEC) % iCPI_RNGECNT) == 0) {
+ currobj.type = TYPE_CPDATA;
+ currobj.scratch = (item-iCPI_DATASEC)/iCPI_RNGECNT;
+ currobj.sec = ((PCPINFOSEC)currobj.mem)->CP_INFO[currobj.scratch].CPI_DATASEC;
+ currobj.len = SECTORS_PER_CODEPAGE;
+ currobj.mem = NULL;
+ get_object ();
+ }
+ }
+ else {
+ currobj.type = TYPE_CPSEC;
+ currobj.sec = ((PCPINFOSEC)currobj.mem)->CP_NEXTSEC;
+ currobj.len = SECTORS_PER_CODEPAGE;
+ currobj.mem = NULL;
+ get_object ();
+ }
+ break;
+#endif
+ default: break;
+ }
+}
+
+/*** fence_bits - fence bits in a bit map
+ *
+ * This function is called to "fence" the bits in a bit map. This
+ * is done by ANDing every byte in the bitmap with 10101010b,
+ * effectively allocating every other sector. This tends to cause
+ * the file system to create allocation sector trees quickly, since
+ * it cannot allocate a run longer than one sector.
+ *
+ * This function only works if the current item is a bitmap. The
+ * bitmap is updated on disk immediately.
+ *
+ * fence_bits ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT No return value
+ * Current bitmap block fenced
+ *
+ * CALLS None
+ *
+ * WARNINGS None
+ *
+ * EFFECTS Changes global bitmap on disk
+ */
+void fence_bits ()
+{
+ register USHORT i;
+ UCHAR c;
+
+#ifdef TRACE
+ fprintf (stderr, "fence_bits ()\n");
+ fflush (stderr);
+#endif
+
+ if (currobj.type != TYPE_BITMAP) {
+ printf ("Cannot fence this object.\n");
+ return;
+ }
+
+ printf ("Really fence this bitmap (Y/N) [N]: ");
+ do {
+ c = log_getch ();
+ c = toupper (c);
+ } while ((c != 'N') && (c != 'Y'));
+ printf ("%c\n", c);
+ if (c == 'N')
+ printf ("Bitmap not changed.\n");
+ else {
+ for (i=0; i<SPB * SECSIZE; i++)
+ ((UCHAR *)currobj.mem) [i] &= 0xaa; /* mask bits */
+ write_scratch (currobj.sec, currobj.mem, SPB); /* save bitmap */
+ }
+ printf ("Bitmap fenced.\n");
+}
+
+/*** mark_as_bad - queue the item in the list of bad sectors.
+ *
+ * Adds the requested field to the list of sectors to be marked as bad.
+ * If the addition fills the list, set fBadListFull.
+ *
+ * ENTRY item - field number to add to bad sector list.
+ *
+ * EXIT item added, fBadListFull set if list is now full.
+ *
+ * CALLS
+ *
+ * WARNINGS item must be the item number of a field that contains
+ * a LSN.
+ *
+ * EFFECTS sectors are marked bad after DAMAGE has closed the
+ * disk.
+ */
+
+#define RM_PATH 2 /* Route via pathname */
+
+void
+mark_as_bad (USHORT item, ULONG ulMask)
+{
+ printf( "ERROR: mark_as_bad not supported.\n" );
+}
+
+/*** displayable - determine if an object is "pushable"
+ *
+ * This function is called to determine if a field in an object can
+ * be "pushed into". This includes data runs as well as other
+ * control structures on the disk, but excludes things like signatures.
+ * This function should be called before calling new_currobj().
+ *
+ * BUGBUG - is this sucker the same as allocatable()?
+ *
+ * displayable (item)
+ *
+ * ENTRY item - field number to analyze
+ *
+ * EXIT Returns TRUE if item displayable, FALSE otherwise
+ *
+ * CALLS None
+ *
+ * WARNINGS None
+ *
+ * EFFECTS None
+ */
+USHORT displayable (USHORT item)
+{
+ union dp dp;
+
+#ifdef TRACE
+ fprintf (stderr, "displayable (%d)\n", item);
+ fflush (stderr);
+#endif
+
+ switch (currobj.type) {
+ case TYPE_SUPERB:
+ if (currobj.offset)
+#ifndef CODEPAGE
+ return (item == 4);
+#else
+ return ((item == iSPB_HFSEC) || (item == iSPB_CPSEC));
+#endif
+ else
+ return ((item == iSB_ROOT) || (item == iSB_BII_P)
+ || (item == iSB_BBL_P) || (item == iSB_DBMAP));
+ break;
+ case TYPE_FNODE:
+ if (currobj.offset == FIELDOFFSET (struct FNODE, FN_ALREC [0]))
+ if (((struct FNODE *)currobj.mem)->FN_AB.AB_FLAG & ABF_NODE)
+ return ((item % 2) == 0);
+ else
+ return ((item % 3) == 0);
+ else if (!currobj.offset)
+#ifndef CODEPAGE
+ return (item == 12);
+#else
+ return (item == iFN_EA_AI_SEC);
+#endif
+ else
+ return (FALSE);
+ break;
+ case TYPE_ALSEC:
+ if (currobj.offset)
+ if (((struct ALSEC *)currobj.mem)->AS_ALBLK.AB_FLAG & ABF_NODE)
+ return ((item % 2) == 0);
+ else
+ return ((item % 3) == 0);
+ else
+ return (FALSE);
+ case TYPE_DIRBLK:
+ dp.p = (UCHAR *)currobj.mem + currobj.offset;
+ if ((item == 8) && !(dp.d->DIR_FLAG & DF_END))
+ return (TRUE);
+#ifndef CODEPAGE
+ else if ((item == 16) && (dp.d->DIR_FLAG & DF_BTP))
+#else
+ else if ((item == iDIR_BTP) && (dp.d->DIR_FLAG & DF_BTP))
+#endif
+ return (TRUE);
+ else
+ return (FALSE);
+ break;
+ case TYPE_BII:
+ if ((2048 - currobj.offset) < 400)
+ return ((item > 0) && (item <= ((2048 - currobj.offset) / 4)));
+ else
+ return ((item > 0) && (item <= 100));
+ break;
+ case TYPE_BBL:
+ return (item == 1);
+ break;
+ case TYPE_HFSEC:
+ return ((item > 0) && (item <= 60));
+ break;
+#ifdef CODEPAGE
+ case TYPE_CPSEC:
+ if (currobj.offset == FIELDOFFSET (CPINFOSEC, CP_INFO[0]))
+ return (((item-iCPI_DATASEC) % iCPI_RNGECNT) == 0);
+ else
+ return (item == iCP_NEXTSEC);
+ break;
+ case TYPE_CPDATA:
+ if (currobj.offset == ((PCPDATASEC)currobj.mem)->CPS_OFFSET[0])
+ return (0);
+ else
+ return (0);
+ break;
+#endif
+ default: return (FALSE);
+ }
+}
+
+/*** change_item - allow the user to change an item in an object
+ *
+ * This function is called when the user asks to change an item
+ * in an object. It asks the user to enter a new value for the
+ * item, then stores that value in the object. This can range
+ * from simply entering a sector number to changing data in a
+ * file.
+ *
+ * It is the caller's responsibility to save the object to disk.
+ *
+ * If the user did not type the /D (Damage) switch on the command
+ * line, this function returns immediately.
+ *
+ * BUGBUG -- caller should probably remove the user's ability to
+ * select the "change" option in the first place.
+ *
+ * change_item (item)
+ *
+ * ENTRY item - field number to change
+ *
+ * EXIT No return value
+ *
+ * CALLS None
+ *
+ * WARNINGS None
+ *
+ * EFFECTS Changes the contents of a structure
+ */
+void change_item (USHORT item)
+{
+ UCHAR c, c2, *pc;
+ USHORT u, u2;
+ ULONG l, l2;
+ USHORT offset, size;
+ union dp dp;
+ UCHAR buf [10];
+ struct FNODE *f;
+ USHORT nameChange, charLimit, charNo;
+
+ nameChange = FALSE;
+
+
+#ifdef TRACE
+ fprintf (stderr, "change_item (%d)\n", item);
+ fflush (stderr);
+#endif
+
+#ifndef CODEPAGE
+ if ((currobj.type == TYPE_FNODE && !currobj.offset &&
+ (item == 15 || item == 16 || item == 17)) ||
+ (currobj.type == TYPE_SUPERB && !currobj.offset && item == 16)) {
+ printf ("Use (N)ext or (P)revious to get at that field.\n");
+ return;
+ }
+#else
+ if ((currobj.type == TYPE_FNODE && !currobj.offset &&
+ (item == 16 || item == 17 || item == 20)) ||
+ /* BUGBUG item 16 is not a change option */
+ (currobj.type == TYPE_SUPERB && !currobj.offset && item == 16)) {
+ printf ("Use (N)ext or (P)revious to get at that field.\n");
+ return;
+ }
+#endif
+
+ switch (currobj.type) {
+ case TYPE_SUPERB:
+ if (!currobj.offset) {
+ offset = superb_off [item-1];
+ size = superb_siz [item-1];
+ }
+ else {
+#ifndef CODEPAGE
+#ifdef CHECKSUMS
+ if (item < 11)
+ offset = (item - 1) * 4 + currobj.offset;
+ else
+ offset = FIELDOFFSET (struct SuperSpare, spb.SPB_SPARDB [item - 11]);
+ size = (item == 4) ? 1 : 4;
+#else
+ if (item < 9)
+ offset = (item - 1) * 4 + currobj.offset;
+ else
+ offset = FIELDOFFSET (struct SuperSpare, spb.SPB_SPARDB [item - 9]);
+ size = (item == 4) ? 1 : 4;
+#endif
+ }
+#else
+ if (item < 11)
+ offset = (item - 1) * 4 + currobj.offset;
+ else
+ offset = FIELDOFFSET (struct SuperSpare, spb.SPB_SPARDB [item - 11]);
+ size = (item == 4) ? 1 : 4;
+ }
+#endif
+ break;
+ case TYPE_BII:
+ offset = (item-1) * 4 + currobj.offset;
+ size = 4;
+ break;
+ case TYPE_BBL:
+ offset = (item==1) ? 0 : (item-2) * 4 + currobj.offset;
+ size = 4;
+ break;
+ case TYPE_FNODE:
+ f = (struct FNODE *)currobj.mem;
+ if (!currobj.offset) {
+ offset = fnode_off [item-1];
+ size = fnode_siz [item-1];
+ }
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_AB)) {
+ offset = fnab_off [item-1] + FIELDOFFSET (struct FNODE, FN_AB);
+ size = fnab_siz [item-1];
+ }
+ else if (currobj.offset == FIELDOFFSET (struct FNODE,
+ FN_FREE[0]) + f->FN_AclFnodeLength)
+ {
+ offset = (item-1) + currobj.offset;
+ size = sizeof (UCHAR);
+ }
+ else {
+ offset = (item-1) * 4 + currobj.offset;
+ size = 4;
+ }
+ break;
+ case TYPE_ALSEC:
+ if (!currobj.offset) {
+ offset = ab_off [item-1];
+ size = ab_siz [item-1];
+ }
+ else {
+ offset = (item-1) * 4 + currobj.offset;
+ size = 4;
+ }
+ break;
+ case TYPE_DIRBLK:
+ if (item <= iDB_SEC) {
+ offset = (item-1) * 4;
+ size = 4;
+ }
+#ifndef CODEPAGE
+ else if (item == 16) {
+ dp.p = (UCHAR *)currobj.mem + currobj.offset;
+ offset = ((UCHAR *)(&(DOWN_PTR (dp))) - dp.p) + currobj.offset;
+ size = 4;
+ }
+ else {
+ if (item == 15)
+ {
+ charLimit = (USHORT )*(UCHAR *)((UCHAR *)currobj.mem +
+ dirent_off [14-6] + currobj.offset); /* DIR_NAML */
+ nameChange = TRUE;
+ }
+ offset = dirent_off [item-6] + currobj.offset;
+ size = dirent_siz [item-6];
+ }
+#else
+ else if (item == iDIR_BTP) {
+ dp.p = (UCHAR *)currobj.mem + currobj.offset;
+
+ if (dp.d->DIR_ELEN > SECTORS_PER_DIRBLK*512) // DIR_ELEN must be good
+ // for DOWN_PTR()
+ pc = dp.p + ((sizeof(struct DIRENT)+dp.d->DIR_NAML+3U) & ~3U);
+ else
+ pc = (UCHAR *)&(DOWN_PTR (dp));
+
+ offset = (pc - dp.p) + currobj.offset;
+ size = 4;
+ }
+ else {
+ if (item == iDIR_NAMA)
+ {
+ charLimit = (USHORT )*(UCHAR *)((UCHAR *)currobj.mem +
+ dirent_off [iDIR_NAMA-iDIR_start] + currobj.offset); /* DIR_NAML */
+ nameChange = TRUE;
+ }
+ offset = dirent_off [item-iDIR_start] + currobj.offset;
+ size = dirent_siz [item-iDIR_start];
+ }
+#endif
+ break;
+ case TYPE_HFSEC:
+ offset = currobj.offset + (item-1) / 3;
+ if (!(item % 3))
+ offset += 2*hfmax;
+ else if ((item % 3) == 1)
+ offset += hfmax;
+ offset *= 4;
+ size = 4;
+ break;
+
+#ifdef CODEPAGE
+ case TYPE_CPSEC:
+ if (currobj.offset == FIELDOFFSET (struct CPINFOSEC, CP_INFO[0])) {
+ offset = FIELDOFFSET (struct CPINFOSEC, CP_INFO[0]) +
+ ((item - 1) / iCPI_RNGECNT) * sizeof (struct CPINFOENT)
+ + cpinfoent_off [(item-1) % iCPI_RNGECNT];
+ size = cpinfoent_siz [(item-1) % iCPI_RNGECNT];
+ printf ("offset = %u, size = %u\n", offset, size);
+ }
+ else {
+ offset = (item-1) * sizeof (ULONG);
+ size = sizeof (ULONG);
+ }
+ break;
+
+ case TYPE_CPDATA:
+ if (currobj.offset == 0) {
+ offset = cpdatasec_off[item-1];
+ size = cpdatasec_siz[item-1];
+ }
+ else {
+ offset = ((PCPDATASEC)currobj.mem)->CPS_OFFSET[currobj.scratch]
+ + cpdataent_off[item-1];
+ size = cpdataent_siz[item-1];
+ }
+ break;
+#endif
+
+ case TYPE_DATA:
+ offset = (item-1) + currobj.offset;
+ size = sizeof (UCHAR);
+ break;
+ case TYPE_BITMAP:
+ offset = item-1 + currobj.offset;
+ size = sizeof (UCHAR);
+ break;
+ default:
+ printf ("This kind of structure can't be changed yet.\n");
+ return;
+ }
+
+ if (!size) { /* this field is an ASCII date */
+ l = *(ULONG *)((UCHAR *)currobj.mem + offset);
+ strcpy (scratch, get_time (l));
+ if (strchr (scratch, '\n'))
+ *strchr (scratch, '\n') = '\0';
+ printf ("%d) %s: ", item, scratch);
+ log_gets (scratch);
+ if (!*scratch) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ if (sscanf (scratch, "%3s %2d %2d:%2d:%2d %d", buf, &tm.tm_mday,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tm.tm_year) != 6) {
+ printf ("Invalid date format, item not changed.\n");
+ return;
+ }
+ if (tm.tm_year > 1900)
+ tm.tm_year -= 1900;
+ for (u=0; u<12; u++)
+ if (!_stricmp (buf, months [u]))
+ break;
+ if (u == 12) {
+ printf ("Invalid date format, item not changed.\n");
+ return;
+ }
+ tm.tm_mon = u;
+ l2 = mktime (&tm);
+ l2 -= timezone;
+ if (tm.tm_isdst)
+ l2 += 60L * 60L;
+ if (l == l2) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ *(ULONG *)((UCHAR *)currobj.mem + offset) = l2;
+ }
+ else if (size == sizeof (UCHAR)) {
+ if (nameChange && (item == iDIR_NAMA))
+ {
+ printf ("Enter number (1-%d) of character to change or 0 to abort: ",
+ charLimit);
+ log_gets (scratch);
+ charNo = atoi (scratch);
+ if (charNo > 0 && charNo <= charLimit)
+ {
+ c = *((UCHAR *)currobj.mem + offset + charNo - 1);
+ printf ("%d + %d) %02x: ", item, charNo, c);
+ log_gets (scratch);
+ if (!*scratch) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ sscanf (scratch, "%2x", &c2);
+ if (c == c2) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ *((UCHAR *)currobj.mem + offset + charNo - 1) = c2;
+ }
+ else
+ {
+ printf ("Item not changed.\n");
+ return;
+ }
+ }
+ else
+ {
+ c = *((UCHAR *)currobj.mem + offset);
+ printf ("%d) %02x: ", item, c);
+ log_gets (scratch);
+ if (!*scratch) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ sscanf (scratch, "%2x", &c2);
+ if (c == c2) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ *((UCHAR *)currobj.mem + offset) = c2;
+ }
+ }
+ else if (size == sizeof (USHORT)) {
+ u = *(USHORT *)((UCHAR *)currobj.mem + offset);
+ printf ("%d) %04x: ", item, u);
+ log_gets (scratch);
+ if (!*scratch) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ sscanf (scratch, "%4x", &u2);
+ if (u == u2) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ *(USHORT *)((UCHAR *)currobj.mem + offset) = u2;
+ }
+ else if (size == sizeof (ULONG)) {
+ l = *(ULONG *)((UCHAR *)currobj.mem + offset);
+ printf ("%d) %08lx: ", item, l);
+ log_gets (scratch);
+ if (!*scratch) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ sscanf (scratch, "%8lx", &l2);
+ if (l == l2) {
+ printf ("Item not changed.\n");
+ return;
+ }
+ *(ULONG *)((UCHAR *)currobj.mem + offset) = l2;
+ }
+ else {
+ printf ("I can't deal with an object %d bytes long.\n", size);
+ return;
+ }
+ printf ("Item %d) changed.\n", item);
+ currobj.dirty = TRUE;
+}
+
+/*** cant_backout - display error message about stack underflow
+ *
+ * This function is called when the user selects the "backout"
+ * function with no previous object to display. An error message
+ * is displayed and the current object is unchanged.
+ *
+ * BUGBUG - should this guy terminate the program, ala incr. search ESC?
+ *
+ * cant_backout ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT No return value
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS None
+ */
+void cant_backout ()
+{
+#ifdef TRACE
+ fprintf (stderr, "cant_backout ()\n");
+ fflush (stderr);
+#endif
+ printf ("You are at the top level and cannot back out further.\n");
+}
+
+/*** get_item - get an item number from the user
+ *
+ * This function is called to ask the user to select an item
+ * to act on. It examines the current object to see whether
+ * the item number given is in range, but does not check whether
+ * the requested item can be used with a given command.
+ *
+ * BUGBUG -- later, this guy can use arrows, tab, mouse, etc. to select
+ *
+ * get_item ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT Returns selected item number, zero if aborted
+ *
+ * CALLS printf
+ * log_gets
+ *
+ * WARNINGS None
+ *
+ * EFFECTS None
+ */
+USHORT get_item ()
+{
+ int i, j;
+ USHORT threshold;
+ ULONG bigoffset;
+ struct FNODE *f;
+
+#ifdef TRACE
+ fprintf (stderr, "get_item ()\n");
+ fflush (stderr);
+#endif
+
+ while (TRUE) {
+ switch (currobj.type) {
+ case TYPE_SUPERB:
+#ifndef CODEPAGE
+ if (currobj.offset) {
+ /* don't display off end of spare block for bad SPB_SDBMAX field */
+ j = ((struct SuperSpare *)currobj.mem)->spb.SPB_SDBMAX;
+ threshold = 8 + (j > 55 ? 55 : j);
+ }
+ else
+ threshold = 15;
+#else
+ if (currobj.offset) {
+ /* don't display off end of spare block for bad SPB_SDBMAX field */
+ j = ((struct SuperSpare *)currobj.mem)->spb.SPB_SDBMAX;
+ threshold = iSPB_CPCNT + (j > 55 ? 55 : j);
+ }
+ else
+ threshold = 15;
+#endif
+ break;
+ case TYPE_BII: threshold = (currobj.offset > (2048 - 400)) ? 12 : 100; break;
+ case TYPE_BBL: threshold = (currobj.offset > (2048 - 396)) ? 12 : 101; break;
+ case TYPE_FNODE:
+ f = (struct FNODE *)currobj.mem;
+ if (!currobj.offset)
+#ifndef CODEPAGE
+ threshold = 15;
+#else
+ threshold = iFN_NEACNT;
+#endif
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_AB))
+ threshold = 4;
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_ALREC [0]))
+ threshold = 24;
+ else if (currobj.offset == FIELDOFFSET (struct FNODE,
+ FN_FREE[0]) + f->FN_AclFnodeLength)
+ threshold = f->FN_EaFnodeLength;
+ else
+ threshold = 0;
+ break;
+ case TYPE_ALSEC:
+ if (!currobj.offset)
+ threshold = 7;
+ else if (((struct ALSEC *)currobj.mem)->AS_ALBLK.AB_FLAG & ABF_NODE)
+ threshold = 40;
+ else
+ threshold = 60;
+ break;
+ case TYPE_DIRBLK:
+ if (((struct DIRENT *)((UCHAR *)currobj.mem + currobj.offset))->DIR_FLAG
+ & DF_BTP)
+#ifndef CODEPAGE
+ threshold = 16;
+ else
+ threshold = 15;
+#else
+ threshold = iDIR_BTP;
+ else
+ threshold = iDIR_NAMA;
+#endif
+ break;
+ case TYPE_HFSEC:
+ if (hfmax - currobj.offset >= 20)
+ threshold = 60;
+ else
+ threshold = (hfmax - currobj.offset) * 3;
+ break;
+#ifdef CODEPAGE
+ case TYPE_CPSEC:
+ if (currobj.offset == FIELDOFFSET (CPINFOSEC, CP_INFO[0]))
+ threshold = iCPI_RNGECNT * ((PCPINFOSEC)currobj.mem)->CP_INFOCNT;
+ else
+ threshold = iCP_NEXTSEC;
+ break;
+
+ case TYPE_CPDATA:
+ if (currobj.offset == ((PCPDATASEC)currobj.mem)->CPS_OFFSET[0])
+ threshold = iCPD_TABLE
+ + 2*(((PCPDATAENT)((UCHAR *)currobj.mem+((PCPDATASEC)currobj.mem)->CPS_OFFSET[currobj.scratch]))->CPD_RNGECNT);
+ else
+ threshold = iCPS_INDEX + 2*((PCPDATASEC)currobj.mem)->CPS_DATACNT;
+ break;
+
+#endif
+ case TYPE_DATA:
+ threshold = 256; /* allow access to first 16 bytes */
+ break;
+ case TYPE_BITMAP:
+ printf ("Enter sector offset of byte (%lx - %lx), 'x' to abort: ",
+ currobj.offset * 8L, currobj.offset * 8L + 0x400);
+ log_gets (scratch);
+ if (scratch [0] == 'x')
+ return (0);
+ else {
+ sscanf (scratch, "%lx", &bigoffset);
+ if (bigoffset / 8 < currobj.offset ||
+ bigoffset / 8 > currobj.offset + 0x400) {
+ printf ("Byte offset out of range.\n");
+ return (0);
+ }
+ return (bigoffset / 8L - currobj.offset + 1);
+ }
+
+ default: threshold = 0; break;
+ }
+
+ printf ("Enter item (1-%d) or 0 to abort: ", threshold);
+ log_gets (scratch);
+ i = atoi (scratch);
+ if ((i <= threshold) && (i >= 0))
+ return (i);
+ else
+ printf ("Item number %d is out of range.\n", i);
+ }
+}
+
+/*** cant_display - display error message about unpushable item
+ *
+ * This function is called when the user selects the "display"
+ * function on an item which cannot be pushed into. For example,
+ * it doesn't make sense to "go into" the signature on an FNODE.
+ * An error message is displayed and the current object is not changed.
+ *
+ * cant_display (item)
+ *
+ * ENTRY item - undisplayable item number
+ *
+ * EXIT No return value
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS None
+ */
+void cant_display (USHORT item)
+{
+#ifdef TRACE
+ fprintf (stderr, "cant_display (%d)\n", item);
+ fflush (stderr);
+#endif
+
+ printf ("Item %d of this object cannot be displayed.\n", item);
+}
+
+/*** cant_mark - display error message about unmarkable item
+ *
+ * This function is called when the "Mark" function is called on an
+ * item that would make no sense to mark as bad. So far, anything that
+ * cannot be displayed, cannot be marked.
+ *
+ * cant_mark (item)
+ *
+ * ENTRY item - unmarkable item number
+ *
+ * EXIT No return value
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS None
+ */
+void cant_mark(USHORT item)
+{
+#ifdef TRACE
+ fprintf (stderr, "cant_mark (%d)\n", item);
+ fflush (stderr);
+#endif
+
+ printf ("Item %d of this object cannot be marked or unmarked.\n", item);
+}
+
+/*** get_command - get a command from the user
+ *
+ * This function is called to prompt the user for a command to
+ * perform. It displays a list of available command letters
+ * and accepts a keystroke from the user. If the keystroke is
+ * not a valid command, the user is reprompted. If the keystroke
+ * is valid, it is translated into a CMD_xxxx code and returned
+ * to the caller.
+ *
+ * BUGBUG - allow help here with special return code to redisplay
+ *
+ * get_command ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT Returns command code (CMD_xxx, in DEFS.H)
+ *
+ * CALLS printf
+ * log_getch
+ *
+ * WARNINGS None
+ *
+ * EFFECTS None
+ */
+USHORT get_command ()
+{
+ UCHAR ch;
+
+#ifdef TRACE
+ fprintf (stderr, "get_command ()\n");
+ fflush (stderr);
+#endif
+ if (change)
+ printf ("\nHelp/Display/%scOpy/Change/Fence/Revert\nMark/Unmark/Backout/Next/Previous/Quit: ",
+ szLogFile == NULL ? "" : "Log/");
+ else
+ printf ("\nHelp/Display/%sBackout/Next/Previous/Quit: ",
+ szLogFile == NULL ? "" : "Log/");
+ while (!(ch=getcmdch ()))
+ ;
+
+ switch (ch) {
+ case 'D': case 'd': return (CMD_DISPLAY);
+ case 'O': case 'o': return (CMD_COPY);
+ case 'C': case 'c': return (CMD_CHANGE);
+ case 'R': case 'r': return (CMD_REVERT);
+ case 'F': case 'f': return (CMD_FENCE);
+ case 'B': case 'b': return (CMD_BACKOUT);
+ case 'N': case 'n': return (CMD_NEXT);
+ case 'P': case 'p': return (CMD_PREVIOUS);
+ case 'M': case 'm': return (CMD_MARKBAD);
+ case 'U': case 'u': return (CMD_UNMARKBAD);
+ case 'L': case 'l': return (CMD_LOG);
+ case 'Q': case 'q': return (CMD_QUIT);
+ case 'H': case 'h': case '?': return (CMD_HELP);
+ }
+}
+
+/*** next_field - move to the next major field in this object
+ *
+ * This function is called for objects too large to be displayed
+ * completely on the screen. It sets currobj.offset to the offset
+ * of the next major field that can be displayed. This might be
+ * the next page of data for a data run, bitmap, or bitmap indirect
+ * block; the next directory entry in a DIRBLK; the FN_AB or FN_ALREC
+ * field of an FNODE; and so on. The previous position can be
+ * regained with the "Previous" command.
+ *
+ * If the offset is already at the end of the structure, it wraps
+ * around to the beginning.
+ *
+ * next_field ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT No return value
+ * currobj.offset updated
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS currobj.offset updated
+ */
+void next_field ()
+{
+ union dp dp;
+ USHORT size;
+ struct FNODE *f;
+
+ switch (currobj.type) {
+ case TYPE_SUPERB:
+ if (!currobj.offset)
+ currobj.offset = FIELDOFFSET (struct SuperSpare, spb);
+ else
+ currobj.offset = 0;
+ break;
+ case TYPE_BII:
+ currobj.offset += 400;
+ if (currobj.offset > 2048)
+ currobj.offset = 0;
+ break;
+ case TYPE_BBL:
+ currobj.offset += 400;
+ if (currobj.offset > 2048)
+ currobj.offset = 4;
+ break;
+ case TYPE_BITMAP:
+ case TYPE_DBBIT:
+ currobj.offset += 128;
+ if (currobj.offset >= (currobj.type == TYPE_DBBIT ? 1024 : 2048))
+ currobj.offset = 0;
+ break;
+ case TYPE_FNODE:
+ f = (struct FNODE *)currobj.mem;
+ if (!currobj.offset)
+ currobj.offset = FIELDOFFSET (struct FNODE, FN_AB);
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_AB))
+ currobj.offset = FIELDOFFSET (struct FNODE, FN_ALREC [0]);
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_ALREC [0])) {
+ if (f->FN_EaFnodeLength)
+ currobj.offset = FIELDOFFSET (struct FNODE, FN_FREE [0]) +
+ f->FN_AclFnodeLength;
+ else
+ currobj.offset = 0;
+ }
+ else if (currobj.offset != FIELDOFFSET (struct FNODE, FN_FREE [0]) +
+ f->FN_AclFnodeLength) {
+ printf ("Illegal FNODE offset %d, returning to start.\n", currobj.offset);
+ currobj.offset = 0;
+ }
+ else
+ currobj.offset = 0;
+ break;
+ case TYPE_ALSEC:
+ if (!currobj.offset)
+ currobj.offset = FIELDOFFSET (struct ALSEC, AS_ALBLK) + sizeof (struct ALBLK);
+ else {
+ size = (((struct ALSEC *)currobj.mem)->AS_ALBLK.AB_FLAG & ABF_NODE) ?
+ sizeof (struct ALNODE) : sizeof (struct ALLEAF);
+ currobj.offset += size * 20;
+ if (currobj.offset + size*20 > SECSIZE * SECTORS_PER_AB)
+ currobj.offset = 0;
+ }
+ break;
+ case TYPE_DIRBLK:
+ dp.p = (UCHAR *)currobj.mem + currobj.offset;
+ if (dp.d->DIR_FLAG & DF_END)
+ currobj.offset = FIELDOFFSET (struct DIRBLK, DB_START);
+ else
+ currobj.offset += dp.d->DIR_ELEN;
+ break;
+ case TYPE_DATA:
+ currobj.scratch += 256;
+ if (currobj.scratch + (currobj.offset * BYTES_PER_SECTOR) > filesize) {
+ currobj.scratch = 0;
+ if (currobj.offset) {
+ currobj.offset = 0L;
+ get_object ();
+ }
+ }
+ else if (currobj.scratch == 2048) { /* need more data */
+ currobj.scratch = 0;
+ currobj.offset += SECTORS_PER_BLOCK;
+ get_object (); /* read more data */
+ }
+ break;
+ case TYPE_HFSEC:
+ if ((currobj.offset + 20) >= hfmax)
+ currobj.offset = 0;
+ else
+ currobj.offset += 20;
+ break;
+#ifdef CODEPAGE
+ case TYPE_CPSEC:
+ if (currobj.offset)
+ currobj.offset = 0;
+ else
+ currobj.offset = FIELDOFFSET (CPINFOSEC, CP_INFO[0]);
+ break;
+ case TYPE_CPDATA:
+ if (currobj.offset == ((PCPDATASEC)currobj.mem)->CPS_OFFSET[0]) {
+ if (++currobj.scratch == ((PCPDATASEC)currobj.mem)->CPS_DATACNT)
+ currobj.offset = 0;
+ } else {
+ currobj.offset = ((PCPDATASEC)currobj.mem)->CPS_OFFSET[0];
+ if (currobj.scratch == ((PCPDATASEC)currobj.mem)->CPS_DATACNT)
+ currobj.scratch = 0;
+ }
+ break;
+#endif
+ default:
+ printf (nonext_str);
+ }
+}
+
+/*** prev_field - move to the previous major field in this object
+ *
+ * This function is called for objects too large to be displayed
+ * completely on the screen. It sets currobj.offset to the offset
+ * of the previous major field that can be displayed. This might be
+ * the previous page of data for a data run, bitmap, or bitmap indirect
+ * block; the next directory entry in a DIRBLK; the beginning or
+ * FN_AB field of an FNODE; and so on. The previous position (the
+ * next major field) can be regained with the "Next" command.
+ *
+ * If the offset is already at the beginning of the structure, it
+ * wraps around to the last major field.
+ *
+ * prev_field ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT No return value
+ * currobj.offset updated
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS currobj.offset updated
+ */
+void prev_field ()
+{
+ union dp dp;
+ UCHAR *target;
+ USHORT size, ofs;
+ struct FNODE *f;
+
+ switch (currobj.type) {
+ case TYPE_SUPERB:
+ if (!currobj.offset)
+ currobj.offset = FIELDOFFSET (struct SuperSpare, spb);
+ else
+ currobj.offset = 0;
+ break;
+ case TYPE_BII:
+ if (currobj.offset < 400)
+ currobj.offset = 2048 - (2048 % 400);
+ else
+ currobj.offset -= 400;
+ break;
+ case TYPE_BBL:
+ if (currobj.offset < 404)
+ currobj.offset = 2048 - (2048 % 400) + 4;
+ else
+ currobj.offset -= 400;
+ break;
+ case TYPE_BITMAP:
+ if (!currobj.offset)
+ currobj.offset = 2048 - 128;
+ else
+ currobj.offset -= 128;
+ break;
+ case TYPE_DBBIT:
+ if (!currobj.offset)
+ currobj.offset = 1024 - 128;
+ else
+ currobj.offset -= 128;
+ break;
+ case TYPE_FNODE:
+ f = (struct FNODE *)currobj.mem;
+ if (currobj.offset == FIELDOFFSET (struct FNODE, FN_AB))
+ currobj.offset = 0;
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_ALREC [0]))
+ currobj.offset = FIELDOFFSET (struct FNODE, FN_AB);
+ else if ((currobj.offset == FIELDOFFSET (struct FNODE, FN_FREE [0]) +
+ f->FN_AclFnodeLength) || !f->FN_EaFnodeLength)
+ currobj.offset = FIELDOFFSET (struct FNODE, FN_ALREC [0]);
+ else if (currobj.offset) {
+ printf ("Illegal FNODE offset %d, returning to start.\n", currobj.offset);
+ currobj.offset = 0;
+ }
+ else
+ currobj.offset = FIELDOFFSET (struct FNODE, FN_FREE [0]) +
+ ((struct FNODE *)currobj.mem)->FN_AclFnodeLength;
+ break;
+ case TYPE_ALSEC:
+ size = (((struct ALSEC *)currobj.mem)->AS_ALBLK.AB_FLAG & ABF_NODE) ?
+ sizeof (struct ALNODE) : sizeof (struct ALLEAF);
+ ofs = FIELDOFFSET (struct ALSEC, AS_ALBLK) + sizeof (struct ALBLK);
+ if (currobj.offset == ofs)
+ currobj.offset = 0;
+ else if (!currobj.offset)
+ currobj.offset = ofs + ((size == sizeof (struct ALNODE)) ? size * 40
+ : size * 20);
+ else
+ currobj.offset -= size * 20;
+ break;
+ case TYPE_DIRBLK:
+ if (currobj.offset == FIELDOFFSET (struct DIRBLK, DB_START)) {
+ dp.p = (UCHAR *)currobj.mem + currobj.offset;
+ while (!(dp.d->DIR_FLAG & DF_END))
+ NEXT_ENTRY (dp);
+ }
+ else {
+ target = (UCHAR *)currobj.mem + currobj.offset;
+ dp.p = (UCHAR *)currobj.mem + FIELDOFFSET (struct DIRBLK, DB_START);
+ while ((dp.p + dp.d->DIR_ELEN) != target)
+ NEXT_ENTRY (dp);
+ }
+ currobj.offset = dp.p - (UCHAR *)currobj.mem;
+ break;
+ case TYPE_DATA:
+ if (!currobj.scratch) { /* beginning of block */
+ if (!currobj.offset) { /* and beginning of file! */
+ currobj.offset = (filesize / 2048L) * 4L;
+ currobj.scratch = (filesize / 256) * 256; /* "seek" to end */
+ currobj.scratch %= 2048; /* offset within a block */
+ get_object (); /* get tail of file */
+ }
+ else { /* not beginning of file */
+ currobj.scratch = 2048 - 256; /* last 256 bytes of block */
+ currobj.offset -= 4L; /* back up one block */
+ get_object (); /* read previous block */
+ }
+ }
+ else /* in middle of block */
+ currobj.scratch -= 256;
+ break;
+ case TYPE_HFSEC:
+ if (!currobj.offset) {
+ currobj.offset = hfmax - (hfmax % 20);
+ if (currobj.offset == hfmax)
+ currobj.offset -= 20;
+ }
+ else
+ currobj.offset -= 20;
+ break;
+ default:
+ printf (noprev_str);
+ }
+}
+
+/*** revert - undo changes made to an object
+ *
+ * This function is called when the user wants to undo changes he
+ * has made to an object. It rereads the current structure off the
+ * disk into currobj. Note that if the user has already saved his
+ * changes (using Backout), Revert is not possible. An informational
+ * message is displayed if the current object has not been changed.
+ *
+ * revert ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT No return value
+ *
+ * CALLS read_scratch
+ *
+ * WARNINGS Changes cannot be reverted once saved with Backout
+ *
+ * EFFECTS Rereads current structure into memory
+ */
+void revert ()
+{
+ if (!currobj.dirty) {
+ printf ("This structure has not been changed, or has already been saved.\n");
+ return;
+ }
+
+ if (currobj.type == TYPE_DATA)
+ get_object (); /* just reread current portion of data */
+ else
+ read_scratch (currobj.sec, currobj.mem, currobj.len);
+ printf ("Structure reverted.\n");
+ currobj.dirty = FALSE;
+}
+
+/*** copy_sectors - process the Copy command
+ *
+ * This function is called when the user requests the Copy command.
+ * It asks for source and destination sectors, and the number of
+ * sectors to copy. It then copies that many sectors from the source
+ * to the destination. The ranges should not overlap, as this
+ * function doesn't worry about rippling in the right direction.
+ *
+ * copy_sectors ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT No return value
+ *
+ * CALLS read_scratch
+ * write_scratch
+ *
+ * WARNINGS Sector ranges that the user gives should not overlap
+ *
+ * EFFECTS Reads and writes to disk
+ */
+void copy_sectors ()
+{
+ ULONG src, dest, len, sect;
+ UCHAR *p;
+
+ printf ("Source sector (0 to abort): ");
+ log_gets (scratch);
+ if (!(src = strtol (scratch, &p, 16)))
+ return;
+ printf ("Dest sector (0 to abort): ");
+ log_gets (scratch);
+ if (!(dest = strtol (scratch, &p, 16)))
+ return;
+ printf ("Number of sectors (0 to abort): ");
+ log_gets (scratch);
+ if (!(len = strtol (scratch, &p, 16)))
+ return;
+
+ if (src+len > dest && dest+len > src) {
+ printf ("Sector ranges overlap.\n");
+ return;
+ }
+
+ printf ("\n");
+ for (sect=0L; sect<len; sect++) {
+ read_scratch (src+sect, scratch, 1);
+ write_scratch (dest+sect, scratch, 1);
+ printf (".");
+ }
+ printf ("\nSectors copied.\n");
+ return;
+}
+
+/*** display - main object-displaying loop
+ *
+ * This function displays an object and asks the user to do something
+ * with it. Commands include displaying the contents of a field in
+ * an object, changing a field, allocating or freeing sectors in the
+ * bit map, moving to the next logical unit in an object (the next
+ * page of data in a data dump, or the next entry in a DIRBLK), and
+ * returning to the previous location (backing out one level in the
+ * hierarchy). Some of these commands are not valid for some fields
+ * in some structures; for example, it doesn't make much sense to
+ * display or allocate the signature of an FNODE. Such commands are
+ * gently denied.
+ *
+ * display ()
+ *
+ * ENTRY No parameters
+ * currobj filled in with superblock description
+ *
+ * EXIT No return value
+ *
+ * CALLS display_object
+ * get_command
+ * get_item
+ * displayable
+ * new_currobj
+ * cant_display
+ * change_item
+ * fence_bits
+ * cant_backout
+ * next_field
+ * prev_field
+ *
+ * WARNINGS None
+ */
+void
+display ()
+{
+ USHORT command, item;
+ UCHAR *p;
+
+ while (TRUE) {
+ display_object ();
+ command = get_command ();
+ switch (command) {
+ case CMD_DISPLAY:
+ while (TRUE) {
+ if (!(item = get_item ()))
+ break;
+ if (displayable (item)) {
+ objstack [stackptr++] = currobj;
+ new_currobj (item);
+ break;
+ }
+ else
+ cant_display (item);
+ }
+ break;
+ case CMD_UNMARKBAD:
+ while (TRUE) {
+ if (!(item = get_item()))
+ break;
+ if (displayable(item)) {
+ mark_as_bad(item, REMOVE);
+ break;
+ }
+ else
+ cant_mark(item);
+ }
+ break;
+ case CMD_MARKBAD:
+ while (TRUE) {
+ if (!(item = get_item()))
+ break;
+ if (displayable(item)) {
+ mark_as_bad(item, ADD);
+ break;
+ }
+ else
+ cant_mark(item);
+ }
+ break;
+ case CMD_LOG:
+ if (!(item = get_item()))
+ break;
+ write_log(item);
+ break;
+ case CMD_COPY:
+ copy_sectors ();
+ break;
+ case CMD_CHANGE:
+ if (!(item = get_item ()))
+ break;
+ change_item (item);
+ break;
+ case CMD_REVERT:
+ revert ();
+ break;
+ case CMD_FENCE:
+ fence_bits ();
+ break;
+ case CMD_BACKOUT:
+ if (currobj.dirty) {
+ currobj.dirty = FALSE;
+ printf ("Saving changes...\n");
+ write_scratch (currobj.sec, currobj.mem, currobj.len);
+ if (!stackptr)
+ break;
+ }
+ if (!stackptr)
+ cant_backout ();
+ else {
+ if (currobj.type == TYPE_FNODE) {
+ p = strrchr (curpath, '\\');
+ if (p)
+ memset (p, '\0', 1023 - (p - curpath));
+ }
+ free_block (currobj.mem);
+ currobj = objstack [--stackptr];
+ }
+ break;
+ case CMD_NEXT:
+ next_field ();
+ break;
+ case CMD_PREVIOUS:
+ prev_field ();
+ break;
+ case CMD_HELP:
+ printf ("\nType the first letter of the command you want.\n");
+ printf ("Valid commands are:\n");
+ printf (" D - Display -- dereference a field in an object.\n");
+ printf (" L - Log -- write a field to a file.\n");
+ if (change) {
+ printf (" C - Change -- change the contents of a field.\n");
+ printf (" R - Revert -- undo changes to a structure.\n");
+ printf (" O - Copy -- copy a range of sectors.\n");
+ printf (" F - Fence -- fence bits in a bitmap.\n");
+ printf (" M - Mark -- mark a sector as bad.\n");
+ }
+ printf (" B - Backout -- return to the previous level. Undoes 'D'.\n");
+ printf (" N - Next -- display next field/page. Different from Display.\n");
+ printf (" P - Previous -- display previous field/page. Undoes 'N'.\n");
+ printf (" Q - Quit -- terminate the program.\n");
+ printf (" H - Help -- print this help message.\n\n");
+ printf ("Most commands will ask you for an item number to act upon.\n");
+ printf ("Each field's item number is printed before the field, with\n");
+ printf ("a parenthesis after it, like: 3) XX_ITEM3: 42. Type an item\n");
+ printf ("number that appears in the display. Some items are not valid\n");
+ printf ("for some commands; for example, you can't dereference the signature\n");
+ printf ("on a structure. Item 0 will cancel the command.\n\n");
+ printf ("Press any key to continue: ");
+ log_getch ();
+ printf ("\n\n");
+ break;
+ case CMD_QUIT:
+ return;
+ }
+ }
+}
diff --git a/private/sdktools/damage/codepage.h b/private/sdktools/damage/codepage.h
new file mode 100644
index 000000000..95e807d09
--- /dev/null
+++ b/private/sdktools/damage/codepage.h
@@ -0,0 +1,192 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1990 **/
+/*****************************************************************/
+/** codepage.h - Code Page structures (disk & memory)
+ *
+ * HISTORY
+ * 19-May-1989 15:54:38 Mark Hitch [markh] first draft
+ * 31-Aug-1989 17:30:24 Greg Jones [gregj] moved to Pinball
+ * 03-Sep-1989 19:13:00 Greg Jones [gregj] added CPLIST structure
+ */
+
+/*
+ * Constant Definitions
+ */
+
+#define SBCS 0 /* single byte code */
+#define DBCS 1 /* first of DBCS code */
+#define DBCS_2 2 /* 2nd byte of DBCS code */
+#define CASEMAP_SIZE 256 /* size of a casemap table */
+#define DBCSFLAG_SIZE (CASEMAP_SIZE << 1) /* size of DBCS flag table */
+#define PREMAPPED 0xff /* flag indicating that string */
+ /* is already casemapped */
+
+#define DBCSCHAR 0x02 /* casemap table translates all DBCS */
+ /* start characters to this value */
+
+/*** Code Page - disk image
+ *
+ * Each volume has one or more sectors which contain information about
+ * the code pages stored on the volume. This information contains the
+ * ordering (index) of each code page, the country code, the code page
+ * id, lsn and offset of the code page information.
+ *
+ * Each Code Page Info sector contains up to 31 code page descriptions
+ * (including the locations of the code page data).
+ *
+ * Each Code Page Data sector contains up to 3 entries of code page data.
+ *
+ * Since all code pages case conversion is identical for character
+ * values 0-127, only 128 bytes are necessary for code page case
+ * conversion information.
+ *
+ * DBCS pairs are packed, with a trailing 0,0 pair terminating the list.
+ * No DBCS is indicated by a 0,0 pair.
+ *
+ * Currently no DBCS Code Page has more than 2 byte pairs, but we don't
+ * want to limit it to that.
+ *
+ * Code Page 850 is only stored once, since the case table is the same for
+ * ALL countries, and there is never DBCS support. It is stored with a
+ * 0 country code for easy matching.
+ *
+ * If no Code Page is specified in Config.Sys, a code page (valid for the
+ * specified or default country) is loaded anyway. DosGetCP return 0, but
+ * HPFS saves the actual Code Page number.
+ */
+
+/** DBCS_RNGE - DBCS range byte pairs
+ */
+
+struct DBCS_RNGE {
+ unsigned char dbcs_rnge_start;
+ unsigned char dbcs_rnge_end;
+}; /* DBCS_RNGE */
+
+typedef struct DBCS_RNGE DBCS_RNGE;
+typedef struct DBCS_RNGE * PDBCS_RNGE;
+
+
+/** CPINFOENT - Code Page information entry
+ *
+ * For each code page described, contains country code, code page ID,
+ * checksum of code page data, lsn & offset of the code page data and
+ * the count of DBCS ranges.
+ */
+
+struct CPINFOENT {
+ unsigned short CPI_CNTRY; /* country code */
+ unsigned short CPI_CPID; /* code page id */
+ unsigned long CPI_CHKSUM; /* checksum of code page data */
+ unsigned long CPI_DATASEC; /* lsn containing code page data */
+ unsigned short CPI_INDEX; /* index of code page (on volume) */
+ unsigned short CPI_RNGECNT; /* # of DBCS ranges (0 -> no DBCS) */
+}; /* CPINFOENT */
+
+typedef struct CPINFOENT CPINFOENT;
+typedef CPINFOENT * PCPINFOENT;
+
+
+/** CPINFOSEC - Code Page information sector
+ *
+ * Each CodePageSector contains information about 31 code pages and
+ * which LSN contains the code page data. Also contains count
+ * of code pages described by the sector and the next CodePageSector
+ * lsn if there are more code pages.
+ */
+
+#define CPPERINFOSEC 31
+
+struct CPINFOSEC {
+ unsigned long CP_SIG; /* signature of code page descriptor */
+ unsigned long CP_INFOCNT; /* count of cp info's in this lsn */
+ unsigned long CP_INDEX; /* index of 1st code page in this lsn */
+ unsigned long CP_NEXTSEC; /* next sector, if more Code Pages */
+#ifdef MASM
+ unsigned char CP_INFO [512-16]; /* code page entries start here */
+#else
+ struct CPINFOENT CP_INFO [CPPERINFOSEC]; /* code page entries */
+#endif
+}; /* CPINFOSEC */
+
+typedef struct CPINFOSEC CPINFOSEC;
+typedef CPINFOSEC * PCPINFOSEC;
+
+
+/** CPDATASEC - Code Page Data Sector header
+ *
+ * Header of sector contain 1-3 code page data elements.
+ */
+
+#define CPPERDATASEC 3
+
+struct CPDATASEC {
+ unsigned long CPS_SIG; /* == CPSSIGVAL */
+ unsigned short CPS_DATACNT; /* count of code pages in this sector */
+ unsigned short CPS_INDEX; /* index of first code page in sector */
+ unsigned long CPS_CHKSUM [CPPERDATASEC]; /* checksum of code page data area */
+ unsigned short CPS_OFFSET [CPPERDATASEC]; /* offset to each Code Page Data entry */
+}; /* CPDATASEC */
+
+typedef struct CPDATASEC CPDATASEC;
+typedef CPDATASEC * PCPDATASEC;
+
+/** CPDATAENT - Code Page Data entry
+ *
+ * For each code page, there is one of these structures. It contains
+ * the case conversion table for the upper half of the single-byte
+ * characters (the lower half is always translated using a fixed rule).
+ */
+
+struct CPDATAENT {
+ unsigned short CPD_CNTRY; /* country code */
+ unsigned short CPD_CPID; /* code page id */
+ unsigned short CPD_RNGECNT; /* # of DBCS ranges */
+ unsigned char CPD_TABLE [128]; /* case conversion table for byte values */
+ /* greater than 127 */
+#ifdef MASM
+ unsigned char CPD_RNGE; /* leadbyte ranges start here */
+#else
+ struct DBCS_RNGE CPD_RNGE [1]; /* variable array of byte pairs */
+ /* (CPD_RNGECNT + 1, with trailing 0,0) */
+#endif
+}; /* CPDATAENT */
+
+typedef struct CPDATAENT CPDATAENT;
+typedef CPDATAENT * PCPDATAENT;
+
+
+/*** Code Page Sector Signatures
+ */
+
+#define VAL_M1 ((('M'-'A')*40+('A'-'A'))*40+'H'-'A')
+#define VAL_M2 ((('M'-'A')*40+('G'-'A'))*40+'H'-'A')
+
+#ifdef MASM
+#define CPSIGVAL VAL_M1*40*40*40 + VAL_M2 /* infosec */
+#define CPSSIGVAL 40000000h + VAL_M1*40*40*40 + VAL_M2 /* datasec */
+#else
+#define CPSIGVAL ((ULONG)VAL_M1*40*40*40 + (ULONG)VAL_M2 )
+#define CPSSIGVAL (0x40000000L + (ULONG)VAL_M1*40*40*40 + (ULONG)VAL_M2)
+#endif
+
+/*
+ * Internal codepage structures for Pinball
+ */
+
+/*
+ * CPLISTENT - global structure which keeps track of all known codepages
+ * in the system. Each CPLIST describes one codepage, containing
+ * its codepage ID, country code, and casemap for all characters.
+ * DBCS lead bytes have already been mapped to 0x01 in the casemap.
+ */
+
+struct CPLISTENT {
+ unsigned long CPL_NEXT; /* ptr to next CPLIST in chain */
+ unsigned short CPL_COUNTRY; /* country code for this codepage */
+ unsigned short CPL_CODEPAGE; /* codepage ID for this codepage */
+ unsigned char CPL_free[3]; /* unused */
+ unsigned char CPL_DBCSFLAG; /* non-zero if codepage has DBCS */
+ unsigned char CPL_CASEMAP [256]; /* table mapping chars to uppercase */
+}; /* CPLISTENT */
diff --git a/private/sdktools/damage/const.h b/private/sdktools/damage/const.h
new file mode 100644
index 000000000..ff9501e16
--- /dev/null
+++ b/private/sdktools/damage/const.h
@@ -0,0 +1,201 @@
+/********************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1987-1990 **/
+/********************************************************************/
+
+#ifdef DEBUG
+#define SAFE 1
+#endif
+
+#ifdef SAFE
+#define LOGS 1
+#endif
+
+/** Constants for File System */
+
+#define MAXPATH 256 /* maximum path length */
+#define GROWDELT 8
+#define MVPFXSIZE 2 /* Size of the multivolume pathname prefix */
+
+/* Sector sizes */
+
+#define SECSIZE 512 /* 512 bytes per sector */
+#define SECSHIFT 9 /* 2^9 = SECSIZE */
+#define SECMSK 01ffh /* sector size mask */
+
+#ifdef MASM
+ .errnz SECSIZE-512 /* C code uses 512 as a magic number - grep them out */
+#endif
+
+/* Cache Sizes */
+
+#define SPB 4 /* sectors per buffer */
+#define SPBMASK 3 /* mask for SPB */
+#define SPBSHIFT 2
+#ifdef OLD_CACHE
+#define BUFCNT 8
+#endif
+#define SPBBITS 0fh /* SPB number of one bits, low order */
+
+#define BMASK SPB*SECSIZE-1 /* mask offset in to cache block */
+#define BSHIFT SECSHIFT+SPBSHIFT
+
+/* Buffers reserved for system ( not available to server ) */
+/* Percentage, ceiling and floor */
+
+#define PRCNT_BUF_RSRVD 20
+#define MAX_BUF_RSRVD 50
+#define MIN_BUF_RSRVD 20
+
+/* Max number of buffer to be ineligible for grabbing by GFB */
+/* If you play with this number, watch out for the minimum cache size */
+#define MAXBUFADJUSTCNT 20
+
+
+#define LWBUFCT 16 /* size of reblocking lazy write buffer */
+
+/* Number of I/O command blocks */
+/* We use one of these for every 16K of server I/O interface */
+/* One per every synchronous I/O */
+/* one for read aheads */
+/* none for lazy writes */
+
+#define IOBCNT 50 /* 50 should be enough */
+
+/* Directory Lookaside record count */
+
+#define DLCNT 10 /* 10 guys for now */
+
+/* Maximum DIRBLKs we may need to allocate for any given
+ * operation. This is in effect the maximum tree depth.
+ *
+ * Worst case, with 256 character file names and nearly empty
+ * DIRBLKs, 10 is enough levels for 60,000 files - about 40 megabytes
+ * of space just for that directory. Given more practical file length
+ * names this is enough for 10s of millions of files in a directory.
+ */
+
+#define MAX_DIR_NEED 10
+
+
+/** Heap Definitions */
+
+#define HHSIZ 4 /* size, in bytes, of heap header */
+#define GROHEAPCNT 50 /* grow heap if we have to compact more */
+ /* than once per 50 allocations */
+
+/** Special Transition Locking Structure size */
+
+#define TRANCNT 4 /* just need 4 spots */
+
+
+/* Zero offset
+ *
+ * MASM won't take 0.BAK, so we use ZERO.BAK
+ */
+
+struct dumy {
+ char ZERO;
+}; /* dumy */
+
+
+/* Maximum number of volumes that we can mount
+ *
+ * The volume ID is kept in the high bits of the sector numbers
+ * kept in our RAM structures,
+ * so there is a tradeoff between max volumes and max sectors.
+ *
+ * 32 max volumes gives us a 65 billion byte volume limit,
+ * which should last us for a while. Since sector numbers
+ * are stored on the disk without their volume upper bits
+ * this is strictly an implimentation detail; we can adjust
+ * the number of volumes or eliminate this tradeoff in other
+ * implimentations which will be 100% media compatable.
+ *
+ * We use the term VSector to indicate a vol/sector combination
+ * and PSector to indicate just the physical absolute sector #
+ *
+ */
+
+#define VOLMAX 32 /* 32 max volumes. */
+#define VOLMNTMAX 24 /* max 20 volumes mounted normally */
+ /* see fsdata.asm for details */
+
+#define MAXSEC 134217728 /* 2^32/32 max sectors */
+
+#define SECMASK 0x07FFFFFF /* mask for sector number */
+
+#define HSECMASK 0x07 /* high byte sector mask */
+
+#define HVOLMASK 0xf8 /* high byte volume mask */
+#define SVOLMASK 0x1f /* shifted right volume mask */
+
+#define VOLRSHIFT (32-5) /* shift right to extract volume index */
+#define VOLLSHIFT 5 /* shift left to extract volume index */
+
+
+/** Signature Values for Disk Structures
+ *
+ * These signature values help with debugging and they'll
+ * be used by the CHKDSK utility to help repair disks.
+ *
+ * WARNING - the low byte of all valid signatures must be non-zero,
+ * since we destroy signatures by clearing the low byte. */
+
+#define J ((('J'-'A')*40+('G'-'A'))*40+'L'-'A')
+#define R ((('R'-'A')*40+('P'-'A'))*40+'W'-'A')
+
+#ifdef MASM
+#define ABSIGVAL J*40*40*40 + R /* allocation blk*/
+#define DBSIGVAL 40000000h + J*40*40*40 + R /* directory blks */
+#define FNSIGVAL 0C0000000h + J*40*40*40 + R /* fnodes */
+#else
+#define ABSIGVAL (long)J*40*40*40 + (long)R /* allocation blk */
+#define DBSIGVAL 0x40000000L + (long)J*40*40*40 + (long)R /* directory blks */
+#define OLDFNSIGVAL 0x80000000L + (long)J*40*40*40 + (long)R /* fnodes */
+#define FNSIGVAL 0xC0000000L + (long)J*40*40*40 + (long)R /* fnodes */
+#endif
+
+
+
+/** FastFile bitmaps
+ *
+ * 0x00000000 all checking disabled
+ * 0x00000001 FF_FLUSHLAZY DoZap lazy writes are automatically flushed
+ * 0x00000002 FF_ZAPSEC DoZap blasts sector numbers/sector data
+ * 0x00000004 FF_LRUCHK vbs verification of LRU/dirty integrity
+ * 0x00000008 FF_CHKSUM sector checksumming is omitted
+ * 0x00000010 FF_PLACECHK placebuf verifies location of buffer
+ * 0x00000020 FF_HEAPCHK verify heap headers
+ * 0x00000040 FF_DIRMAP produce inram map of directory tree
+ * 0x00000080 FF_HASHCHN check hash chains
+ * 0x00000100 FF_HEAPDMP dump heap structures
+ * 0x00000200 FF_HEAPORPHAN Check for heap orphans at dismount
+ * 0x00000400 FF_GODREAD Check for read of uninitialized cache data
+ * 0x00000800 FF_HEAPYIELD issue yields in GHS
+ */
+
+#define FF_FLUSHLAZY 0x00000001
+#define FF_ZAPSEC 0x00000002
+#define FF_LRUCHK 0x00000004
+#define FF_CHKSUM 0x00000008
+#define FF_PLACECHK 0x00000010
+#define FF_HEAPCHK 0x00000020
+#define FF_DIRMAP 0x00000040
+#define FF_HASHCHN 0x00000080
+#define FF_HEAPDUMP 0x00000100
+#define FF_HEAPORPHAN 0x00000200
+#define FF_GODREAD 0x00000400
+#define FF_HEAPYIELD 0x00000800
+
+/* Dependency dumys.
+ *
+ * The assembler won't to an ".errnz" comparing two external
+ * addresses, since it doesn't know their address. So we
+ * put the .errnz in the module which defines the address,
+ * and we make that location and all folks that rely upon the
+ * relationship reference that dumy.
+ *
+ * If you change a relationship with such a dumy definition, you
+ * must find and edit all references to this dumy.
+ */
diff --git a/private/sdktools/damage/damage.c b/private/sdktools/damage/damage.c
new file mode 100644
index 000000000..08f282128
--- /dev/null
+++ b/private/sdktools/damage/damage.c
@@ -0,0 +1,218 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1990 **/
+/*****************************************************************/
+/*** MAIN.C - Main entrypoint for DAMAGE
+ *
+ * This program is a graphic-oriented utility to display and change
+ * file system structures. It is called "damage" because its primary
+ * use will be to corrupt file system structures to test CHKDSK's
+ * recovery skills. It has an option to disallow changes, though,
+ * so that it can be used purely informationally.
+ *
+ * Modification history:
+ * G.A. Jones 09/07/88 Original for Pinball testing.
+ * G.A. Jones 09/08/88 Added get_object call.
+ * G.A. Jones 09/13/88 Added pathname buffer.
+ * G.A. Jones 09/19/88 Bug in parse_args - /D not recognized.
+ * G.A. Jones 09/20/88 Message fixes.
+ * G.A. Jones 09/21/88 Added hotfix support.
+ * S. Hern 02/06/89 Added ability to to dump the SB_CDDAT
+ * as a time.h-format asciiz string (/t)
+ * S. Hern 04/20/89 Allow switching for redirected input
+ * davidbro 04/20/89 changed /r redirection behavior
+ * S. Hern 04/25/89 changed /r redirection behavior (see
+ * usage code)
+ * davidbro 05/21/89 added code to mark bad sectors on exit
+ * davidbro 05/22/89 added /l: switch support
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <direct.h>
+#include <process.h>
+#include "defs.h"
+#include "types.h"
+#include "globals.h"
+
+
+static USHORT dump_sb_cddat = 0;
+
+/*** error_msg - display error message
+ *
+ * This function is called to display a message to the standard
+ * error device.
+ *
+ * error_msg (str)
+ *
+ * ENTRY str - pointer to message
+ *
+ * EXIT No return value
+ *
+ * CALLS fprintf
+ * fflush
+ */
+void error_msg (str)
+ UCHAR *str;
+{
+ fprintf (stderr, "%s\n", str); /* display the message to the error handle */
+ fflush (stderr); /* flush the buffer to the console */
+}
+
+/*** exit_error - print informative message and exit
+ *
+ * exit_error (code)
+ *
+ * ENTRY code - error code number, defined in DEFS.H
+ *
+ * CALLS exit
+ * error_msg
+ * close_disk
+ *
+ * EFFECTS Deallocates memory
+ * Unlocks and closes disk
+ * Exits program
+ *
+ * WARNINGS Does not return
+ */
+void exit_error (USHORT code)
+{
+ UCHAR scratchbuf [80];
+
+#ifdef TRACE
+ fprintf (stderr, "exit_error (%d)\n", code);
+ fflush (stderr);
+#endif
+
+ if (code <= MAX_ERROR_CODE)
+ error_msg (error_messages [code]); /* display appropriate message */
+ else {
+ sprintf (scratchbuf, unknown_error_str, code);
+ error_msg ((UCHAR *)scratchbuf); /* display "unknown code" message */
+ }
+
+ close_disk (); /* unlock disk, close our handle */
+
+
+ exit (code);
+}
+
+void usage ()
+{
+ printf (version_str);
+ printf (timestamp_str, __DATE__, __TIME__);
+
+ printf ("Usage: DAMAGE [d:] [/D]\n");
+ printf (" d: - Pinball drive to access\n");
+ printf (" /D - Allow changes\n");
+ printf (" /R - Redirect input\n");
+ printf (" /R:<filename> - Replay keystrokes from <filename>\n");
+ printf (" /K:<filename> - Save keystrokes to <filename>\n");
+ printf (" /L:<filename> - Log command output file\n");
+
+ exit (1);
+}
+
+void parse_args (argc, argv)
+ USHORT argc;
+ UCHAR *argv [];
+{
+ UCHAR *p;
+ USHORT i;
+
+ _getcwd (disk_name, 80);
+
+ if (argc < 2)
+ usage ();
+ for (i=1; i<argc; i++) {
+ p=_strlwr (argv [i]);
+
+ if (p [1] == ':')
+ strcpy (disk_name, p);
+
+ else if (!strcmp (p, "/d"))
+ change = 1;
+ else if (!strcmp (p, "/t"))
+ dump_sb_cddat = 1;
+ else if (!strncmp (p, "/k:", 3))
+ szKeySave = &(argv[i][3]);
+ else if (!strcmp (p, "/r"))
+ redirect_input = 1;
+ else if (!strncmp (p, "/r:", 3))
+ szKeyReplay = &(argv[i][3]);
+ else if (!strncmp (p, "/l:", 3))
+ szLogFile = &(argv[i][3]);
+ else if (!strncmp (p, "/unsafe", 7 ))
+ fUnsafe = TRUE;
+ else
+ usage ();
+ }
+}
+
+int _CRTAPI1
+main (argc, argv)
+ USHORT argc;
+ UCHAR *argv [];
+{
+ parse_args (argc, argv);
+
+
+ if (!dump_sb_cddat) {
+ printf (version_str);
+ printf (timestamp_str, __DATE__, __TIME__);
+ }
+
+ if (szKeySave != NULL) {
+ fpSave = fopen(szKeySave, "w");
+ if (fpSave == NULL)
+ exit_error(SAVE_ERROR);
+ }
+
+ if (szKeyReplay != NULL) {
+ fpReplay = fopen(szKeyReplay, "r");
+ if (fpReplay == NULL)
+ exit_error(REPLAY_ERROR);
+ }
+
+ if (szLogFile != NULL) {
+
+ fpLog = fopen(szLogFile, "a");
+
+ if (fpLog == NULL) {
+
+ exit_error(LOG_ERROR);
+ }
+ }
+
+ if (!open_disk (disk_name, change)) {
+ exit_error (OPEN_ERROR);
+ }
+
+ currobj.sec = SEC_SUPERB;
+ currobj.len = 2L;
+ currobj.mem = NULL;
+ get_object ();
+ hfmax = ((struct SuperSpare *)currobj.mem)->spb.SPB_HFMAX;
+
+ memset (curpath, '\0', 1024);
+
+ if (dump_sb_cddat)
+ printf ("%s",
+ get_time (((struct SuperSpare *)currobj.mem)->sb.SB_CDDAT));
+ else
+ display ();
+
+ close_disk ();
+
+ if (szKeySave != NULL)
+ fclose(fpSave);
+
+ if (szKeyReplay != NULL)
+ fclose(fpReplay);
+
+ if (szLogFile != NULL)
+ fclose(fpLog);
+
+
+ exit (0);
+}
diff --git a/private/sdktools/damage/defs.h b/private/sdktools/damage/defs.h
new file mode 100644
index 000000000..ac31a0863
--- /dev/null
+++ b/private/sdktools/damage/defs.h
@@ -0,0 +1,260 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1990 **/
+/*****************************************************************/
+/* DEFS.H
+
+ Revision History:
+ P.A. Williams 06/16/89 Added i<fieldname> defines defining the
+ item number for a field. IE DIR_FLAG
+ is item number iDIR_FLAG.
+ S.A.Hern 06/22/89 Added missing iSB_BSEC to superblock defines
+ plus allocation sector offsets
+*/
+#include <const.h>
+#include <nt.h>
+
+/*
+ * Define CODEPAGE here to compile for new codepage disk format.
+ */
+
+#define CODEPAGE
+
+
+/*
+ * Definitions of common function return values
+ */
+#define FALSE 0
+#ifndef TRUE
+#define TRUE (~ FALSE)
+#endif
+#define NOT_OK 0
+#define OK 1
+#define DELETE_ME 2
+
+/*
+ * Definitions for exit codes
+ */
+#define SUCCESS_CODE 0 /* no error occurred */
+#define ARG_ERROR 1 /* error in arguments */
+#define OPEN_ERROR 2 /* error opening disk */
+#define INSF_MEM_ERROR 3 /* insufficient memory */
+#define READ_ERROR 4 /* error reading disk */
+#define WRITE_ERROR 5 /* error writing disk */
+
+#define SAVE_ERROR 6 // can't open keystroke save file
+#define REPLAY_ERROR 7 // can't open keystroke replay file
+#define LOG_ERROR 8 // can't open log file
+
+#define MAX_ERROR_CODE 9 /* minimum invalid error code */
+
+/*
+ * Definitions of various file system dimensions.
+ */
+#define BYTES_PER_SECTOR 512
+#define SECTORS_PER_FNODE 1
+#define SECTORS_PER_DIRBLK 4
+#define SECTORS_PER_AB 1
+#define SECTORS_PER_BLOCK 4
+#define SECTORS_PER_CODEPAGE 1
+#define BYTES_PER_BITMAP 2044
+
+/*
+ * Block types
+ */
+#define TYPE_SUPERB 0
+#define TYPE_BII 1
+#define TYPE_BITMAP 2
+#define TYPE_BBL 3
+#define TYPE_HFSEC 4
+#define TYPE_FNODE 5
+#define TYPE_DIRBLK 6
+#define TYPE_ALSEC 7
+#define TYPE_DATA 8
+#define TYPE_DBBIT 9
+#define TYPE_CPSEC 10
+#define TYPE_CPDATA 11
+
+#define MAX_OBJECTS 1024
+
+/*
+ * Valid command codes -- translated from keystrokes by get_command().
+ */
+#define CMD_DISPLAY 0
+#define CMD_CHANGE 1
+#define CMD_FENCE 2
+#define CMD_BACKOUT 3
+#define CMD_NEXT 4
+#define CMD_PREVIOUS 5
+#define CMD_QUIT 6
+#define CMD_HELP 7
+#define CMD_REVERT 8
+#define CMD_COPY 9
+#define CMD_MARKBAD 10
+#define CMD_LOG 11
+#define CMD_UNMARKBAD 12
+
+#define OPEN_FLAG 0x0001U
+#define OPEN_MODE 0xe0c2U
+
+#define GET_RECOMM (UCHAR)0
+
+#define IOCTL_LOCK 0x00U
+#define IOCTL_UNLOCK 0x01U
+#define IOCTL_READ 0x64U
+#define IOCTL_WRITE 0x44U
+#define IOCTL_GET_PARAMS 0x63U
+
+#define MAX_SECTORS_PER_TRACK 256
+
+#ifdef V11
+#define IOCTL_CATEGORY 9U
+#else
+#define IOCTL_CATEGORY 8U
+#endif
+
+#define NEXT_ENTRY(dp) dp.p += dp.d->DIR_ELEN
+#define DOWN_PTR(dp) (*(ULONG *)(dp.p + dp.d->DIR_ELEN - sizeof (long)))
+#define DIR_START(db) &((db).DB_START)
+#define AB_START(b) (ULONG *)((UCHAR *)(&((b)->a.AS_ALBLK))+sizeof(struct ALBLK))
+
+#define FIELDOFFSET(type, field) ((USHORT)&(((type *)0)->field))
+#define FIELDSIZE(type, field) (sizeof (((type *)0)->field))
+
+#define ADD 0L // add to bad lsn list
+#define REMOVE 0x80000000L // remove from bad lsn list
+
+/* item number definitions */
+
+#define INC(item) (item+1)
+
+/* Superblock */
+
+#define iSB_SIG1 1
+#define iSB_SIG2 INC(iSB_SIG1)
+#define iSB_VER INC(iSB_SIG2)
+#define iSB_FVER INC(iSB_VER)
+#define iSB_ROOT INC(iSB_FVER)
+#define iSB_SEC INC(iSB_ROOT)
+#define iSB_BSEC INC(iSB_SEC)
+#define iSB_BII_P INC(iSB_BSEC)
+#define iSB_BBL_P INC(iSB_BII_P)
+#define iSB_CDDAT INC(iSB_BBL_P)
+#define iSB_DODAT INC(iSB_CDDAT)
+#define iSB_DBSIZE INC(iSB_DODAT)
+#define iSB_DBLOW INC(iSB_DBSIZE)
+#define iSB_DBHIGH INC(iSB_DBLOW)
+#define iSB_DBMAP INC(iSB_DBHIGH)
+#define iSpareblock INC(iSB_DBMAP)
+
+/* Spareblock */
+
+#define iSPB_SIG1 1
+#define iSPB_SIG2 INC(iSPB_SIG1)
+#define iSPB_FLAG INC(iSPB_SIG2)
+#define iSPB_HFSEC INC(iSPB_FLAG)
+#define iSPB_HFUSE INC(iSPB_HFSEC)
+#define iSPB_HFMAX INC(iSPB_HFUSE)
+#define iSPB_SDBCNT INC(iSPB_HFMAX)
+#define iSPB_SDBMAX INC(iSPB_SDBCNT)
+#define iSPB_CPSEC INC(iSPB_SDBMAX)
+#define iSPB_CPCNT INC(iSPB_CPSEC)
+#ifdef CHECKSUMS
+#define iSPB_SUPERBSUM INC(iSPB_CPCNT)
+#define iSPB_SPAREBSUM INC(iSPB_SUPERBSUM)
+#endif
+
+/* DIRBLK */
+
+#define iDB_SIG 1
+#define iDB_FREP INC(iDB_SIG)
+#define iDB_CCNT INC(iDB_FREP)
+#define iDB_PAR INC(iDB_CCNT)
+#define iDB_SEC INC(iDB_PAR)
+
+/* DIRENT */
+#define iDIR_start INC(iDB_SEC)
+
+#define iDIR_ELEN INC(iDB_SEC)
+#define iDIR_FLAG INC(iDIR_ELEN)
+#define iDIR_FN INC(iDIR_FLAG)
+#define iDIR_MTIM INC(iDIR_FN)
+#define iDIR_SIZE INC(iDIR_MTIM)
+#define iDIR_ATIM INC(iDIR_SIZE)
+#define iDIR_CTIM INC(iDIR_ATIM)
+#define iDIR_EALEN INC(iDIR_CTIM)
+#define iDIR_FLEX INC(iDIR_EALEN)
+#define iDIR_CPAGE INC(iDIR_FLEX)
+#define iDIR_NAML INC(iDIR_CPAGE)
+#define iDIR_NAMA INC(iDIR_NAML)
+#define iDIR_BTP INC(iDIR_NAMA)
+
+/* FNODE */
+
+#define iFN_SIG 1
+#define iFN_SRH INC(iFN_SIG)
+#define iFN_FRH INC(iFN_SRH)
+#define iFN_XXX INC(iFN_FRH)
+#define iFN_HCNT INC(iFN_XXX)
+#define iFN_CONTFN INC(iFN_HCNT)
+#define iFN_ACLBASE INC(iFN_CONTFN)
+#define iFN_ACL_AI_DAL INC(iFN_ACLBASE)
+#define iFN_ACL_AI_SEC INC(iFN_ACL_AI_DAL)
+#define iFN_ACL_AI_FNL INC(iFN_ACL_AI_SEC)
+#define iFN_ACL_AI_DAT INC(iFN_ACL_AI_FNL)
+#define iFN_EA_AI_DAL INC(iFN_ACL_AI_DAT)
+#define iFN_EA_AI_SEC INC(iFN_EA_AI_DAL)
+#define iFN_EA_AI_FNL INC(iFN_EA_AI_SEC)
+#define iFN_EA_AI_DAT INC(iFN_EA_AI_FNL)
+#define iFN_AB INC(iFN_EA_AI_DAT)
+#define iFN_ALREC INC(iFN_AB)
+#define iFN_VLEN INC(iFN_ALREC)
+#define iFN_NEACNT INC(iFN_VLEN)
+
+/* ALBLK */
+
+#define iAB_FLAG 1
+#define iAB_FCNT INC(iAB_FLAG)
+#define iAB_OCNT INC(iAB_FCNT)
+#define iAB_FREP INC(iAB_OCNT)
+
+/* Allocation sector */
+#define iAS_SIG 1
+#define iAS_SEC INC(iAS_SIG)
+#define iAS_RENT INC(iAS_SEC)
+#define iAS_ALBLK_AB_FLAG INC(iAS_RENT)
+#define iAS_ALBLK_AB_FCNT INC(iAS_ALBLK_AB_FLAG)
+#define iAS_ALBLK_AB_OCNT INC(iAS_ALBLK_AB_FCNT)
+#define iAS_ALBLK_AB_FREP INC(iAS_ALBLK_AB_OCNT)
+
+/* CPINFOSEC */
+
+#define iCP_SIG 1
+#define iCP_INFOCNT INC(iCP_SIG)
+#define iCP_INDEX INC(iCP_INFOCNT)
+#define iCP_NEXTSEC INC(iCP_INDEX)
+#define iCP_INFO INC(iCP_NEXTSEC)
+
+/* CPINFOENT */
+
+#define iCPI_CNTRY 1
+#define iCPI_CPID INC(iCPI_CNTRY)
+#define iCPI_CHKSUM INC(iCPI_CPID)
+#define iCPI_DATASEC INC(iCPI_CHKSUM)
+#define iCPI_INDEX INC(iCPI_DATASEC)
+#define iCPI_RNGECNT INC(iCPI_INDEX)
+
+/* CPDATASEC */
+
+#define iCPS_SIG 1
+#define iCPS_DATACNT INC(iCPS_SIG)
+#define iCPS_INDEX INC(iCPS_DATACNT)
+#define iCPS_CHKSUM INC(iCPS_INDEX)
+
+/* CPDATAENT */
+
+#define iCPD_CNTRY 1
+#define iCPD_CPID INC(iCPD_CNTRY)
+#define iCPD_RNGECNT INC(iCPD_CPID)
+#define iCPD_TABLE INC(iCPD_RNGECNT)
+#define iCPD_RNGE INC(iCPD_TABLE)
diff --git a/private/sdktools/damage/dir.h b/private/sdktools/damage/dir.h
new file mode 100644
index 000000000..550449f18
--- /dev/null
+++ b/private/sdktools/damage/dir.h
@@ -0,0 +1,138 @@
+/********************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1987-1990 **/
+/********************************************************************/
+#ifdef MASM
+ include dirent.inc
+#else
+#define attr_directory 0x10
+#endif
+
+
+/* Directory Entry Fields
+ *
+ * Directory entries are always left as a multiple of 4
+ * to speed up moves. The DIR_NAMA field is variable length,
+ * the DIR_BTP field, if present, is the last dword in the record.
+ * ACL information may be stored after the DIR_NAMA field but before
+ * the DIR_BTP field so the DIR_BTP field must be located by going
+ * backwards from the end of the record
+ *
+ * WARNING - Mkdir block copies some of these entries and
+ * makes assumptions about which fields get copied. Check
+ * mkdir if stuff is added.
+ */
+
+struct DIRENT {
+ unsigned short DIR_ELEN; /* length of this entry (including free space) */
+ unsigned short DIR_FLAG; /* flags - low byte defined below */
+ /* high byte holds the old attr_ FAT values */
+ unsigned long DIR_FN; /* FNODE Sector */
+ unsigned long DIR_MTIM; /* last modification time */
+ unsigned long DIR_SIZE; /* file size */
+
+ unsigned long DIR_ATIM; /* last access time */
+ unsigned long DIR_CTIM; /* fnode creation time */
+ unsigned long DIR_EALEN; /* bytes of extended attributes */
+ char DIR_FLEX; /* description of "flex" area following the
+ * file name. Current definition is:
+ * bits 0-2: number of ACEs in dirent
+ * bits 3-7: reserved.
+ */
+ char DIR_CPAGE; /* code page index on volume */
+
+/* the following fields have information specific to the name and directory
+ * position of the file. This info is not propigated for a move/rename
+ * That code uses DIR_NAML as a seperator - check MOVE if changes are
+ * made to this structure */
+
+ unsigned char DIR_NAML; /* length of file name */
+ unsigned char DIR_NAMA; /* name goes here */
+
+/* ACL information may be stored here */
+
+/* long DIR_BTP; btree pointer to descendent DIRBLK record. */
+ /* This is only present if DF_BTP is set. */
+ /* This field is referenced from the end of */
+ /* the record, not DIR_NAMA+DIR_NAML */
+}; /* DIRENT */
+
+#ifdef MASM
+#define DIR_BTP dword ptr -4 /* referenced from the end of the record */
+#endif
+#define SIZE_DIR_BTP 4
+
+#define MAX_DIRACL 3 /* max of 3 ACLs in dirent */
+#define DIRSIZL offset DIR_NAMA /* base size of leaf dir entry (minus name) */
+#define DIRSIZP (sizeof (struct DIRENT)-1+4) /* base size of dir entry with btree ptr w/o name */
+
+#define MAX_DIRENT (DIRSIZP+255+MAX_DIRACL*(sizeof (struct SPERM_LIST))+10) /* max size of a DIRENT */
+ /* (plus some slop) */
+
+/* Directory Block Definition
+ *
+ * The change count field is incremented every time we move any
+ * of the entries in this block. For efficiency reasons, folks
+ * remember the Sector # and offset of a directory entry, and the
+ * value of the DB_CCNT field when that info was recorded.
+ * If the DB_CCNT field is different then the remembered value,
+ * then the entry offset is invalid and the entry should be
+ * refound from the top. Note that when a directory block splits,
+ * the old DIRBLK gets the old DB_CCNT field. Since
+ * the new DIRBLK is previously unknown, it can have
+ * any DB_CCNT value. We start with zero so that DB_CCNT
+ * gives us a feel for the change rate in the directory.
+ */
+
+struct DIRBLK {
+ unsigned long DB_SIG; /* signature value */
+ unsigned long DB_FREP; /* offset of first free byte */
+ unsigned long DB_CCNT; /* change count (low order bit is flag) */
+ /* =1 if this block is topmost */
+ /* =0 otherwise */
+ unsigned long DB_PAR; /* parent directory PSector # if not topmost */
+ /* FNODE sector if topmost */
+ unsigned long DB_SEC; /* PSector # of this directory block */
+
+ char DB_START; /* first dirent record goes here */
+ char DB_DUMY[2027]; /* round out to 2048 bytes */
+
+
+}; /* DIRBLK */
+
+/* Maximum entries per directory. */
+
+#define MAXDIRE (size DIRBLK- DB_START)/(size DIRENT)
+
+
+/** DIR_FLEX mask
+ */
+#define DFX_ACLMASK 0x03 /* Bits describing number of ACLS */
+
+
+/** DIR_FLAG values
+ */
+
+#define DF_SPEC 0x0001 /* special . entry */
+#define DF_ACL 0x0002 /* item has ACL */
+#define DF_BTP 0x0004 /* entry has a btree down pointer */
+#define DF_END 0x0008 /* is dumy end record */
+#define DF_XACL 0x0040 /* item has explicit ACL */
+#define DF_NEEDEAS 0x0080 /* file has "need" EAs */
+
+#define DF_NEWNAME 0x4000 /* filename doesn't use old naming rules */
+#define attr_newname 0x40 /* ditto for "dos attribute byte" */
+
+#define DF_RMASK DF_ACL+DF_XACL+DF_NEEDEAS /* only attributes preserved for rename */
+
+#ifdef MASM
+ .errnz DF_BTP - SIZE_DIR_BTP /* code uses this "coincidence" */
+#endif
+
+/* Attributes which creation can specify */
+
+#define DF_CMASK attr_read_only+attr_hidden+attr_archive+attr_system
+
+
+#define SD_ACL_LIM 1024 /* *SD_ACL lists bigger than this come from */
+ /* system memory, smaller come from heap */
diff --git a/private/sdktools/damage/display.c b/private/sdktools/damage/display.c
new file mode 100644
index 000000000..b854eb49c
--- /dev/null
+++ b/private/sdktools/damage/display.c
@@ -0,0 +1,724 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1990 **/
+/*****************************************************************/
+/*** DISPLAY.C - Routines to display objects
+ *
+ * DAMAGE
+ * Gregory A. Jones
+ *
+ * Modification history:
+ * G.A. Jones 09/07/88 Original for Pinball testing.
+ * G.A. Jones 09/08/88 Coded initial displays and commands.
+ * G.A. Jones 09/09/88 Coded more displays, D, N, P, B cmds.
+ * G.A. Jones 09/09/88 Moved command stuff to CMD.C.
+ * G.A. Jones 09/12/88 Coded DIRBLK display.
+ * G.A. Jones 09/13/88 Added bitmap displays.
+ * G.A. Jones 09/13/88 Added data and pathname displays.
+ * G.A. Jones 09/16/88 Added bad block list displays.
+ * G.A. Jones 09/19/88 Removed DIR_UID, DIR_UPRM, etc.
+ * G.A. Jones 10/12/88 Moved ATIM, CTIM from FNODE to DIRENT.
+ * G.A. Jones 10/19/88 Added dirblk banding support.
+ * P.A. Williams 05/31/89 Don't print off end of spare block
+ * if have bad SPB_SDBMAX field.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "types.h"
+#include "globals.h"
+
+/*** get_time - get pointer to time string
+ *
+ * This function is called to convert a filesystem structure's
+ * timestamp into a displayable string.
+ *
+ * get_time (time)
+ *
+ * ENTRY time - number of seconds since 01/01/70
+ *
+ * EXIT Returns pointer to time string
+ *
+ * CALLS asctime
+ * gmtime
+ *
+ * WARNINGS Each call to get_time destroys the results of
+ * the previous call.
+ *
+ * EFFECTS None
+ */
+UCHAR *get_time(ULONG time)
+{
+ struct tm *tm;
+
+ time_t Time1;
+
+ Time1 = (time_t)time;
+
+ tm = gmtime (&Time1);
+ return ((tm != NULL) ? asctime (tm) : "(null)\n");
+}
+
+/*** sb_flags - display flags of a superblock
+ *
+ * This function is called to display the flags field of the super
+ * block. It displays an appropriate string for each bit set in
+ * the number passed. A newline is printed after the display.
+ * All the flags are shown on the same line.
+ *
+ * sb_flags (flags)
+ *
+ * ENTRY flags - SB_FLAG field of the super block
+ *
+ * EXIT No return value
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS Writes to standard output
+ */
+void sb_flags (ULONG flags)
+{
+ if (!flags) {
+ printf ("(none)\n");
+ return;
+ }
+
+ if (flags & SPF_DIRT)
+ printf ("DIRT ");
+ if (flags & SPF_SPARE)
+ printf ("SPARE ");
+ if (flags & SPF_BADSEC)
+ printf ("BADSEC ");
+ if (flags & SPF_VER)
+ printf ("VER ");
+
+ printf ("\n");
+}
+
+/*** ab_flags - display flags of an ALBLK
+ *
+ * This function is called to display the flags field of an ALBLK
+ * structure. It displays an appropriate string for each bit set in
+ * the number passed. A newline is printed after the display. All
+ * the flags are shown on the same line.
+ *
+ * ab_flags (flags)
+ *
+ * ENTRY flags - AB_FLAG field of the ALBLK
+ *
+ * EXIT No return value
+ *
+ * CALLS printf
+ *
+ * WARNINGS The AB_FLAG2 field is not currently used.
+ *
+ * EFFECTS Writes to standard output
+ */
+void ab_flags (UCHAR flags)
+{
+ if (!flags) {
+ printf ("(none)\n");
+ return;
+ }
+
+ if (flags & ABF_NODE)
+ printf ("NODE ");
+ if (flags & ABF_BIN)
+ printf ("BIN ");
+ if (flags & ABF_FNP)
+ printf ("FNP ");
+
+ printf ("\n");
+}
+
+/*** dir_flags - display flags of a DIRENT
+ *
+ * This function is called to display the flags field of a directory
+ * entry. It displays an appropriate string for each bit set in the
+ * number passed. A newline is printed after the display. All the
+ * flags are shown on the same line.
+ *
+ * Currently, the only DOS flags supported are "directory" and "archive".
+ * Of course, all Pinball flags (END, BTP, etc.) are supported.
+ *
+ * dir_flags (flags)
+ *
+ * ENTRY flags - DIR_FLAG field of the DIRENT
+ *
+ * EXIT No return value
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS Writes to standard output
+ */
+void dir_flags (ULONG flags)
+{
+ if (!flags) {
+ printf ("(none)\n");
+ return;
+ }
+
+ if (flags & DF_SPEC)
+ printf ("SPEC ");
+ if (flags & DF_ACL)
+ printf ("ACL ");
+ if (flags & DF_BTP)
+ printf ("BTP ");
+ if (flags & DF_END)
+ printf ("END ");
+ if (flags & DF_XACL)
+ printf ("XACL ");
+#ifdef CODEPAGE
+ if (flags & DF_NEEDEAS)
+ printf ("NEAS ");
+#endif
+
+#ifndef CODEPAGE
+ printf ("| ");
+
+ if (flags & 0x1000)
+ printf ("Dir ");
+ if (flags & 0x2000)
+ printf ("Arc ");
+#else
+ if (flags & 0x1000)
+ printf ("| Dir ");
+ if (flags & 0x2000)
+ printf ("| Arc ");
+ if (flags & 0x4000)
+ printf ("| New ");
+#endif
+
+ printf ("\n");
+}
+
+/*** display_object - display the contents of an object
+ *
+ * This function is called to display the contents of an object on
+ * the screen. The display is formatted according to the type of
+ * the object. Structures are shown with their fields labeled with
+ * item numbers, so that the user can easily choose an item to change
+ * or push into. DIRBLKs are displayed as the DIRBLK header followed
+ * by the DIRENT currently being examined. Data is displayed either
+ * as ASCII text or in a debug-style hex dump.
+ *
+ * display_object ()
+ *
+ * ENTRY No parameters
+ *
+ * EXIT No return value
+ *
+ * CALLS printf
+ *
+ * WARNINGS None
+ *
+ * EFFECTS Displays an object on the screen
+ */
+void display_object ()
+{
+ struct SuperSpare *s;
+ struct FNODE *f;
+ struct DIRBLK *d;
+ struct ALSEC *a;
+ PCPINFOSEC cp;
+ PCPINFOENT cpi;
+ PCPDATASEC cps;
+ PCPDATAENT cpd;
+ union dp dp;
+ ULONG *l, offset, btp;
+ UCHAR *p;
+ USHORT i, j;
+
+#ifdef TRACE
+ fprintf (stderr, "display_object ()\n");
+ fflush (stderr);
+#endif
+
+ switch (currobj.type) {
+ case TYPE_SUPERB:
+ s = (struct SuperSpare *)currobj.mem;
+ if (currobj.offset == FIELDOFFSET (struct SuperSpare, spb)) {
+ printf ("Spareblock:\n");
+ printf (" 1) SPB_SIG1: %08lx ", s->spb.SPB_SIG1);
+ if (s->spb.SPB_SIG1 == SPSIG1)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", SPSIG1);
+ printf (" 2) SPB_SIG2: %08lx ", s->spb.SPB_SIG2);
+ if (s->spb.SPB_SIG2 == SPSIG2)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", SPSIG2);
+ printf (" 3) SPB_FLAG: ");
+ sb_flags (s->spb.SPB_FLAG);
+ printf (" 4) SPB_HFSEC: %08lx\n", s->spb.SPB_HFSEC);
+ printf (" 5) SPB_HFUSE: %08lx\n", s->spb.SPB_HFUSE);
+ printf (" 6) SPB_HFMAX: %08lx\n", s->spb.SPB_HFMAX);
+ printf (" 7) SPB_SDBCNT: %08lx\n", s->spb.SPB_SDBCNT);
+#ifndef CODEPAGE
+ printf (" 8) SPB_SDBMAX: %08lx\n\n", s->spb.SPB_SDBMAX);
+#ifdef CHECKSUMS
+ printf (" 9) SPB_SUPERBSUM: %08lx\n", s->spb.SPB_SUPERBSUM);
+ printf (" 10) SPB_SPAREBSUM: %08lx\n\n", s->spb.SPB_SPAREBSUM);
+#endif
+
+ /* don't go past end of spare block if have bad SPB_SDBMAX field */
+ j = (s->spb.SPB_SDBMAX > 55L) ? 55 : s->spb.SPB_SDBMAX;
+
+ for (i=0; i<j; i++) {
+#ifdef CHECKSUMS
+ printf ("%3d) %08lx ", i+11, s->spb.SPB_SPARDB [i]);
+#else
+ printf ("%3d) %08lx ", i+9, s->spb.SPB_SPARDB [i]);
+#endif
+ if (!((i+1) % 5))
+ printf ("\n");
+ }
+ if (i % 5)
+ printf ("\n");
+ }
+#else
+ printf (" 8) SPB_SDBMAX: %08lx\n", s->spb.SPB_SDBMAX);
+ printf (" 9) SPB_CPSEC: %08lx\n", s->spb.SPB_CPSEC);
+ printf (" 10) SPB_CPCNT: %08lx\n\n", s->spb.SPB_CPCNT);
+
+ /* don't go past end of spare block if have bad SPB_SDBMAX field */
+ j = (s->spb.SPB_SDBMAX > 55L) ? 55 : s->spb.SPB_SDBMAX;
+
+ for (i=0; i<j; i++) {
+ printf ("%3d) %08lx ", i+11, s->spb.SPB_SPARDB [i]);
+ if (!((i+1) % 5))
+ printf ("\n");
+ }
+ if (i % 5)
+ printf ("\n");
+ }
+#endif
+ else {
+ printf ("Superblock:\n");
+ printf (" 1) SB_SIG1: %08lx ", s->sb.SB_SIG1);
+ if (s->sb.SB_SIG1 == SBSIG1)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", SBSIG1);
+ printf (" 2) SB_SIG2: %08lx ", s->sb.SB_SIG2);
+ if (s->sb.SB_SIG2 == SBSIG2)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", SBSIG2);
+ printf (" 3) SB_VER: %02x\n", s->sb.SB_VER);
+ printf (" 4) SB_FVER: %02x\n", s->sb.SB_FVER);
+ printf (" 5) SB_ROOT: %08lx\n", s->sb.SB_ROOT);
+ printf (" 6) SB_SEC: %08lx\n", s->sb.SB_SEC);
+ printf (" 7) SB_BSEC: %08lx\n", s->sb.SB_BSEC);
+ printf (" 8) SB_BII.P: %08lx\n", s->sb.SB_BII.P);
+ printf (" 9) SB_BBL.P: %08lx\n", s->sb.SB_BBL.P);
+ printf ("10) SB_CDDAT: %s", get_time (s->sb.SB_CDDAT));
+ printf ("11) SB_DODAT: %s", get_time (s->sb.SB_DODAT));
+ printf ("12) SB_DBSIZE: %08lx\n", s->sb.SB_DBSIZE);
+ printf ("13) SB_DBLOW: %08lx\n", s->sb.SB_DBLOW);
+ printf ("14) SB_DBHIGH: %08lx\n", s->sb.SB_DBHIGH);
+ printf ("15) SB_DBMAP: %08lx\n", s->sb.SB_DBMAP);
+ printf ("16) Spareblock: {..}\n");
+ }
+ break;
+ case TYPE_DBBIT:
+ p = (UCHAR *)currobj.mem + currobj.offset;
+ printf ("DIRBLK bitmap at sector %08lx, mapping DIRBLKs %04lx to %04lx:\n",
+ currobj.sec, currobj.offset * 8L, (currobj.offset + 128L) * 8L - 1);
+ for (i=0; i<16; i++) {
+ printf ("%06lx ", (currobj.offset + (i * 8)) * 8);
+ for (j=0; j<8; j++) {
+ _itoa ((unsigned int)(p [i*8+j]), scratch, 2);
+ strrev (scratch);
+ while (strlen (scratch) < 8)
+ strcat (scratch, "0");
+ printf (" %s", scratch);
+ }
+ printf ("\n");
+ }
+ break;
+ case TYPE_BII:
+ l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
+ printf ("Bitmap indirect block at sector %08lx, offset %04x bytes:\n",
+ currobj.sec, currobj.offset);
+ for (i=1; (i<=100) && (i*4+currobj.offset <= 2048); i++) {
+ printf ("%3d) %08lx ", i, l [i-1]);
+ if (!(i % 5))
+ printf ("\n");
+ }
+ if ((i-1) % 5)
+ printf ("\n");
+ break;
+ case TYPE_BITMAP:
+ p = (UCHAR *)currobj.mem + currobj.offset;
+ printf ("Bitmap at sector %08lx, mapping sectors %06lx to %06lx:\n",
+ currobj.sec, (currobj.scratch * 2048L + currobj.offset) * 8L,
+ (currobj.scratch * 2048L + currobj.offset + 128L) * 8L - 1);
+ for (i=0; i<16; i++) {
+ printf ("%06lx ",
+ (currobj.scratch * 2048L + currobj.offset + (i * 8)) * 8);
+ for (j=0; j<8; j++) {
+ _itoa ((unsigned int)(p [i*8+j]), scratch, 2);
+ strrev (scratch);
+ while (strlen (scratch) < 8)
+ strcat (scratch, "0");
+ printf (" %s", scratch);
+ }
+ printf ("\n");
+ }
+ break;
+ case TYPE_BBL:
+ l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
+ printf ("Bad block list block at sector %08lx, entries %d-%d:\n",
+ currobj.sec, (USHORT)currobj.offset / 4,
+ (currobj.offset > 2048-396) ? 511 : ((currobj.offset / 4) + 99));
+ printf (" 1) Forward link: %08lx\n\n", *(ULONG *)currobj.mem);
+ for (i=1; (i<=100) && (i*4+currobj.offset <= 2048); i++) {
+ printf ("%3d) %08lx ", i+1, l [i-1]);
+ if (!(i % 5))
+ printf ("\n");
+ }
+ if ((i-1) % 5)
+ printf ("\n");
+ break;
+ case TYPE_HFSEC:
+ l = (ULONG *)currobj.mem + currobj.offset;
+
+ printf ("Hotfix list at sector %08lx, entries %d-%d:\n", currobj.sec,
+ (int)currobj.offset + 1,
+ (currobj.offset+20 > hfmax) ?
+ (int)(hfmax - currobj.offset) : (int)currobj.offset+20);
+ printf ("Replacement\tReplaces\tContaining FNODE\n");
+
+ for (i=0; (i<20) && (currobj.offset+i < hfmax); i++)
+ printf ("%3d) %08lx\t%3d) %08lx\t%3d) %08lx\n", i*3+1, *(l+i+hfmax),
+ i*3+2, *(l+i), i*3+3, *(l+i+2*hfmax));
+ break;
+#ifdef CODEPAGE
+ case TYPE_CPSEC:
+ cp = (PCPINFOSEC)currobj.mem;
+ printf ("Code page information at sector %08lx:\n\n", currobj.sec);
+
+ if (currobj.offset == FIELDOFFSET (CPINFOSEC, CP_INFO[0])) {
+ printf ("CP_INFO CPI_CNTRY CPI_CPID CPI_CHKSUM CPI_DATASEC");
+ printf (" CPI_INDEX CPI_RNGECNT\n");
+
+ for (i = 0; i < cp->CP_INFOCNT; i++) {
+ cpi = &cp->CP_INFO[i];
+ printf (" [%2d] %3d) %04x %3d) %04x %3d) %08lx",
+ i,
+ i*iCPI_RNGECNT+1, cpi->CPI_CNTRY,
+ i*iCPI_RNGECNT+2, cpi->CPI_CPID,
+ i*iCPI_RNGECNT+3, cpi->CPI_CHKSUM);
+ printf (" %3d) %08lx %3d) %04x %3d) %04x\n",
+ i*iCPI_RNGECNT+4, cpi->CPI_DATASEC,
+ i*iCPI_RNGECNT+5, cpi->CPI_INDEX,
+ i*iCPI_RNGECNT+6, cpi->CPI_RNGECNT);
+ }
+ } else {
+
+ printf (" 1) CP_SIG: %08lx ", cp->CP_SIG);
+ if (cp->CP_SIG == CPSIGVAL)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", CPSIGVAL);
+ printf (" 2) CP_INFOCNT: %08lx\n", cp->CP_INFOCNT);
+ printf (" 3) CP_INDEX: %08lx\n", cp->CP_INDEX);
+ printf (" 4) CP_NEXTSEC: %08lx\n", cp->CP_NEXTSEC);
+ printf (" 5) CP_INFO[%2d]: {..}\n", cp->CP_INFOCNT);
+ }
+ break;
+
+ case TYPE_CPDATA:
+ cps = (PCPDATASEC)currobj.mem;
+ printf ("Code page data at sector %08lx:\n\n", currobj.sec);
+
+ if (currobj.offset == ((PCPDATASEC)currobj.mem)->CPS_OFFSET[0]) {
+ cpd = (PCPDATAENT)((UCHAR *)currobj.mem
+ + cps->CPS_OFFSET[currobj.scratch]);
+ printf ("Data Entry[%d]:\n", currobj.scratch);
+ printf (" 1) CPD_CNTRY: %04x\n", cpd->CPD_CNTRY);
+ printf (" 2) CPD_CPID: %04x\n", cpd->CPD_CPID);
+ printf (" 3) CPD_RNGECNT: %04x\n", cpd->CPD_RNGECNT);
+ printf (" 4) CPD_TABLE[128]:");
+ for (j = 0; j < 128; j++)
+ if ( (j % 22) == 0 )
+ printf ("\n [%3d-%3d]:", j, j>128-22 ? 127 : j+21);
+ else
+ printf (" %02x", cpd->CPD_TABLE[j]);
+
+ printf("\n\n");
+
+ for (j = 0; j <= cpd->CPD_RNGECNT; j++)
+ printf("%2d) CPD_RNGE[%d].start: %02x %2d) CPD_RNGE[%d].end: %02x\n",
+ iCPD_RNGE+2*j, j, cpd->CPD_RNGE[j].dbcs_rnge_start,
+ iCPD_RNGE+2*j+1, j, cpd->CPD_RNGE[j].dbcs_rnge_end);
+ } else {
+ printf (" 1) CPS_SIG: %08lx ", cps->CPS_SIG);
+ if (cps->CPS_SIG == CPSSIGVAL)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", CPSSIGVAL);
+ printf (" 2) CPS_DATACNT: %04x\n", cps->CPS_DATACNT);
+ printf (" 3) CPS_INDEX: %04x\n\n", cps->CPS_INDEX);
+
+ for (i = 0; i < cps->CPS_DATACNT; i++)
+ printf ("%2d) CPS_CHKSUM[%2d]: %08lx %2d) CPS_OFFSET[%2d]: %04x\n",
+ iCPS_CHKSUM+2*i, i, cps->CPS_CHKSUM[i],
+ iCPS_CHKSUM+1+2*i, i, cps->CPS_OFFSET[i]);
+
+ printf("%2d) Data Entries {..}\n", iCPS_CHKSUM+2*i);
+ }
+ break;
+#endif
+ case TYPE_FNODE:
+ f = (struct FNODE *)currobj.mem;
+ if (!currobj.offset) {
+ printf ("FNODE at sector %08lx for %s:\n", currobj.sec,
+ *curpath ? curpath : "root directory");
+ printf (" 1) FN_SIG: %08lx ", f->FN_SIG);
+ if (f->FN_SIG == FNSIGVAL)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", FNSIGVAL);
+ printf (" 2) FN_SRH: %08lx\n", f->FN_SRH);
+ printf (" 3) FN_FRH: %08lx\n", f->FN_FRH);
+ printf (" 4) FN_XXX: %08lx\n", f->FN_SIG);
+ printf (" 5) FN_HCNT: %02x\n", f->FN_HCNT);
+ printf (" 6) FN_CONTFN: %08lx\n", f->FN_CONTFN);
+#ifndef CODEPAGE
+ printf (" 7) FN_ACL.AI_DAL: %08lx\n", f->FN_AclDiskLength);
+ printf (" 8) FN_ACL.AI_SEC: %08lx\n", f->FN_AclSector);
+ printf (" 9) FN_ACL.AI_FNL: %04x\n", f->FN_AclFnodeLength);
+ printf ("10) FN_ACL.AI_DAT: %02x\n", f->FN_AclDataFlag);
+ printf ("11) FN_EA.AI_DAL: %08lx\n", f->FN_EaDiskLength);
+ printf ("12) FN_EA.AI_SEC: %08lx\n", f->FN_EaSector);
+ printf ("13) FN_EA.AI_FNL: %04x\n", f->FN_EaFnodeLength);
+ printf ("14) FN_EA.AI_DAT: %02x\n", f->FN_EaDataFlag);
+ printf ("15) FN_AB: {..}\n");
+ printf ("16) FN_ALREC: {..}\n");
+ if (f->FN_EaFnodeLength)
+ printf ("17) FN_FREE (EAs): {..}\n");
+ }
+#else
+ printf (" 7) FN_ACLBASE: %04x\n", f->FN_ACLBASE);
+ printf (" 8) FN_ACL.AI_DAL: %08lx\n", f->FN_AclDiskLength);
+ printf (" 9) FN_ACL.AI_SEC: %08lx\n", f->FN_AclSector);
+ printf ("10) FN_ACL.AI_FNL: %04x\n", f->FN_AclFnodeLength);
+ printf ("11) FN_ACL.AI_DAT: %02x\n", f->FN_AclDataFlag);
+ printf ("12) FN_EA.AI_DAL: %08lx\n", f->FN_EaDiskLength);
+ printf ("13) FN_EA.AI_SEC: %08lx\n", f->FN_EaSector);
+ printf ("14) FN_EA.AI_FNL: %04x\n", f->FN_EaFnodeLength);
+ printf ("15) FN_EA.AI_DAT: %02x\n", f->FN_EaDataFlag);
+ printf ("16) FN_AB: {..}\n");
+ printf ("17) FN_ALREC: {..}\n");
+ printf ("18) FN_VLEN: %08lx\n", f->FN_VLEN);
+ printf ("19) FN_NEACNT: %08lx\n", f->FN_NEACNT);
+ if (f->FN_EaFnodeLength)
+ printf ("20) FN_FREE (EAs): {..}\n");
+ }
+#endif
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_AB)) {
+ printf ("FNODE at sector %08lx for %s (FN_AB):\n", currobj.sec,
+ *curpath ? curpath : "root directory");
+ printf (" 1) AB_FLAG: ");
+ ab_flags (f->FN_AB.AB_FLAG);
+ printf (" 2) AB_FCNT: %02x\n", f->FN_AB.AB_FCNT);
+ printf (" 3) AB_OCNT: %02x\n", f->FN_AB.AB_OCNT);
+ printf (" 4) AB_FREP: %04x\n", f->FN_AB.AB_FREP);
+ }
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_ALREC [0])) {
+ printf ("FNODE at sector %08lx for %s (FN_ALREC):\n", currobj.sec,
+ *curpath ? curpath : "root directory");
+ l = (ULONG *)f->FN_ALREC;
+ if (f->FN_AB.AB_FLAG & ABF_NODE) {
+ for (i=0; i<12; i++) {
+ printf ("ALREC [%02d]: %2d) AN_LOF: %08lx ", i, i*2+1, *l);
+ printf ("%2d) AN_SEC: %08lx\n", i*2+2, *(l+1));
+ l += 2;
+ }
+ }
+ else {
+ for (i=0; i<8; i++) {
+ printf ("ALREC [%02d]: %2d) AL_LOF: %08lx ", i, i*3+1, *l);
+ printf ("%2d) AL_LEN: %08lx ", i*3+2, *(l+1));
+ printf ("%2d) AL_POF: %08lx\n", i*3+3, *(l+2));
+ l += 3;
+ }
+ }
+ }
+ else if (currobj.offset == FIELDOFFSET (struct FNODE, FN_FREE [0]) +
+ f->FN_AclFnodeLength) {
+ p = (UCHAR *)currobj.mem + currobj.offset;
+ printf ("Extended attributes in FNODE for %s:\n",
+ *curpath ? curpath : "root directory");
+ for (i=0; (i<23) && (i*16 < f->FN_EaFnodeLength); i++) {
+ sprintf (scratch, "%04x %02x %02x %02x %02x %02x %02x %02x %02x-",
+ i * 16, p [i*16], p [i*16+1], p [i*16+2], p [i*16+3], p [i*16+4],
+ p [i*16+5], p [i*16+6], p [i*16+7]);
+ sprintf (scratch + strlen (scratch),
+ "%02x %02x %02x %02x %02x %02x %02x %02x | ",
+ p [i*16+8], p [i*16+9], p [i*16+10], p [i*16+11],
+ p [i*16+12], p [i*16+13], p [i*16+14], p [i*16+15]);
+ if (i*16 + 15 >= f->FN_EaFnodeLength)
+ memset (&scratch [(f->FN_EaFnodeLength % 16) * 3 + 6], ' ',
+ (16 - (f->FN_EaFnodeLength % 16)) * 3);
+
+ printf ("%s", scratch);
+
+ for (j=0; (j<16) && (i*16 + j < f->FN_EaFnodeLength); j++) {
+ if (p [i*16+j] < ' ')
+ scratch [j] = '.';
+ else
+ scratch [j] = p [i*16+j];
+ }
+ scratch [j] = '\0';
+ printf ("%s\n", scratch);
+ }
+ }
+ else {
+ printf ("Unknown offset in FNODE, returning to start.\n");
+ currobj.offset = 0;
+ }
+ break;
+ case TYPE_DIRBLK:
+ d = (struct DIRBLK *)currobj.mem;
+ printf ("DIRBLK at sector %08lx for %s:\n", currobj.sec,
+ *curpath ? curpath : "root directory");
+ printf (" 1) DB_SIG: %08lx ", d->DB_SIG);
+ if (d->DB_SIG == DBSIGVAL)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", DBSIGVAL);
+ printf (" 2) DB_FREP: %08lx\n", d->DB_FREP);
+ printf (" 3) DB_CCNT: %08lx\n", d->DB_CCNT);
+ printf (" 4) DB_PAR: %08lx\n", d->DB_PAR);
+ printf (" 5) DB_SEC: %08lx\n\n", d->DB_SEC);
+
+ dp.p = (UCHAR *)currobj.mem + currobj.offset;
+
+ printf ("DIRENT at offset %04x:\n", currobj.offset);
+ printf (" 6) DIR_ELEN: %04x\n", dp.d->DIR_ELEN);
+ printf (" 7) DIR_FLAG: ");
+ dir_flags (dp.d->DIR_FLAG);
+ printf (" 8) DIR_FN: %08lx\n", dp.d->DIR_FN);
+ printf (" 9) DIR_MTIM: %s", get_time (dp.d->DIR_MTIM));
+ printf ("10) DIR_SIZE: %08lx\n", dp.d->DIR_SIZE);
+ printf ("11) DIR_ATIM: %s", get_time (dp.d->DIR_ATIM));
+ printf ("12) DIR_CTIM: %s", get_time (dp.d->DIR_CTIM));
+ printf ("13) DIR_EALEN: %08lx\n", dp.d->DIR_EALEN);
+#ifndef CODEPAGE
+ printf ("14) DIR_NAML: %02x\n", dp.d->DIR_NAML);
+ strncpy (scratch, &dp.d->DIR_NAMA, dp.d->DIR_NAML);
+ scratch [dp.d->DIR_NAML] = '\0';
+ printf ("15) DIR_NAMA: `%s'\n", scratch);
+ if (dp.d->DIR_FLAG & DF_BTP)
+ printf ("16) DIR_BTP: %08lx\n", DOWN_PTR (dp));
+ break;
+#else
+ printf ("14) DIR_FLEX: %02x\n", dp.d->DIR_FLEX);
+ printf ("15) DIR_CPAGE: %02x\n", dp.d->DIR_CPAGE);
+ printf ("16) DIR_NAML: %02x\n", dp.d->DIR_NAML);
+ strncpy (scratch, &dp.d->DIR_NAMA, dp.d->DIR_NAML);
+ scratch [dp.d->DIR_NAML] = '\0';
+ printf ("17) DIR_NAMA: `%s'\n", scratch);
+ if (dp.d->DIR_FLAG & DF_BTP) {
+ if (dp.d->DIR_ELEN > SECTORS_PER_DIRBLK*512) // DIR_ELEN must be good
+ // for DOWN_PTR()
+ btp = *(ULONG *)(dp.p + ((sizeof(struct DIRENT)+dp.d->DIR_NAML+3U) & ~3U));
+ else
+ btp = DOWN_PTR (dp);
+
+ printf ("18) DIR_BTP: %08lx\n", btp);
+ }
+ break;
+#endif
+ case TYPE_ALSEC:
+ a = (struct ALSEC *)currobj.mem;
+ if (!currobj.offset) {
+ printf ("ALSEC at sector %08lx for %s (header):\n", currobj.sec,
+ *curpath ? curpath : "root directory");
+ printf (" 1) AS_SIG: %08lx ", a->AS_SIG);
+ if (a->AS_SIG == ABSIGVAL)
+ printf ("(correct)\n");
+ else
+ printf ("(should be %08lx)\n", ABSIGVAL);
+ printf (" 2) AS_SEC: %08lx\n", a->AS_SEC);
+ printf (" 3) AS_RENT: %08lx\n", a->AS_RENT);
+ printf (" 4) AB_FLAG: ");
+ ab_flags (a->AS_ALBLK.AB_FLAG);
+ printf (" 5) AB_FCNT: %02x\n", a->AS_ALBLK.AB_FCNT);
+ printf (" 6) AB_OCNT: %02x\n", a->AS_ALBLK.AB_OCNT);
+ printf (" 7) AB_FREP: %04x\n", a->AS_ALBLK.AB_FREP);
+ if (a->AS_ALBLK.AB_FLAG & ABF_NODE)
+ printf (" 8) Node records: {..}\n");
+ else
+ printf (" 8) Leaf records: {..}\n");
+ }
+ else {
+ printf ("ALSEC at sector %08lx for %s (records):\n", currobj.sec,
+ *curpath ? curpath : "root directory");
+ l = (ULONG *)((UCHAR *)currobj.mem + currobj.offset);
+ if (a->AS_ALBLK.AB_FLAG & ABF_NODE) {
+ for (i=0; i<20; i++) {
+ printf ("Node %02d: %2d) AN_LOF: %08lx %2d) AN_SEC: %08lx\n",
+ (USHORT)(currobj.offset-sizeof (struct ALSEC))/sizeof (struct ALNODE)+i+1,
+ i*2+1, *l, i*2+2, *(l+1));
+ l += 2;
+ }
+ }
+ else {
+ for (i=0; i<20; i++) {
+ printf (
+ "Leaf %02d: %2d) AL_LOF: %08lx %2d) AL_LEN: %08lx %2d) AL_POF: %08lx\n",
+ (USHORT)(currobj.offset-sizeof (struct ALSEC))/sizeof (struct ALLEAF)+i+1,
+ i*3+1, *l, i*3+2, *(l+1), i*3+3, *(l+2));
+ l += 3;
+ }
+ }
+ }
+
+ break;
+ case TYPE_DATA:
+ p = (UCHAR *)currobj.mem + currobj.scratch;
+ offset = currobj.offset * 512L + currobj.scratch;
+ printf ("Hex data at %08lx, offset %08lx, file %s:\n", currobj.sec,
+ offset, *curpath ? curpath : "root directory");
+ for (i=0; (i<16) && (offset + i*16 < filesize); i++) {
+ sprintf (scratch, "%08lx %02x %02x %02x %02x %02x %02x %02x %02x-",
+ currobj.offset * 512L + currobj.scratch + i * 16,
+ p [i*16], p [i*16+1], p [i*16+2], p [i*16+3], p [i*16+4],
+ p [i*16+5], p [i*16+6], p [i*16+7]);
+ sprintf (scratch + strlen (scratch),
+ "%02x %02x %02x %02x %02x %02x %02x %02x | ",
+ p [i*16+8], p [i*16+9], p [i*16+10], p [i*16+11],
+ p [i*16+12], p [i*16+13], p [i*16+14], p [i*16+15]);
+ if (offset + i*16 + 15 >= filesize)
+ memset (&scratch [(filesize % 16) * 3 + 10], ' ',
+ (16 - (filesize % 16)) * 3);
+
+ printf ("%s", scratch);
+
+ for (j=0; (j<16) && (offset + i*16 + j < filesize); j++) {
+ if (p [i*16+j] < ' ')
+ scratch [j] = '.';
+ else
+ scratch [j] = p [i*16+j];
+ }
+ scratch [j] = '\0';
+ printf ("%s\n", scratch);
+ }
+
+ break;
+ default:
+ printf ("Unknown type %d encountered.\n", currobj.type);
+ }
+}
diff --git a/private/sdktools/damage/fnode.h b/private/sdktools/damage/fnode.h
new file mode 100644
index 000000000..c38a004ab
--- /dev/null
+++ b/private/sdktools/damage/fnode.h
@@ -0,0 +1,183 @@
+/********************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1987-1990 **/
+/********************************************************************/
+
+
+/** File Allocation Tracking
+ *
+ * File space is allocated as a list of extents, each extent as
+ * large as we can make it. This list is kept in a B+TREE format.
+ * Each B+TREE block consists of a single sector containing an
+ * ALSEC record, except for the top most block. The topmost block
+ * consists of just an ALBLK structure, is usually much smaller than
+ * 512 bytes, and is typically included in another structure.
+ *
+ * The leaf block(s) in the tree contain triples which indicate
+ * the logical to physical mapping for this file. Typically this
+ * extent list is small enough that it is wholy contained in the
+ * fnode ALBLK stucture. If more than ALCNT extents are required
+ * then the tree is split into two levels. Note that when the
+ * topmost B+TREE block is 'split' no actual split is necessary,
+ * since the new child block is much bigger than the parent block
+ * and can contain all of the old records plus the new one. Thus,
+ * we can have B+TREEs where the root block contains only one
+ * downpointer.
+ *
+ * The following rules apply:
+ *
+ * 1) if the file is not empty, there is at least one sector allocated
+ * to logical offset 0. This simplifys some critical loops.
+ *
+ * 2) The last entry in the last node block contains a AN_LOF value of
+ * FFFFFFFF. This allows us to extend that last leaf block
+ * without having to update the node block.
+ *
+ * 3) For the node records, the AN_SEC points to a node or leaf
+ * sector which describes extents which occur before that
+ * record's AN_LOF value.
+ */
+
+/** Allocation block structure
+ *
+ * Each allocation block consists of one of these. This may be
+ * a small block imbedded in an FNODE or OFT structure, or it
+ * may occupy a whole sector and be embedded in an ALSEC structure.
+ */
+
+struct ALBLK {
+ unsigned char AB_FLAG; /* flags */
+ unsigned char AB_FLAG2[3]; /* unused - sometimes copied with AB_FLAG */
+ unsigned char AB_FCNT; /* free count - slots for ALLEAF or ALNODE */
+ unsigned char AB_OCNT; /* occupied count - # of ALLEAF or ALNODEs */
+ unsigned short AB_FREP; /* offset to last item+1 */
+ /* ALLEAF or ALNODE records go here */
+}; /* ALBLK */
+
+#define ABF_NODE 0x80 /* if not a leaf node */
+#define ABF_BIN 0x40 /* suggest using binary search to find */
+#define ABF_FNP 0x20 /* parent is an FNODE */
+#define ABF_NFG 0x01 /* not a flag, high order bit of AB_FREP */
+
+/* Allocation Node Structure
+ *
+ * These follow an ALBLK header for a node block */
+
+struct ALNODE {
+ unsigned long AN_LOF; /* logical offset (sectors */
+ unsigned long AN_SEC; /* sector for guys < this */
+}; /* ALNODE */
+
+
+/* Allocation Leaf Structure
+ *
+ * These follow an ALBLK header in a leaf block */
+
+struct ALLEAF {
+ unsigned long AL_LOF; /* logical sector offset (sectors) */
+ unsigned long AL_LEN; /* length of extent (sectors) */
+ unsigned long AL_POF; /* physical sector offset (sectors)*/
+}; /* ALLEAF */
+
+
+/** Allocation Sector Structure
+ *
+ * Root ALBLK structures are contained within other structures,
+ * such as the FNODE. When the B+TREE is more than one level,
+ * though, the non-root nodes are each held in a sector.
+ *
+ * This structure defines that format
+ */
+
+struct ALSEC {
+ unsigned long AS_SIG; /* signature */
+ unsigned long AS_SEC; /* sector # of this sector */
+ unsigned long AS_RENT; /* parent sector # or FNODE # */
+ struct ALBLK AS_ALBLK; /* ALBLK goes here */
+ /* ALNODE or ALLEAF records start here */
+}; /* ALSEC */
+
+/* # of bytes available for ALLEAF or ALNODE values. Size chosen
+ * so an integral # of either structure fits */
+
+#ifdef MASM
+#define ASSIZ ((SECSIZE - sizeof ALSEC)/24*24)
+ .errnz size ALLEAF-12
+ .errnz size ALNODE-8
+ .errnz (ASSIZ + AL_LOF + size AL_LOF + size ALBLK) GT 512 ; extra room for an AL_LOF value
+#else
+#define ASSIZ ((SECSIZE - sizeof (struct ALSEC))/24*24)
+#endif
+
+
+/* AuxInfo Structure
+ *
+ * The FNODE contains two AuxInfo structures, one for ACLs and
+ * one for EAs.
+ *
+ * These structures point to within FNODE storage and also
+ * potentially point to an overflow area which is an ALBLK structure.
+ * The AI_FNL stuff is stored in the FN_FREE area, the ACLs first
+ * and the EAs second, any free space following. The start of the
+ * EAs can be found by offseting FN_FREE with FN_ACL.AI_FNL
+ */
+
+struct AUXINFO {
+ unsigned long AI_DAL; /* non-fnode Disk Allocation length */
+ unsigned long AI_SEC; /* sec # of first sec in extent or of ALSEC */
+ unsigned short AI_FNL; /* length of fnode info */
+ unsigned char AI_DAT; /* non-zero if AI_SEC points to ALSEC */
+}; /* AUXINFO */
+
+/** Fnode block definition
+ *
+ * Every file and directory has an FNODE. The file location
+ * stuff is only used for files; directories are kept in
+ * a BTREE of DIRBLK records pointed to by FN_SEC[0].RSEC
+ */
+
+#define ALCNT 8 /* 8 ALLEAF records in an FN_AT entry */
+
+struct FNODE {
+
+ unsigned long FN_SIG; /* signature value */
+ unsigned long FN_SRH; /* sequential read history */
+ unsigned long FN_FRH; /* fast read history */
+ unsigned char FN_NAME[16]; /* 1st 18 bytes of file name */
+ unsigned long FN_CONTFN; /* fnode of directory cont. this file/dir */
+
+ ULONG FN_AclDiskLength;
+ ULONG FN_AclSector;
+ USHORT FN_AclFnodeLength;
+ UCHAR FN_AclDataFlag;
+
+ unsigned char FN_HCNT; /* count of valid history bits */
+
+ ULONG FN_EaDiskLength;
+ ULONG FN_EaSector;
+ USHORT FN_EaFnodeLength;
+ UCHAR FN_EaDataFlag;
+
+ unsigned char FN_FLAG; /* FNODE flag byte */
+
+ struct ALBLK FN_AB; /* allocation block structure */
+ struct ALLEAF FN_ALREC[ALCNT]; /* referenced from FN_AB */
+ unsigned long FN_VLEN; /* length of valid data in file. if DIR_SIZE */
+ /* is > FN_VLEN then the space inbetween */
+ /* must be zapped before being shown to user */
+ unsigned long FN_NEACNT; /* # of "need eas" in file */
+ unsigned char FN_UID[16]; /* reserved for UID value */
+ short FN_ACLBASE; /* FN_ACLBASE offset of 1st ACE in fnode */
+ unsigned char FN_SPARE[10];/* 10 more bytes emergency spares */
+ unsigned char FN_FREE[316]; /* free space for perm and env list; perm list
+ * comes first. */
+}; /* FNODE */
+
+#ifdef MASM
+ .errnz AL_LOF /* verify validity of FN_DMY1 hack above */
+ .errnz size AL_LOF-4
+#endif
+
+/* Fnode FN_FLAG bits */
+
+#define FNF_DIR 0x01 /* is a directory fnode */
diff --git a/private/sdktools/damage/glb.c b/private/sdktools/damage/glb.c
new file mode 100644
index 000000000..54ec7b2af
--- /dev/null
+++ b/private/sdktools/damage/glb.c
@@ -0,0 +1,468 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1990 **/
+/*****************************************************************/
+/*** GLB.C - Declarations of global variables.
+ *
+ * DAMAGE
+ * Gregory A. Jones
+ *
+ * Modification history:
+ * G.A. Jones 09/07/88 Adapted from CHKDSK code.
+ * G.A. Jones 09/08/88 Added object stack declaration.
+ * G.A. Jones 09/09/88 Added item array, more messages.
+ * G.A. Jones 09/13/88 Added filesize variable.
+ * G.A. Jones 09/19/88 Changed number of items in a DIRENT.
+ * G.A. Jones 09/19/88 Added xxx_off[], xxx_siz[] arrays.
+ * G.A. Jones 09/20/88 Added date codes to xxx_siz[] arrays.
+ * G.A. Jones 09/20/88 Message fixes, month array.
+ * G.A. Jones 09/21/88 Added hfmax variable for HFSEC dump.
+ * G.A. Jones 10/12/88 Moved ATIM, CTIM from FNODE to DIRENT.
+ * G.A. Jones 10/19/88 Added dirblk banding support.
+ * davidbro 4/20/89 Added keystroke save/replay functionality
+ * S. Hern 4/25/89 Added redirect_input variable
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include "defs.h"
+#include "types.h"
+
+UCHAR disk_name [80]; /* holds the name of the disk to check */
+USHORT disk_handle = 0; /* disk handle for direct access */
+USHORT change = 0; /* set non-zero if /D specified */
+USHORT redirect_input = 0; /* allow redirected input */
+USHORT fUnsafe = 0; /* write without locking */
+
+UCHAR *szKeySave = NULL; // NULL if not saving keystrokes,
+ // set to filename of save file by the
+ // /K: option
+
+UCHAR *szKeyReplay = NULL; // NULL if not replaying keystrokes
+ // from a file, set to filename of
+ // replay file by /R: option
+
+UCHAR *szLogFile = NULL; // NULL if no log file specified, set
+ // to filename of the log file by the
+ // /L: option
+
+FILE *fpSave; // file for saving keystrokes
+FILE *fpReplay; // file for replaying keystrokes
+FILE *fpLog; // file for logging information
+
+/*
+ * Various error messages for common exit problems.
+ */
+
+UCHAR version_str [] = "Pinball DAMAGE version 1.10\n";
+UCHAR timestamp_str [] = "Built %s %s\n\n";
+
+UCHAR argument_error_str [] = "Invalid parameter";
+UCHAR open_error_str [] = "Cannot open drive";
+UCHAR unknown_error_str [] = "Unknown error code %d";
+UCHAR insf_mem_error_str [] = "Insufficient memory";
+UCHAR read_error_str [] = "Error reading disk";
+UCHAR write_error_str [] = "Error writing disk";
+UCHAR usage_str [] = "Usage: DAMAGE [d:] [/d]\n";
+UCHAR nonext_str [] = "There is no 'next' field in this structure.\n";
+UCHAR noprev_str [] = "There is no 'previous' field in this structure.\n";
+UCHAR cantsave_str [] = "Cannot open keystroke save file";
+UCHAR cantreplay_str [] = "Cannot open keystroke replay file";
+UCHAR cantlog_str [] = "Cannot open log file";
+
+UCHAR *error_messages [] = {
+ "Successful operation",
+ argument_error_str,
+ open_error_str,
+ insf_mem_error_str,
+ read_error_str,
+ write_error_str,
+ cantsave_str,
+ cantreplay_str,
+ cantlog_str
+};
+
+UCHAR *bitmap = NULL; /* pointer to first copy of bitmap */
+UCHAR *bitmap2 = NULL; /* pointer to second copy of bitmap */
+
+ULONG number_of_sectors = 0L; /* number of sectors in partition */
+ULONG partition_offset = 0L; /* where the partitions starts */
+
+union blk scratch_blk; /* to read disk structures temporarily */
+
+UCHAR curpath [1024]; /* which directory is being checked */
+UCHAR scratch [512]; /* general scratch area -- input etc. */
+ULONG filesize; /* size of currently displayed file */
+USHORT hfmax; /* number of hotfix entries */
+
+UCHAR *zeros; /* for zeroing blocks */
+
+struct diskpacket dp; /* IOCTL packet for disk I/O */
+struct parmpacket prm; /* contains volume's dimensions */
+struct mbr ourmbr; /* contains image of master boot rec. */
+
+/*
+ * The following arrays make it easy to get at signatures and block
+ * sizes without IF statements. They are ordered according to the
+ * TYPE_xxxx definitions in DEFS.H. If those definitions are changed,
+ * make sure that these arrays still match.
+ */
+
+USHORT sizes [] = {
+ SECTORS_PER_DIRBLK, SECTORS_PER_FNODE, SECTORS_PER_AB, SECTORS_PER_FNODE
+};
+
+ULONG sigs [] = {
+ DBSIGVAL, FNSIGVAL, ABSIGVAL, FNSIGVAL
+};
+
+/*
+ * This array defines the number of items in each kind of structure.
+ * For ordinary structures a positive number is recorded. Structures
+ * which are basically arrays, such as data runs, bitmaps, and bitmap
+ * indirect blocks, have special values recorded which indicate that
+ * an offset (in bytes or dwords) should be requested from the user.
+ * The array is indexed by a TYPE_xxxx value.
+ */
+
+#ifndef CODEPAGE
+int maxitem [] = {
+ 15, /* items in a super block */
+ 100, /* bitmap indirect is an array of longwords - 100 on screen at a time */
+ -2, /* bitmap is an array of bits */
+ 101, /* bad block list--fwdlink plus 100 bad sector numbers on screen */
+ 3, /* hotfix list -- treat each array as one item */
+ 18, /* FNODE - handle FN_AB as one item, FN_ALREC as one item, EAs as one */
+ 16, /* DIRBLK - 5-item header plus one 11-item DIRENT */
+ 5, /* ALSEC - 3-item header, ALBLK is one item, array is one item */
+ -3, /* data is an array of bytes */
+ -2 /* dirblk bitmap is an array of bits */
+};
+#else
+int maxitem [] = {
+ 15, /* items in a super block */
+ 100, /* bitmap indirect is an array of longwords - 100 on screen at a time */
+ -2, /* bitmap is an array of bits */
+ 101, /* bad block list--fwdlink plus 100 bad sector numbers on screen */
+ 3, /* hotfix list -- treat each array as one item */
+ 21, /* FNODE - handle FN_AB as one item, FN_ALREC as one item, EAs as one */
+ 18, /* DIRBLK - 5-item header plus one 13-item DIRENT */
+ 5, /* ALSEC - 3-item header, ALBLK is one item, array is one item */
+ -3, /* data is an array of bytes */
+ -2 /* dirblk bitmap is an array of bits */
+};
+#endif
+
+/*
+ * The following definitions are for the structure which describes the
+ * object we're currently working on, as well as a stack of objects we've
+ * displayed so far.
+ */
+
+struct object currobj = {TYPE_SUPERB, (ULONG)SEC_SUPERB, 2L, 0L, NULL, 0, 0};
+
+struct object objstack [MAX_OBJECTS];
+USHORT stackptr = 0;
+
+/*
+ * The following arrays define the offsets of various fields in structures,
+ * for the Change command to use. In each case, the offset is that within
+ * the current structure, not from the beginning of an enclosing one. Thus,
+ * the "offset" of AB_FLAG in the ALBLK field of an FNODE is zero, not
+ * FIELDOFFSET (struct FNODE, FN_AB).
+ *
+ * Item sizes are in bytes (as returned by FIELDSIZE, which uses sizeof()),
+ * but the code value 0 indicates a date to be typed as mm/dd/yy hh:mm:ss.
+ */
+
+USHORT superb_off [15] = {
+ FIELDOFFSET (struct SuperB, SB_SIG1),
+ FIELDOFFSET (struct SuperB, SB_SIG2),
+ FIELDOFFSET (struct SuperB, SB_VER),
+ FIELDOFFSET (struct SuperB, SB_FVER),
+ FIELDOFFSET (struct SuperB, SB_ROOT),
+ FIELDOFFSET (struct SuperB, SB_SEC),
+ FIELDOFFSET (struct SuperB, SB_BSEC),
+ FIELDOFFSET (struct SuperB, SB_BII.P),
+ FIELDOFFSET (struct SuperB, SB_BBL.P),
+ FIELDOFFSET (struct SuperB, SB_CDDAT),
+ FIELDOFFSET (struct SuperB, SB_DODAT),
+ FIELDOFFSET (struct SuperB, SB_DBSIZE),
+ FIELDOFFSET (struct SuperB, SB_DBLOW),
+ FIELDOFFSET (struct SuperB, SB_DBHIGH),
+ FIELDOFFSET (struct SuperB, SB_DBMAP),
+};
+
+#ifndef CODEPAGE
+USHORT fnode_off [15] = {
+ FIELDOFFSET (struct FNODE, FN_SIG),
+ FIELDOFFSET (struct FNODE, FN_SRH),
+ FIELDOFFSET (struct FNODE, FN_FRH),
+ FIELDOFFSET (struct FNODE, FN_SIG),
+ FIELDOFFSET (struct FNODE, FN_HCNT),
+ FIELDOFFSET (struct FNODE, FN_CONTFN),
+ FIELDOFFSET (struct FNODE, FN_AclDiskLength),
+ FIELDOFFSET (struct FNODE, FN_AclSector),
+ FIELDOFFSET (struct FNODE, FN_AclFnodeLength),
+ FIELDOFFSET (struct FNODE, FN_AclDataFlag),
+ FIELDOFFSET (struct FNODE, FN_EaDiskLength),
+ FIELDOFFSET (struct FNODE, FN_EaSector),
+ FIELDOFFSET (struct FNODE, FN_EaFnodeLength),
+ FIELDOFFSET (struct FNODE, FN_EaDataFlag)
+};
+#else
+/* node, flag is missing */
+USHORT fnode_off [20] = {
+ FIELDOFFSET (struct FNODE, FN_SIG),
+ FIELDOFFSET (struct FNODE, FN_SRH),
+ FIELDOFFSET (struct FNODE, FN_FRH),
+ FIELDOFFSET (struct FNODE, FN_SIG),
+ FIELDOFFSET (struct FNODE, FN_HCNT),
+ FIELDOFFSET (struct FNODE, FN_CONTFN),
+ FIELDOFFSET (struct FNODE, FN_ACLBASE),
+ FIELDOFFSET (struct FNODE, FN_AclDiskLength),
+ FIELDOFFSET (struct FNODE, FN_AclSector),
+ FIELDOFFSET (struct FNODE, FN_AclFnodeLength),
+ FIELDOFFSET (struct FNODE, FN_AclDataFlag),
+ FIELDOFFSET (struct FNODE, FN_EaDiskLength),
+ FIELDOFFSET (struct FNODE, FN_EaSector),
+ FIELDOFFSET (struct FNODE, FN_EaFnodeLength),
+ FIELDOFFSET (struct FNODE, FN_EaDataFlag),
+ FIELDOFFSET (struct FNODE, FN_AB),
+ FIELDOFFSET (struct FNODE, FN_ALREC[0]),
+ FIELDOFFSET (struct FNODE, FN_VLEN),
+ FIELDOFFSET (struct FNODE, FN_NEACNT),
+ FIELDOFFSET (struct FNODE, FN_FREE[0])
+};
+#endif
+
+USHORT fnab_off [4] = {
+ FIELDOFFSET (struct ALBLK, AB_FLAG),
+ FIELDOFFSET (struct ALBLK, AB_FCNT),
+ FIELDOFFSET (struct ALBLK, AB_OCNT),
+ FIELDOFFSET (struct ALBLK, AB_FREP)
+};
+
+USHORT ab_off [7] = {
+ FIELDOFFSET (struct ALSEC, AS_SIG),
+ FIELDOFFSET (struct ALSEC, AS_SEC),
+ FIELDOFFSET (struct ALSEC, AS_RENT),
+ FIELDOFFSET (struct ALSEC, AS_ALBLK.AB_FLAG),
+ FIELDOFFSET (struct ALSEC, AS_ALBLK.AB_FCNT),
+ FIELDOFFSET (struct ALSEC, AS_ALBLK.AB_OCNT),
+ FIELDOFFSET (struct ALSEC, AS_ALBLK.AB_FREP)
+};
+
+#ifndef CODEPAGE
+USHORT dirent_off [10] = {
+ FIELDOFFSET (struct DIRENT, DIR_ELEN),
+ FIELDOFFSET (struct DIRENT, DIR_FLAG),
+ FIELDOFFSET (struct DIRENT, DIR_FN),
+ FIELDOFFSET (struct DIRENT, DIR_MTIM),
+ FIELDOFFSET (struct DIRENT, DIR_SIZE),
+ FIELDOFFSET (struct DIRENT, DIR_ATIM),
+ FIELDOFFSET (struct DIRENT, DIR_CTIM),
+ FIELDOFFSET (struct DIRENT, DIR_EALEN),
+ FIELDOFFSET (struct DIRENT, DIR_NAML),
+ FIELDOFFSET (struct DIRENT, DIR_NAMA)
+};
+#else
+USHORT dirent_off [12] = {
+ FIELDOFFSET (struct DIRENT, DIR_ELEN),
+ FIELDOFFSET (struct DIRENT, DIR_FLAG),
+ FIELDOFFSET (struct DIRENT, DIR_FN),
+ FIELDOFFSET (struct DIRENT, DIR_MTIM),
+ FIELDOFFSET (struct DIRENT, DIR_SIZE),
+ FIELDOFFSET (struct DIRENT, DIR_ATIM),
+ FIELDOFFSET (struct DIRENT, DIR_CTIM),
+ FIELDOFFSET (struct DIRENT, DIR_EALEN),
+ FIELDOFFSET (struct DIRENT, DIR_FLEX),
+ FIELDOFFSET (struct DIRENT, DIR_CPAGE),
+ FIELDOFFSET (struct DIRENT, DIR_NAML),
+ FIELDOFFSET (struct DIRENT, DIR_NAMA)
+};
+#endif
+
+#ifdef CODEPAGE
+USHORT cpinfoent_off [6] = {
+ FIELDOFFSET (struct CPINFOENT, CPI_CNTRY),
+ FIELDOFFSET (struct CPINFOENT, CPI_CPID),
+ FIELDOFFSET (struct CPINFOENT, CPI_CHKSUM),
+ FIELDOFFSET (struct CPINFOENT, CPI_DATASEC),
+ FIELDOFFSET (struct CPINFOENT, CPI_INDEX),
+ FIELDOFFSET (struct CPINFOENT, CPI_RNGECNT)
+};
+
+USHORT cpdataent_off [5] = {
+ FIELDOFFSET (struct CPDATAENT, CPD_CNTRY),
+ FIELDOFFSET (struct CPDATAENT, CPD_CPID),
+ FIELDOFFSET (struct CPDATAENT, CPD_RNGECNT),
+ FIELDOFFSET (struct CPDATAENT, CPD_TABLE[0]),
+ FIELDOFFSET (struct CPDATAENT, CPD_RNGE[0]),
+};
+
+USHORT cpdatasec_off [9] = {
+ FIELDOFFSET (struct CPDATASEC, CPS_SIG),
+ FIELDOFFSET (struct CPDATASEC, CPS_DATACNT),
+ FIELDOFFSET (struct CPDATASEC, CPS_INDEX),
+ FIELDOFFSET (struct CPDATASEC, CPS_CHKSUM[0]),
+ FIELDOFFSET (struct CPDATASEC, CPS_OFFSET[0]),
+ FIELDOFFSET (struct CPDATASEC, CPS_CHKSUM[1]),
+ FIELDOFFSET (struct CPDATASEC, CPS_OFFSET[1]),
+ FIELDOFFSET (struct CPDATASEC, CPS_CHKSUM[2]),
+ FIELDOFFSET (struct CPDATASEC, CPS_OFFSET[2]),
+};
+#endif
+
+USHORT superb_siz [20] = {
+ FIELDSIZE (struct SuperB, SB_SIG1),
+ FIELDSIZE (struct SuperB, SB_SIG2),
+ FIELDSIZE (struct SuperB, SB_VER),
+ FIELDSIZE (struct SuperB, SB_FVER),
+ FIELDSIZE (struct SuperB, SB_ROOT),
+ FIELDSIZE (struct SuperB, SB_SEC),
+ FIELDSIZE (struct SuperB, SB_BSEC),
+ FIELDSIZE (struct SuperB, SB_BII.P),
+ FIELDSIZE (struct SuperB, SB_BBL.P),
+ 0, /* SB_CDDAT and */
+ 0, /* SB_DODAT are both dates */
+ FIELDSIZE (struct SuperB, SB_DBSIZE),
+ FIELDSIZE (struct SuperB, SB_DBLOW),
+ FIELDSIZE (struct SuperB, SB_DBHIGH),
+ FIELDSIZE (struct SuperB, SB_DBMAP),
+};
+
+#ifndef CODEPAGE
+USHORT fnode_siz [15] = {
+ FIELDSIZE (struct FNODE, FN_SIG),
+ FIELDSIZE (struct FNODE, FN_SRH),
+ FIELDSIZE (struct FNODE, FN_FRH),
+ FIELDSIZE (struct FNODE, FN_SIG),
+ FIELDSIZE (struct FNODE, FN_HCNT),
+ FIELDSIZE (struct FNODE, FN_CONTFN),
+ FIELDSIZE (struct FNODE, FN_AclDiskLength),
+ FIELDSIZE (struct FNODE, FN_AclSector),
+ FIELDSIZE (struct FNODE, FN_AclFnodeLength),
+ FIELDSIZE (struct FNODE, FN_AclDataFlag),
+ FIELDSIZE (struct FNODE, FN_EaDiskLength),
+ FIELDSIZE (struct FNODE, FN_EaSector),
+ FIELDSIZE (struct FNODE, FN_EaFnodeLength),
+ FIELDSIZE (struct FNODE, FN_EaDataFlag)
+};
+#else
+/* note, previously, one more element than req'd */
+USHORT fnode_siz [21] = {
+ FIELDSIZE (struct FNODE, FN_SIG),
+ FIELDSIZE (struct FNODE, FN_SRH),
+ FIELDSIZE (struct FNODE, FN_FRH),
+ FIELDSIZE (struct FNODE, FN_SIG),
+ FIELDSIZE (struct FNODE, FN_HCNT),
+ FIELDSIZE (struct FNODE, FN_CONTFN),
+ FIELDSIZE (struct FNODE, FN_ACLBASE),
+ FIELDSIZE (struct FNODE, FN_AclDiskLength),
+ FIELDSIZE (struct FNODE, FN_AclSector),
+ FIELDSIZE (struct FNODE, FN_AclFnodeLength),
+ FIELDSIZE (struct FNODE, FN_AclDataFlag),
+ FIELDSIZE (struct FNODE, FN_EaDiskLength),
+ FIELDSIZE (struct FNODE, FN_EaSector),
+ FIELDSIZE (struct FNODE, FN_EaFnodeLength),
+ FIELDSIZE (struct FNODE, FN_EaDataFlag),
+ FIELDSIZE (struct FNODE, FN_AB),
+ FIELDSIZE (struct FNODE, FN_ALREC[0]),
+ FIELDSIZE (struct FNODE, FN_VLEN),
+ FIELDSIZE (struct FNODE, FN_NEACNT),
+ FIELDSIZE (struct FNODE, FN_FREE[0])
+};
+#endif
+
+USHORT fnab_siz [4] = {
+ FIELDSIZE (struct ALBLK, AB_FLAG),
+ FIELDSIZE (struct ALBLK, AB_FCNT),
+ FIELDSIZE (struct ALBLK, AB_OCNT),
+ FIELDSIZE (struct ALBLK, AB_FREP)
+};
+
+USHORT ab_siz [7] = {
+ FIELDSIZE (struct ALSEC, AS_SIG),
+ FIELDSIZE (struct ALSEC, AS_SEC),
+ FIELDSIZE (struct ALSEC, AS_RENT),
+ FIELDSIZE (struct ALSEC, AS_ALBLK.AB_FLAG),
+ FIELDSIZE (struct ALSEC, AS_ALBLK.AB_FCNT),
+ FIELDSIZE (struct ALSEC, AS_ALBLK.AB_OCNT),
+ FIELDSIZE (struct ALSEC, AS_ALBLK.AB_FREP)
+};
+
+#ifndef CODEPAGE
+USHORT dirent_siz [10] = {
+ FIELDSIZE (struct DIRENT, DIR_ELEN),
+ FIELDSIZE (struct DIRENT, DIR_FLAG),
+ FIELDSIZE (struct DIRENT, DIR_FN),
+ 0, /* DIR_MTIM is a date */
+ FIELDSIZE (struct DIRENT, DIR_SIZE),
+ 0, /* DIR_ATIM and */
+ 0, /* DIR_CTIM are both dates */
+ FIELDSIZE (struct DIRENT, DIR_EALEN),
+ FIELDSIZE (struct DIRENT, DIR_NAML),
+ FIELDSIZE (struct DIRENT, DIR_NAMA)
+};
+#else
+USHORT dirent_siz [12] = {
+ FIELDSIZE (struct DIRENT, DIR_ELEN),
+ FIELDSIZE (struct DIRENT, DIR_FLAG),
+ FIELDSIZE (struct DIRENT, DIR_FN),
+ 0, /* DIR_MTIM is a date */
+ FIELDSIZE (struct DIRENT, DIR_SIZE),
+ 0, /* DIR_ATIM and */
+ 0, /* DIR_CTIM are both dates */
+ FIELDSIZE (struct DIRENT, DIR_EALEN),
+ FIELDSIZE (struct DIRENT, DIR_FLEX),
+ FIELDSIZE (struct DIRENT, DIR_CPAGE),
+ FIELDSIZE (struct DIRENT, DIR_NAML),
+ FIELDSIZE (struct DIRENT, DIR_NAMA)
+};
+#endif
+
+#ifdef CODEPAGE
+USHORT cpinfoent_siz [6] = {
+ FIELDSIZE (struct CPINFOENT, CPI_CNTRY),
+ FIELDSIZE (struct CPINFOENT, CPI_CPID),
+ FIELDSIZE (struct CPINFOENT, CPI_CHKSUM),
+ FIELDSIZE (struct CPINFOENT, CPI_DATASEC),
+ FIELDSIZE (struct CPINFOENT, CPI_INDEX),
+ FIELDSIZE (struct CPINFOENT, CPI_RNGECNT)
+};
+
+USHORT cpdataent_siz [5] = {
+ FIELDSIZE (struct CPDATAENT, CPD_CNTRY),
+ FIELDSIZE (struct CPDATAENT, CPD_CPID),
+ FIELDSIZE (struct CPDATAENT, CPD_RNGECNT),
+ FIELDSIZE (struct CPDATAENT, CPD_TABLE),
+ FIELDSIZE (struct CPDATAENT, CPD_RNGE[0]),
+};
+
+USHORT cpdatasec_siz [9] = {
+ FIELDSIZE (struct CPDATASEC, CPS_SIG),
+ FIELDSIZE (struct CPDATASEC, CPS_DATACNT),
+ FIELDSIZE (struct CPDATASEC, CPS_INDEX),
+ FIELDSIZE (struct CPDATASEC, CPS_CHKSUM[0]),
+ FIELDSIZE (struct CPDATASEC, CPS_OFFSET[0]),
+ FIELDSIZE (struct CPDATASEC, CPS_CHKSUM[1]),
+ FIELDSIZE (struct CPDATASEC, CPS_CHKSUM[1]),
+ FIELDSIZE (struct CPDATASEC, CPS_OFFSET[2]),
+ FIELDSIZE (struct CPDATASEC, CPS_OFFSET[2]),
+};
+#endif
+
+UCHAR *months [12] = {
+ "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"
+};
+
+struct tm tm;
+
+struct vioprm mode25 = {
+ 12, 1, 4, 80, 25, 640, 350
+};
+
+struct vioprm mode43 = {
+ 12, 1, 4, 80, 43, 640, 350
+};
diff --git a/private/sdktools/damage/globals.h b/private/sdktools/damage/globals.h
new file mode 100644
index 000000000..2dbc23621
--- /dev/null
+++ b/private/sdktools/damage/globals.h
@@ -0,0 +1,85 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1990 **/
+/*****************************************************************/
+extern UCHAR disk_name [80];
+extern USHORT disk_handle;
+extern USHORT change;
+extern USHORT redirect_input;
+extern USHORT fUnsafe;
+
+extern UCHAR *szKeySave;
+extern UCHAR *szKeyReplay;
+extern UCHAR *szLogFile;
+
+extern FILE *fpSave;
+extern FILE *fpReplay;
+extern FILE *fpLog;
+
+extern UCHAR version_str [];
+extern UCHAR timestamp_str [];
+
+extern UCHAR argument_error_str [];
+extern UCHAR open_error_str [];
+extern UCHAR unknown_error_str [];
+extern UCHAR insf_mem_error_str [];
+extern UCHAR read_error_str [];
+extern UCHAR write_error_str [];
+extern UCHAR usage_str [];
+extern UCHAR nonext_str [];
+extern UCHAR noprev_str [];
+
+extern UCHAR *error_messages [];
+
+extern UCHAR *bitmap;
+extern UCHAR *bitmap2;
+
+extern ULONG number_of_sectors;
+extern ULONG partition_offset;
+
+extern union blk scratch_blk;
+
+extern UCHAR curpath [];
+extern UCHAR scratch [];
+extern ULONG filesize;
+extern USHORT hfmax;
+
+extern UCHAR *zeros;
+
+extern struct diskpacket dp;
+extern struct parmpacket prm;
+extern struct mbr ourmbr;
+
+extern USHORT sizes [];
+extern ULONG sigs [];
+extern int maxitem [];
+
+extern struct object currobj;
+extern struct object objstack [];
+extern USHORT stackptr;
+
+extern USHORT superb_off [];
+extern USHORT fnode_off [];
+extern USHORT fnab_off [];
+extern USHORT ab_off [];
+extern USHORT dirent_off [];
+#ifdef CODEPAGE
+extern USHORT cpinfoent_off [];
+extern USHORT cpdataent_off [];
+extern USHORT cpdatasec_off [];
+#endif
+extern USHORT superb_siz [];
+extern USHORT fnode_siz [];
+extern USHORT fnab_siz [];
+extern USHORT ab_siz [];
+extern USHORT dirent_siz [];
+#ifdef CODEPAGE
+extern USHORT cpinfoent_siz [];
+extern USHORT cpdataent_siz [];
+extern USHORT cpdatasec_siz [];
+#endif
+
+extern UCHAR *months [];
+extern struct tm tm;
+
+extern struct vioprm mode25, mode43;
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);
+}
diff --git a/private/sdktools/damage/log.c b/private/sdktools/damage/log.c
new file mode 100644
index 000000000..3c60023c1
--- /dev/null
+++ b/private/sdktools/damage/log.c
@@ -0,0 +1,55 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1990 **/
+/*****************************************************************/
+/*
+ * LOG.C -- keystroke saving, keystroke replaying, and logfile
+ * routines. For DAMAGE.
+ *
+ * created by Dave Brown, 4/20/89
+ *
+ * modification log:
+ * date: by: what:
+ * =======================================================
+ * 4/20/89 davidbro created file
+ * 4/25/89 S. Hern allowed redirected input
+ *
+ */
+
+#include <conio.h>
+#include <stdio.h>
+#include "defs.h"
+#include "globals.h"
+
+UCHAR
+log_getch()
+{
+ UCHAR ch, x;
+
+ if (redirect_input)
+ {
+ ch = getchar();
+ while ((x = getchar()) != '\n');
+ }
+ else if (szKeyReplay == NULL)
+ ch = _getch();
+ else
+ ch = fgetc(fpReplay);
+ if (szKeySave != NULL)
+ fputc(ch, fpSave);
+ return ch;
+}
+
+void
+log_gets(UCHAR *s)
+{
+ if (szKeyReplay == NULL)
+ gets(s);
+ else {
+ fgets(s, 80, fpReplay);
+ printf(s);
+ s[strlen(s) - 1] = '\0';
+ }
+ if (szKeySave != NULL)
+ fprintf(fpSave, "%s\n", s);
+}
diff --git a/private/sdktools/damage/makefile b/private/sdktools/damage/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/sdktools/damage/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/damage/map.c b/private/sdktools/damage/map.c
new file mode 100644
index 000000000..e99115903
--- /dev/null
+++ b/private/sdktools/damage/map.c
@@ -0,0 +1,283 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1990 **/
+/*****************************************************************/
+/*** MAP.C - Routines to manipulate disk maps and allocate memory
+ *
+ * DAMAGE
+ * Gregory A. Jones
+ *
+ * Modification history:
+ * G.A. Jones 06/02/88 Original for Pinball 1.0.
+ * G.A. Jones 09/07/88 Adapted from CHKDSK's MAP.C and MEM.C.
+ * G.A. Jones 09/08/88 Coded get_object.
+ * G.A. Jones 09/19/88 Set dirty flag to FALSE on new object.
+ */
+
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+#include "defs.h"
+#include "types.h"
+#include "globals.h"
+
+/*** clr_bit - clear a bit in a bitmap
+ *
+ * This routine is called to clear a bit in a bitmap. This
+ * indicates a sector in use by the file system.
+ *
+ * clr_bit (lsn)
+ *
+ * ENTRY lsn - sector number to allocate
+ *
+ * EXIT Return value 0 if success, 1 if no bitmap,
+ * 2 if bad sector number
+ *
+ * CALLS None
+ *
+ * EFFECTS Clears a bit in the global bitmap
+ *
+ * WARNINGS Bitmap should be allocated first
+ */
+USHORT clr_bit (ULONG lsn)
+{
+ register ULONG byte;
+ register USHORT bit;
+
+#ifdef TRACE_BITS
+ fprintf (stderr, "clr_bit (%lx)\n", lsn);
+ fflush (stderr);
+#endif
+
+ if (!bitmap) /* bitmap is not allocated yet */
+ return (1); /* return error condition */
+
+ if (lsn > number_of_sectors) /* sector outside bitmap */
+ return (2); /* return error condition */
+
+ byte = lsn >> 3; /* divide by 8 without a DIV */
+ bit = (USHORT)(lsn & 7); /* "mod" by 8 without a DIV */
+ bitmap [byte] &= ~(1 << bit); /* clear the bit by ANDing with its inverse */
+
+ return (0);
+}
+
+/*** set_bit - set a bit in a bitmap
+ *
+ * This routine is called to set a bit in a bitmap. This
+ * indicates a sector not in use by the file system.
+ *
+ * set_bit (lsn)
+ *
+ * ENTRY lsn - sector number to free
+ *
+ * EXIT Return value 0 if success, 1 if no bitmap,
+ * 2 if bad sector number
+ *
+ * CALLS None
+ *
+ * EFFECTS Sets a bit in the global bitmap
+ *
+ * WARNINGS Bitmap should be allocated first
+ */
+USHORT set_bit (ULONG lsn)
+{
+ register ULONG byte;
+ register USHORT bit;
+
+#ifdef TRACE_BITS
+ fprintf (stderr, "set_bit (%lx)\n", lsn);
+ fflush (stderr);
+#endif
+
+ if (!bitmap) /* bitmap is not allocated yet */
+ return (1); /* return error condition */
+
+ if (lsn > number_of_sectors) /* sector outside bitmap */
+ return (2); /* return error condition */
+
+ byte = lsn >> 3; /* divide by 8 without a DIV */
+ bit = (USHORT)(lsn & 7); /* "mod" by 8 without a DIV */
+ bitmap [byte] |= (1 << bit); /* set the bit by ORing with it */
+
+ return (0);
+}
+
+/*** allocate_block - allocate a memory chunk in multiples of 512 bytes
+ *
+ * This function is called to allocate a block of memory which is
+ * a multiple of 512 bytes (one sector). This is a useful tool for
+ * allocating a memory structure to store a run of sectors in.
+ *
+ * BUGBUG - make this a macro to save stack and execution time?
+ *
+ * allocate_block (nblocks)
+ *
+ * ENTRY nblocks - number of 512-byte blocks to allocate
+ *
+ * EXIT Returns NULL if insufficient memory, pointer if success
+ *
+ * CALLS malloc
+ *
+ * EFFECTS Allocates memory
+ *
+ * WARNINGS May return NULL pointer
+ */
+void *allocate_block (USHORT nblocks)
+{
+#ifdef TRACE
+ fprintf (stderr, "allocate_block (%d)\n", nblocks);
+ fflush (stderr);
+#endif
+
+ return (malloc (nblocks * BYTES_PER_SECTOR));
+}
+
+/*** free_block - free a memory chunk allocated by allocate_block
+ *
+ * This function is called to free a block of memory which was
+ * allocated by the allocate_block function.
+ *
+ * BUGBUG - make this a macro to save stack and execution time?
+ *
+ * free_block (mem)
+ *
+ * ENTRY mem - pointer to memory to free
+ *
+ * EXIT No return value
+ *
+ * CALLS _ffree
+ *
+ * EFFECTS Deallocates memory
+ *
+ * WARNINGS "mem" will point to free space after this call
+ */
+void free_block (void *mem)
+{
+#ifdef TRACE
+ fprintf (stderr, "free_block ()\n");
+ fflush (stderr);
+#endif
+
+ free (mem);
+}
+
+/*** allocate_maps - allocate bit maps and disk map
+ *
+ * This function is called to allocate memory for both copies of
+ * the bitmap, as well as CHKDSK's internal disk map. The bit
+ * maps are not initialized, since they will be filled with disk
+ * data; the disk map is initialized to DISK_UNKNOWN.
+ *
+ * Memory for the bitmaps is allocate one block (2K) overlong so
+ * that reading the maps in will not overflow them.
+ *
+ * allocate_maps (nsects)
+ *
+ * ENTRY nsects - number of sectors in partition
+ *
+ * EXIT No return value
+ *
+ * CALLS malloc
+ * memset
+ *
+ * EFFECTS Allocates memory
+ * Initializes disk map
+ *
+ * WARNINGS May exit program if insufficient memory
+ */
+void allocate_maps (ULONG nsects)
+{
+ ULONG i;
+
+#ifdef TRACE
+ fprintf (stderr, "allocate_maps ()\n");
+ fflush (stderr);
+#endif
+
+ i = (nsects - 1L) / ((ULONG)BYTES_PER_BITMAP * 8L) + 2L;
+ if (((bitmap = calloc (i, 2048)) == NULL) ||
+ ((bitmap2 = calloc (i, 2048)) == NULL))
+ exit_error (INSF_MEM_ERROR);
+}
+
+/*** free_map - free a huge map
+ *
+ * This function is called to free memory allocated for a bit
+ * map with halloc.
+ *
+ * free_map (p)
+ *
+ * ENTRY p - pointer to memory to free
+ *
+ * EXIT No return value
+ *
+ * CALLS hfree
+ *
+ * EFFECTS Deallocates memory
+ */
+void free_map (void * p)
+{
+#ifdef TRACE
+ fprintf (stderr, "free_map ()\n");
+ fflush (stderr);
+#endif
+
+ if (p)
+ free (p);
+}
+
+/*** get_object - fill in currobj with information about an object
+ *
+ * This function is called to get a filesystem object off the disk
+ * and store information about it in the current object structure.
+ * It allocates memory for the object (or part of it, if it is a
+ * large object such as a big data run), and reads the object into
+ * memory. "currobj" is filled in with information about the object.
+ *
+ * If the memory pointer in currobj is already filled in, the memory
+ * is re-used, and data is read from the offset stored in currobj.
+ * This allows large data runs to be examined without reading the
+ * entire run into memory.
+ *
+ * This routine expects the "sec" and "len" fields of currobj to
+ * be set to point to the desired object before being called. If
+ * a new portion of an object is being paged in, "offset" must also
+ * be set; otherwise, "offset" is set to zero.
+ *
+ * The offset passed must be a multiple of one sector; allowing
+ * byte granularity would complicate this routine tremendously.
+ *
+ * get_object ()
+ *
+ * ENTRY No parameters
+ * currobj.sec, .len, and .offset set appropriately
+ *
+ * EXIT No return value
+ * currobj.mem, .offset filled in
+ *
+ * CALLS allocate_block
+ * read_scratch
+ *
+ * WARNINGS if (currobj.mem), offset % 512 must be zero
+ *
+ * EFFECTS Allocates memory
+ * Reads disk
+ * Changes global variable "currobj"
+ */
+void get_object ()
+{
+ ULONG l;
+
+ if (currobj.mem) { /* get different portion of object */
+ l = currobj.sec + currobj.offset; /* get sector address of what we want */
+ read_scratch (l, currobj.mem, SECTORS_PER_BLOCK); /* read 2K */
+ }
+ else { /* get new object */
+ l = (currobj.len > SECTORS_PER_BLOCK) ? SECTORS_PER_BLOCK : currobj.len;
+ currobj.mem = allocate_block (l);
+ read_scratch (currobj.sec, currobj.mem, l);
+ currobj.offset = 0L;
+ currobj.dirty = FALSE;
+ }
+}
diff --git a/private/sdktools/damage/sources b/private/sdktools/damage/sources
new file mode 100644
index 000000000..2f20273d5
--- /dev/null
+++ b/private/sdktools/damage/sources
@@ -0,0 +1,60 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=sdktools
+MINORCOMP=damage
+
+TARGETNAME=damage
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+SOURCES=cmd.c \
+ display.c \
+ glb.c \
+ io.c \
+ log.c \
+ map.c
+
+INCLUDES=\nt\public\sdk\inc
+GPSIZE=32
+
+!IFDEF NTDEBUG
+!IFDEF NOMEMLEAK
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX -DDBG
+!ELSE
+!IFDEF STACK_TRACE
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX -DDBG -DMEMLEAK -DSTACK_TRACE
+!ELSE
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX -DDBG -DMEMLEAK
+!ENDIF
+!ENDIF
+!ELSE
+C_DEFINES=-DCONDITION_HANDLING=1 -DNOMINMAX
+!ENDIF
+
+UMLIBS=obj\*\damage.lib
+
+UMTYPE=console
+
+UMAPPL=damage
diff --git a/private/sdktools/damage/superb.h b/private/sdktools/damage/superb.h
new file mode 100644
index 000000000..dcad0429e
--- /dev/null
+++ b/private/sdktools/damage/superb.h
@@ -0,0 +1,243 @@
+/********************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1987-1990 **/
+/********************************************************************/
+#define SEC_SUPERB 16 /* superblock is after 8K boot block */
+#define SEC_SPAREB 17 /* spareblock is after superblock */
+#define SEC_BOOT 0 /* boot sector */
+
+
+#define SUPERB_PWLEN 15
+
+
+/** SUPERB.INC - Super Block Definition
+ *
+ * The Superblock is the first block of the file system.
+ * It starts at sector #4, leaving 2K for boot sectors.
+ *
+ * Pointer to the root directory
+ * Pointer to the bit map
+ * Clean pointer
+ * Pointer to the bad list
+ */
+
+struct RSP {
+ unsigned long P; /* main psector pointer */
+ unsigned long P2; /* spare pointer */
+}; /* RSP */
+
+
+struct SuperB {
+ unsigned long SB_SIG1; /* signature value 1 */
+ unsigned long SB_SIG2; /* signature value 2 */
+
+ unsigned char SB_VER; /* version # of filesystem structures */
+ unsigned char SB_FVER; /* functional version number - the smallest/
+ * oldest version of the filesystem that can
+ * understand this disk - some version
+ * enhancements may define fields which can be
+ * ignored by earlier versions */
+
+ short SB_DUMY; /* free */
+
+ unsigned long SB_ROOT; /* Psector # of root fnode */
+
+ unsigned long SB_SEC; /* # of sectors on volume */
+ unsigned long SB_BSEC; /* # of bad sectors on volume */
+
+ struct RSP SB_BII; /* Bitmap Indirect Block */
+ struct RSP SB_BBL; /* badblock list chain #1 */
+
+ unsigned long SB_CDDAT; /* date of last CHKDSK */
+ unsigned long SB_DODAT; /* date of last Disk Optimize */
+
+ unsigned long SB_DBSIZE; /* # of sectors in dirblk band */
+ unsigned long SB_DBLOW; /* first Psector in DIRBLK band */
+ unsigned long SB_DBHIGH; /* last Psector in DIRBLK band */
+ unsigned long SB_DBMAP; /* first Psector of DIRBLK band bit map. Starts
+ * on a 2K boundary, 2K bytes maximum */
+
+ unsigned char SB_VOLNAME[32]; /* Volume name */
+
+ unsigned long SB_SIDSEC; /* sector # of first sector in SIDTAB */
+ /* ID map is 4K - 8 contiguous sectors */
+
+ unsigned char BlankSpace[512-100];
+ /* MUST BE ZERO */
+}; /* SuperB */
+
+
+
+/** SpareB - Spare Block Definitions
+ *
+ * SpareB contains various emergency supplies and fixup information.
+ * This stuff isn't in the superblock in order for the superblock
+ * to be read only and decrease the liklihood that a flakey write
+ * will cause the superblock to become unreadable.
+ *
+ * This sector is located directly after the superblock - sector 5.
+ *
+ * Note that the number of spare DIRBLKs is a format option, given
+ * that they all have to fit into the SpareB, giving us a max of
+ * 101 of them.
+ *
+ * Access to the SpareB is complicated by the fact that we can't
+ * access it via the cache, since the cache may be unavailable.
+ * If every cache buffer is dirty, we could get a HotFix error when
+ * writing the first one, which would deadlock us if we needed to
+ * read this stuff via the cache. Instead, we read it directly into
+ * a private buffer via RdHF.
+ *
+ * This means that the disk layout must be such that each cache cluster
+ * that contains the SpareB or the hotfix list must not contain any
+ * other writable sector, to prevent us from having a modified
+ * direct-written sector overwritten by an earlier unmodified copy
+ * which was in a cache block. It's ok for the SuperB to be in the
+ * same cache group as the SpareB since the SuperB is RO to the filesys.
+ *
+ * Checksums. Done on both Super Block and the Spare Block.
+ * Both checksums are stored in the Spare Block. The checksum
+ * field for the Super Block (SPB_SUPERBSUM) must be set when
+ * calculating the checksum for the Spare Block. The checksum
+ * field for the Spare Block (SPB_SPAREBSUM) must be zero when
+ * calculating the checksum for the Spare Block.
+ * If both checksum fields are zero, the checksums have not been
+ * calculated for the volume.
+ *
+ */
+
+#define SPAREDB 20 /* 20 spare DIRBLKs */
+
+struct SpareB {
+
+ unsigned long SPB_SIG1; /* signature value 1 */
+ unsigned long SPB_SIG2; /* signature value 2 */
+
+ unsigned char SPB_FLAG; /* cleanliness flag */
+ unsigned char SPB_ALIGN[3]; /* alignment */
+
+ unsigned long SPB_HFSEC; /* first hotfix list P sector */
+ unsigned long SPB_HFUSE; /* # of hot fixes in effect */
+ unsigned long SPB_HFMAX; /* max size of hot fix list */
+
+ unsigned long SPB_SDBCNT; /* # of spare dirblks */
+ unsigned long SPB_SDBMAX; /* maximum number of spare DB values. */
+ unsigned long SPB_CPSEC; /* code page sector */
+ unsigned long SPB_CPCNT; /* count of code pages on volume */
+ unsigned long SPB_SUPERBSUM; /* Checksum of Super Block */
+ unsigned long SPB_SPAREBSUM; /* Checksum of Spare Block */
+ unsigned long SPB_DUMY[15]; /* some extra space for future use */
+ unsigned long SPB_SPARDB[101]; /* Psector #s of spare dirblks */
+}; /* SpareB */
+
+
+/* Super Block and Spare Block Signatures */
+
+#define SBSIG1 0xf995e849 /* two signatures cause we got lotsa */
+#define SBSIG2 0xFA53E9C5 /* space */
+#define SPSIG1 0xf9911849 /* two signatures cause we got lotsa */
+#define SPSIG2 0xFA5229C5 /* space */
+
+
+
+/* Superblock Versions */
+
+#define SBBASEV 2 /* base version */
+#define SBBASEFV 2 /* base functional version */
+
+
+/* Superblock flags */
+
+#define SBF_LOCALSEC 1
+
+
+/* Spare Block Flags */
+
+#define SPF_DIRT 0x0001 /* file system is dirty */
+#define SPF_SPARE 0x0002 /* spare DIRBLKs have been used */
+#define SPF_HFUSED 0x0004 /* hot fix sectors have been used */
+#define SPF_BADSEC 0x0008 /* bad sector, corrupt disk */
+#define SPF_BADBM 0x0010 /* bad bitmap block */
+#define SPF_VER 0x0080 /* file system was written by a version
+ * < SB_VER, so some of the new fields
+ * may have not been updated */
+
+
+/** Bit maps
+ *
+ * PFS keeps track of free space in a series of bit maps.
+ * Currently, each bit map is 2048 bytes, which covers about
+ * 8 megabytes of disk space. We could rearrange these to be
+ * more cylinder sensitive...
+ *
+ * The superblock has the address of a section of contiguous sectors
+ * that contains a double word sector # for each bit map block. This
+ * will be a maximum of 2048 bytes (4 sectors)
+ *
+ * Max # of size RAM (K) size 2nd lvl
+ * bitmaps (meg) to reside bitmap
+ * bitmap (bytes)
+ *
+ * 1 8.39 2 256
+ * 2 16.78 4 512
+ * 3 25.17 6 768
+ * 4 33.55 8 1024
+ * 5 41.94 10 1280
+ * 6 50.33 12 1536
+ * 7 58.72 14 1792
+ * 8 67.11 16 2048
+ * 9 75.50 18 2304
+ * 10 83.89 20 2560
+ * 15 125.83 30 3840
+ * 20 167.77 40 5120
+ * 30 251.66 60 7680
+ * 40 335.54 80 10240
+ * 50 419.43 100 12800
+ * 100 838.86 200 25600
+ * 200 1677.72 400 51200
+ * 300 2516.58 600 76800
+ * 400 3355.44 800 102400
+ * 500 4194.30 1000 128000
+ */
+
+
+
+/** Hot Fixing
+ *
+ * Each file system maintains a structure listing N "hot fix"
+ * disk clusters of HOTFIXSIZ sectors each, each starting on
+ * a multiple of HOTFIXSIZ. Whenever the file system discovers
+ * that it's trying to write to a bad spot on the disk it will
+ * instead select a free hot fix cluster and write there, instead.
+ * The substitution will be recorded in the hot fix list, and the
+ * SBF_SPARE bit will be set. The file system sill describes the
+ * data as being in the bad old sectors; the disk interface will
+ * do a mapping between the `believed' location and the true location.
+ *
+ * CHKDSK will be run as soon as possible; it will move the
+ * hot fixed data from the hot fix cluster to somewhere else,
+ * freeing that hot fix cluster, and adjusting the disk structure
+ * to point to the new location of the data. As a result, entrys
+ * on the hot fix list should be transient and few.
+ *
+ * The superblock contains the # of the first sector of the hot fix list.
+ * The list takes the following format, spread across as many sectors
+ * as necessary:
+ *
+ * long oldsec[SB_HFMAX]; sector # of start of bad clusters
+ * long newsec[SB_HFMAX]; sector # of start of subst. cluster
+ * long fnode [SB_HFMAX]; fnode sector of file/directory
+ * involved with bad cluster. May be
+ * 0 (don't know) or invalid. The
+ * repair program must verify that it
+ * *is* an FNODE and must see if other
+ * structures might also involve this
+ * bad cluster.
+ *
+ * the SB_HFUSE field describes the number of these records which is
+ * in use - unused ones should have oldsec[i] = 0. The list will
+ * be 'dense' - no oldsec[i] will be 0 where i < SB_HFUSE.
+ *
+ * The sector(s) which contain the hot fix list must be contiguous
+ * and may not themselves be defective.
+ */
diff --git a/private/sdktools/damage/types.h b/private/sdktools/damage/types.h
new file mode 100644
index 000000000..05b194c5a
--- /dev/null
+++ b/private/sdktools/damage/types.h
@@ -0,0 +1,216 @@
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1990 **/
+/*****************************************************************/
+/*** TYPES.H - definitions of types used internally.
+ *
+ * DAMAGE
+ * Gregory A. Jones
+ *
+ * Modification history:
+ * G.A. Jones 09/07/88 Adapted from Pinball CHKDSK.
+ * G.A. Jones 09/13/88 Added "scratch" field to object struct.
+ * G.A. Jones 09/19/88 Added "dirty" field to object struct.
+ * G.A. Jones 10/14/88 Fixed array limit on diskpkt.
+ */
+
+#include <codepage.h>
+
+#include <fnode.h>
+#include <dir.h>
+#include <superb.h>
+
+union blk { /* this is a generic structure to read a block into */
+ struct DIRBLK d; /* a dirblk, */
+ struct FNODE f; /* an fnode, */
+ struct ALSEC a; /* and indirection block in one package */
+};
+
+struct mem_blk { /* general structure to keep a tree node in */
+ struct mem_blk *next; /* next disk fragment in linked list */
+ ULONG psn; /* where we found the block on the disk */
+ USHORT children; /* number of children this block needs */
+ USHORT parent; /* non-zero if this block needs a parent */
+ union blk blk; /* the actual structure from the disk */
+ struct mem_blk *childlist; /* linked list of child structures */
+};
+
+union dp { /* structure used for walking through directories */
+ struct DIRENT *d; /* a DIRENT pointer for structure access */
+ UCHAR *p; /* and a character pointer for pointer arithmetic */
+};
+
+struct part {
+ UCHAR bootind;
+ UCHAR starthead;
+ UCHAR startsect;
+ UCHAR startcyl;
+ UCHAR systind;
+ UCHAR endhead;
+ UCHAR endsect;
+ UCHAR endcyl;
+ ULONG lsn;
+ ULONG nsects;
+};
+
+struct mbr { /* the structure of an MBR */
+ UCHAR brec [0x1be]; /* code and data for boot record program */
+ struct part ptbl [4]; /* the partition table */
+ USHORT sig; /* boot record signature */
+};
+
+struct diskpacket {
+ UCHAR cmdinfo;
+ USHORT head;
+ USHORT cyl;
+ USHORT sect;
+ USHORT nsect;
+ struct {
+ USHORT sect;
+ USHORT size;
+ } map [MAX_SECTORS_PER_TRACK];
+};
+
+struct parmpacket {
+ USHORT reserved1;
+ USHORT ncyl;
+ USHORT nh;
+ USHORT spt;
+ USHORT reserved2 [4];
+};
+
+struct bpb {
+ USHORT bytes_per_sector;
+ UCHAR sectors_per_cluster; /* ignored by Pinball */
+ USHORT reserved_sectors;
+ UCHAR number_of_FATS; /* zeroed by Pinball */
+ USHORT root_entries; /* zeroed by Pinball */
+ USHORT short_total_sectors; /* zeroed by Pinball */
+ UCHAR media_descriptor;
+ USHORT sectors_per_FAT; /* zeroed by Pinball */
+ USHORT sectors_per_track;
+ USHORT heads;
+ ULONG hidden_sectors; /* refers to sectors on physical disk
+ prior to the logical disk */
+ ULONG total_sectors;
+};
+
+struct device_param {
+ struct bpb dev_bpb;
+ UCHAR reserved [6];
+ USHORT num_cylinders;
+ UCHAR device_type; /* hi floppy, lo floppy, fixed etc */
+ USHORT device_attr; /* removable flag, detect change flag */
+};
+
+struct object { /* information about an object */
+ USHORT type; /* which type it is (TYPE_xxxx in DEFS.H) */
+ ULONG sec; /* where it is on disk */
+ ULONG len; /* how long it is */
+ ULONG offset; /* in bytes for DIRBLKs, sectors for runs */
+ void *mem; /* pointer to memory image of the object */
+ USHORT scratch; /* miscellaneous - bitmap number, etc. */
+ USHORT dirty; /* set if object changed */
+};
+
+struct vioprm { /* parameters to VIOSETMODE */
+ USHORT length;
+ UCHAR type;
+ UCHAR color;
+ USHORT cols;
+ USHORT rows;
+ USHORT horiz;
+ USHORT vert;
+};
+
+struct SuperSpare { /* general structure for beginning of the disk */
+ struct SuperB sb; /* the superblock comes first */
+ struct SpareB spb; /* the spareblock immediately after */
+};
+
+
+
+// Function prototypes:
+
+
+// from cmd.c:
+
+UCHAR getcmdch ();
+void new_currobj ( USHORT item );
+void fence_bits ();
+void mark_as_bad (USHORT item, ULONG ulMask);
+USHORT displayable (USHORT item);
+void change_item (USHORT item);
+void cant_backout ();
+USHORT get_item ();
+void cant_display (USHORT item);
+void cant_mark(USHORT item);
+USHORT get_command ();
+void next_field ();
+void prev_field ();
+void revert ();
+void copy_sectors ();
+void display ();
+
+// from display.c:
+
+UCHAR *get_time(ULONG time);
+void sb_flags (ULONG flags);
+void ab_flags (UCHAR flags);
+void dir_flags (ULONG flags);
+void display_object ();
+
+
+// from io.c:
+
+BOOLEAN
+open_disk(
+ char* DosDriveName,
+ BOOLEAN WriteAccess
+ );
+
+BOOLEAN
+read_scratch(
+ ULONG Lbn,
+ void* UserBuffer,
+ ULONG NumberOfSectors
+ );
+
+BOOLEAN
+write_scratch(
+ ULONG Lbn,
+ void* UserBuffer,
+ ULONG NumberOfSectors
+ );
+
+BOOLEAN
+lock_disk(
+ );
+
+void
+close_disk(
+ );
+
+void
+write_log(USHORT item);
+
+
+// from log.c:
+
+UCHAR log_getch();
+void log_gets(UCHAR *s);
+
+
+// from map.c:
+
+USHORT clr_bit (ULONG lsn);
+USHORT set_bit (ULONG lsn);
+void *allocate_block (USHORT nblocks);
+void free_block (void *mem);
+void allocate_maps (ULONG nsects);
+void free_map (void * p);
+void get_object ();
+
+// from damage.c:
+
+void exit_error (USHORT code);