diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/sdktools/damage | |
download | NT4.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.h | 258 | ||||
-rw-r--r-- | private/sdktools/damage/cdib.h | 260 | ||||
-rw-r--r-- | private/sdktools/damage/cmd.c | 1762 | ||||
-rw-r--r-- | private/sdktools/damage/codepage.h | 192 | ||||
-rw-r--r-- | private/sdktools/damage/const.h | 201 | ||||
-rw-r--r-- | private/sdktools/damage/damage.c | 218 | ||||
-rw-r--r-- | private/sdktools/damage/defs.h | 260 | ||||
-rw-r--r-- | private/sdktools/damage/dir.h | 138 | ||||
-rw-r--r-- | private/sdktools/damage/display.c | 724 | ||||
-rw-r--r-- | private/sdktools/damage/fnode.h | 183 | ||||
-rw-r--r-- | private/sdktools/damage/glb.c | 468 | ||||
-rw-r--r-- | private/sdktools/damage/globals.h | 85 | ||||
-rw-r--r-- | private/sdktools/damage/io.c | 612 | ||||
-rw-r--r-- | private/sdktools/damage/log.c | 55 | ||||
-rw-r--r-- | private/sdktools/damage/makefile | 6 | ||||
-rw-r--r-- | private/sdktools/damage/map.c | 283 | ||||
-rw-r--r-- | private/sdktools/damage/sources | 60 | ||||
-rw-r--r-- | private/sdktools/damage/superb.h | 243 | ||||
-rw-r--r-- | private/sdktools/damage/types.h | 216 |
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); |