summaryrefslogtreecommitdiffstats
path: root/private/sdktools/he
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/sdktools/he
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/sdktools/he')
-rw-r--r--private/sdktools/he/he.c386
-rw-r--r--private/sdktools/he/he.rc11
-rw-r--r--private/sdktools/he/hexedit.c2156
-rw-r--r--private/sdktools/he/hexedit.h79
-rw-r--r--private/sdktools/he/makefile6
-rw-r--r--private/sdktools/he/makefile.inc2
-rw-r--r--private/sdktools/he/sources27
7 files changed, 2667 insertions, 0 deletions
diff --git a/private/sdktools/he/he.c b/private/sdktools/he/he.c
new file mode 100644
index 000000000..e8c595d16
--- /dev/null
+++ b/private/sdktools/he/he.c
@@ -0,0 +1,386 @@
+
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1991 **/
+/*****************************************************************/
+
+/**** he - HexEdit a file
+ *
+ * Wrapper to HexEdit function to allow file (or drive) editting
+ *
+ * Written: Ken Reneris
+ *
+ */
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdddisk.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <process.h>
+#include <windows.h>
+#include "hexedit.h"
+
+NTSTATUS fncRead(), fncWrite(), fncWriteDASD();
+
+void EditFile (char *name);
+void ReadIni ();
+
+WORD vAttrList, vAttrTitle, vAttrHigh;
+
+VOID _CRTAPI1
+main (argc, argv)
+USHORT argc;
+char *argv[];
+{
+ char *argument = argv[1];
+
+ if (argc < 2) {
+ printf ("he fname\n");
+ exit (1);
+ }
+
+ ReadIni ();
+
+ if ((strncmp(argv[1], "\\\\.\\", 4)) == 0) {
+ char *cp;
+ int index;
+
+ // Insure there is a backslash on the DosName being opened.
+ for (cp = argv[1], index = 0; *cp; *cp++, index++) {
+ // action in for loop
+ }
+ cp--;
+ if (*cp != '\\') {
+
+ // Need to add backslash to name.
+
+ argument = GlobalAlloc (0,index + 4);
+ for (cp = argv[1], index = 0; argument[index] = *cp; *cp++, index++) {
+ // action in for loop
+ }
+ argument[index] = '\\';
+ argument[index + 1] = '\0';
+ }
+ }
+ EditFile (argument);
+}
+
+
+
+void
+EditFile (
+ char *name
+ )
+{
+ FILE_ALIGNMENT_INFORMATION AlignmentInfo;
+ DISK_GEOMETRY DiskGeo;
+ LARGE_INTEGER li;
+ struct HexEditParm ei;
+ USHORT rc, rc1, i, l;
+ PWSTR WideName;
+ OBJECT_ATTRIBUTES oa;
+ NTSTATUS status;
+ UNICODE_STRING NtDriveName;
+ ANSI_STRING NtDriveNameAnsi;
+ IO_STATUS_BLOCK status_block;
+
+
+ //
+ // Try to open & edit as regular filename
+ //
+
+ memset ((PUCHAR) &ei, 0, sizeof (ei));
+ ei.ename = name;
+ ei.flag = FHE_VERIFYONCE | FHE_SAVESCRN | FHE_JUMP;
+ ei.read = fncRead;
+ ei.write = fncWrite;
+ ei.ioalign = 1;
+ ei.Console = INVALID_HANDLE_VALUE;
+ ei.AttrNorm = vAttrList;
+ ei.AttrHigh = vAttrTitle;
+ ei.AttrReverse = vAttrHigh;
+
+ ei.handle = CreateFile (
+ name,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+
+ if (ei.handle == INVALID_HANDLE_VALUE) {
+ // Try for just read access
+
+ ei.handle = CreateFile (
+ name,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+ }
+
+
+ if (ei.handle != INVALID_HANDLE_VALUE) {
+ ei.totlen = SetFilePointer (ei.handle, 0, NULL, FILE_END);
+ HexEdit (&ei);
+ return ;
+ }
+ rc = (USHORT)GetLastError ();
+
+ //
+ // Try expanding the name from dosname to ntname.
+ // Since regular name failed, assume a sector edit
+ //
+ l = strlen(name)+1;
+ WideName = GlobalAlloc (0,l * sizeof(WCHAR));
+
+ for(i=0; i < l; i++)
+ WideName[i] = name[i];
+
+ // OK, now get the corresponding NT name
+ rc1 = RtlDosPathNameToNtPathName_U (
+ WideName,
+ &NtDriveName,
+ NULL,
+ NULL );
+
+ if (!rc1) {
+ printf ("Open error %d\n", rc);
+ exit (rc);
+ }
+
+
+ // If the NT drive name has a trailing backslash, remove it.
+ l = NtDriveName.Length/sizeof(WCHAR);
+ if( NtDriveName.Buffer[l-1] == '\\' ) {
+
+ NtDriveName.Buffer[l-1] = 0;
+ NtDriveName.Length -= sizeof(WCHAR);
+ }
+
+ InitializeObjectAttributes(
+ &oa,
+ &NtDriveName,
+ OBJ_CASE_INSENSITIVE,
+ 0,
+ 0 );
+
+ status = NtOpenFile(
+ &ei.handle,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ &oa,
+ &status_block,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT );
+
+ if (!NT_SUCCESS(status)) {
+ // try for just read access
+
+ status = NtOpenFile(
+ &ei.handle,
+ SYNCHRONIZE | FILE_READ_DATA,
+ &oa,
+ &status_block,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT );
+ }
+
+ if (!NT_SUCCESS(status)) {
+ NtDriveName.Length = strlen(name) * sizeof(WCHAR);
+ NtDriveName.Buffer = WideName;
+
+ InitializeObjectAttributes(
+ &oa,
+ &NtDriveName,
+ OBJ_CASE_INSENSITIVE,
+ 0,
+ 0 );
+
+ status = NtOpenFile(
+ &ei.handle,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ &oa,
+ &status_block,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT );
+
+ if (!NT_SUCCESS(status)) {
+ // try for just read access
+
+ status = NtOpenFile(
+ &ei.handle,
+ SYNCHRONIZE | FILE_READ_DATA,
+ &oa,
+ &status_block,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT );
+ }
+ }
+
+
+ RtlUnicodeStringToAnsiString (&NtDriveNameAnsi, &NtDriveName, TRUE);
+ ei.ename = NtDriveNameAnsi.Buffer;
+
+ if (!NT_SUCCESS(status)) {
+ printf ("%s open error %lx\n", ei.ename, status);
+ exit (status);
+ }
+
+ NtQueryInformationFile(
+ ei.handle,
+ &status_block,
+ &AlignmentInfo,
+ sizeof( AlignmentInfo ),
+ FileAlignmentInformation );
+
+ ei.ioalign = AlignmentInfo.AlignmentRequirement;
+
+ status = NtDeviceIoControlFile(
+ ei.handle,
+ 0,
+ NULL,
+ NULL,
+ &status_block,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ &DiskGeo,
+ sizeof( DiskGeo ) );
+
+
+ if (NT_SUCCESS(status)) {
+ li = RtlExtendedIntegerMultiply (DiskGeo.Cylinders,
+ DiskGeo.TracksPerCylinder);
+
+ li = RtlExtendedIntegerMultiply (li, DiskGeo.SectorsPerTrack);
+ li = RtlExtendedIntegerMultiply (li, DiskGeo.BytesPerSector);
+
+ ei.totlen = li.LowPart;
+ } else {
+ ei.totlen = SetFilePointer (ei.handle, 0, NULL, FILE_END);
+ }
+
+ ei.flag = FHE_VERIFYALL | FHE_PROMPTSEC | FHE_SAVESCRN | FHE_JUMP;
+ HexEdit (&ei);
+}
+
+
+NTSTATUS fncRead (h, loc, data, len, ploc)
+HANDLE h;
+DWORD len, loc;
+char *data;
+ULONG *ploc;
+{
+ DWORD l, br;
+
+ l = SetFilePointer (h, loc, NULL, FILE_BEGIN);
+ if (l == -1)
+ return GetLastError();
+
+ if (!ReadFile (h, data, len, &br, NULL))
+ return GetLastError();
+
+ return (br != len ? ERROR_READ_FAULT : 0);
+}
+
+
+NTSTATUS fncWrite (h, loc, data, len, ploc)
+HANDLE h;
+DWORD len, loc;
+char *data;
+ULONG ploc;
+{
+ DWORD l, bw;
+
+ l = SetFilePointer (h, loc, NULL, FILE_BEGIN);
+ if (l == -1)
+ return GetLastError();
+
+ if (!WriteFile (h, data, len, &bw, NULL))
+ return GetLastError();
+
+ return (bw != len ? ERROR_WRITE_FAULT : 0);
+}
+
+
+
+/*** xtoi - Hex to int
+ *
+ * Entry:
+ * pt - pointer to hex number
+ *
+ * Return:
+ * value of hex number
+ *
+ */
+unsigned xtoi (pt)
+char *pt;
+{
+ unsigned u;
+ char c;
+
+ u = 0;
+ while (c = *(pt++)) {
+ if (c >= 'a' && c <= 'f')
+ c -= 'a' - 'A';
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
+ u = u << 4 | c - (c >= 'A' ? 'A'-10 : '0');
+ }
+ return (u);
+}
+
+
+void
+ReadIni ()
+{
+ static char Delim[] = " :=;\t\r\n";
+ FILE *fp;
+ char *env, *verb, *value;
+ char s [200];
+ long l;
+
+
+ env = getenv ("INIT");
+ if (env == NULL)
+ return;
+
+ strcpy (s, env);
+ strcat (s, "\\TOOLS.INI"); // just use list ini section
+ fp = fopen (s, "r");
+ if (fp == NULL)
+ return;
+
+ while (fgets (s, 200, fp) != NULL) {
+ if (s[0] != '[')
+ continue;
+ _strupr (s);
+ if (strstr (s, "LIST") == NULL)
+ continue;
+ /*
+ * ini file found w/ "list" keyword. Now read it.
+ */
+ while (fgets (s, 200, fp) != NULL) {
+ if (s[0] == '[')
+ break;
+ verb = strtok (s, Delim);
+ value = strtok (NULL, Delim);
+ if (verb == NULL)
+ continue;
+ if (value == NULL)
+ value = "";
+
+ _strupr (verb);
+ if (strcmp (verb, "LCOLOR") == 0) vAttrList = (WORD)xtoi(value);
+ else if (strcmp (verb, "TCOLOR") == 0) vAttrTitle= (WORD)xtoi(value);
+ else if (strcmp (verb, "HCOLOR") == 0) vAttrHigh = (WORD)xtoi(value);
+ }
+ break;
+ }
+ fclose (fp);
+}
diff --git a/private/sdktools/he/he.rc b/private/sdktools/he/he.rc
new file mode 100644
index 000000000..d091b2e70
--- /dev/null
+++ b/private/sdktools/he/he.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Hex Editor"
+
+#define VER_INTERNALNAME_STR "he.exe"
+#define VER_ORIGINALFILENAME_STR "he.exe"
+
+#include <common.ver>
diff --git a/private/sdktools/he/hexedit.c b/private/sdktools/he/hexedit.c
new file mode 100644
index 000000000..68af558f1
--- /dev/null
+++ b/private/sdktools/he/hexedit.c
@@ -0,0 +1,2156 @@
+
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1990 **/
+/*****************************************************************/
+
+/**** hexedit.c - Generic sector based hex editor function call
+ *
+ * Fill out a HexEditParm structure, and call HexEdit. It provides
+ * a simple hex editor with a few misc features.
+ *
+ * Is single threaded & non-reentrant, but can be called from any thread.
+ *
+ * External uses:
+ * he - allows editing of a file
+ *
+ * Written: Ken Reneris 2/25/91
+ *
+ */
+
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <stdio.h>
+#include <windows.h>
+#include "hexedit.h"
+#include <stdarg.h>
+
+#define LOCAL static
+// #define LOCAL
+
+#define BUFSZ 512
+#define SECTORMASK 0xFFFFFE00L
+#define SECTORSHIFT 9
+
+static UCHAR rghexc[] = "0123456789ABCDEF";
+
+struct Buffer {
+ struct Buffer *next;
+ ULONG offset;
+ ULONG physloc;
+ USHORT flag;
+ USHORT len;
+ UCHAR *data;
+ UCHAR orig [BUFSZ];
+} ;
+#define FB_DIRTY 0x0001 // Buffer may be dirty
+#define FB_BAD 0x0002 // Buffer had an error when read in
+
+#define LINESZ 16 // 16 bytes per display line
+#define LINESHIFT 4L
+#define LINEMASK 0xFFFFFFF0L
+#define CELLPERLINE 80
+
+struct Global {
+ struct HexEditParm *Parm;
+ HANDLE Console; // Internal console handle
+ HANDLE StdIn;
+ NTSTATUS (*Read)(); // Copy of HeGbl.Parm->read
+ ULONG Flag; // Copy of HeGbl.Parm->flag
+ ULONG TotLen; // Sizeof item being editted
+ ULONG TotLen1; // Sizeof item being editted - 1
+ USHORT Lines; // # of lines in edit screen
+ USHORT LineTot; // # of lines totaly in use
+ USHORT PageSz; // sizeof page in bytes
+ USHORT TopLine; // TopLine edit starts at
+ ULONG CurOffset; // Relative offset of first line
+ ULONG CurEditLoc; // Location with cursor
+ UCHAR *CurPT; // Pointer to data where cursor is
+ UCHAR CurAscIndent;
+ UCHAR DWidth; // width of dispalymode
+ UCHAR na;
+ struct Buffer *CurBuf; // Buffer which cursor is in
+ ULONG CurFlag; // Cursor info
+ ULONG DisplayMode; // Mask of displaymode
+ ULONG ItemWrap; // Mask of displaymode wrap
+ UCHAR rgCols[LINESZ]; // Location within lines
+ ULONG UpdatePos; // Location waitin to be updated
+ struct Buffer *Buf; // List of buffer's read in
+ PCHAR_INFO pVioBuf; // Virtual screen
+ COORD dwVioBufSize; // Dimensions of HeGbl.pVioBuf
+ COORD CursorPos; // Position of cursor
+ WORD AttrNorm; // Attribute of plain text
+ WORD AttrHigh; // Attribute of highlighted text
+ WORD AttrReverse; // Attribute of reverse text
+ WORD na3;
+ COORD dwSize; // Original screen size
+ ULONG OrigMode; // Original screen mode
+ CONSOLE_CURSOR_INFO CursorInfo; // Original cursor info
+ PUCHAR SearchPattern;
+} HeGbl;
+
+#define D_BYTE 0 // DisplayMode
+#define D_WORD 1
+#define D_DWORD 3
+
+#define FC_NIBBLE 0x0001 // Cursor on lower or upper nibble?
+#define FC_TEXT 0x0002 // Cursor on Hex or Text
+#define FC_INFLUSHBUF 0x1000 // So we don't recurse
+#define FC_CURCENTER 0x2000 // if jumping to cursor, put in center
+
+#define PUTCHAR(a,b,c) { a->Char.AsciiChar=b; a->Attributes=c; a++; }
+
+
+//
+// Internal prototypes
+//
+
+int heUpdateStats(), hePositionCursor(), heRefresh(), heSetDisp();
+int heInitConsole(), heUpdateAllLines(), heInitScr(), heSetCursorBuf(), heUpdateFncs();
+VOID _CRTAPI1 heDisp (USHORT, USHORT, PUCHAR, ...);
+USHORT heIOErr (UCHAR *str, ULONG loc, ULONG ploc, ULONG errcd);
+
+int heFlushBuf (struct Buffer *pBuf);
+
+VOID heEndConsole(), heGotoPosition(), heJumpToLink();
+VOID heUpdateCurLine(), heUndo(), heCopyOut(), heCopyIn(), heSearch();
+VOID heBox (USHORT x, USHORT y, USHORT len_x, USHORT len_y);
+UCHAR heGetChar (PUCHAR keys);
+VOID heFlushAllBufs (USHORT update);
+VOID heFindMousePos (COORD);
+VOID heShowBuf (ULONG, ULONG);
+VOID heSetDisplayMode (ULONG mode);
+
+#define RefreshDisp() heShowBuf(0, HeGbl.LineTot)
+#define SetCurPos(a,b) { \
+ HeGbl.CursorPos.X = b; \
+ HeGbl.CursorPos.Y = a + HeGbl.TopLine; \
+ SetConsoleCursorPosition (HeGbl.Console, HeGbl.CursorPos); \
+ }
+
+
+int (*vrgUpdateFnc[])() = {
+ NULL, // 0 - No update
+ heUpdateStats, // 1 - Update stats
+ hePositionCursor, // 2 - Cursor has new position
+ heUpdateAllLines, // 3 - Update all lines
+ heUpdateFncs, // 4 -
+ hePositionCursor, // 5 - Calc cursor before AllLines
+ heRefresh, // 6 - Clear lines
+ heSetDisp, // 7 - Draws init screen
+ // the following functions are only called once during init
+ heInitScr, // 8 - get's video mode, etc.
+ heInitConsole // 9 - setup console handle
+} ;
+
+#define U_NONE 0
+#define U_NEWPOS 2
+#define U_SCREEN 5
+#define U_REDRAW 9
+
+
+#define TOPLINE 4
+#define LINEINDENT 1
+#define HEXINDENT (10 + LINEINDENT)
+#define ASCINDENT_BYTE (3*16 + HEXINDENT + 1)
+#define ASCINDENT_WORD (5*8 + HEXINDENT + 1)
+#define ASCINDENT_DWORD (9*4 + HEXINDENT + 1)
+
+#define POS(l,c) (HeGbl.pVioBuf+CELLPERLINE*(l)+c)
+
+USHORT vrgAscIndent[] = {
+ ASCINDENT_BYTE, ASCINDENT_WORD, 0, ASCINDENT_DWORD
+ };
+
+UCHAR vrgDWidth[] = { 2, 4, 0, 8 };
+
+LOCAL struct Buffer *vBufFree; // List of free buffers
+LOCAL USHORT vUpdate;
+LOCAL USHORT vRecurseLevel = 0;
+LOCAL BOOL vInSearch = FALSE;
+
+
+/*
+ * Prototypes
+ */
+
+struct Buffer *heGetBuf (ULONG);
+void heSetUpdate (USHORT);
+void heHexLine (struct Buffer *, USHORT, USHORT);
+void heHexDWord (PCHAR_INFO, ULONG, WORD);
+USHORT heLtoa (PCHAR_INFO, ULONG);
+ULONG heHtou (UCHAR *);
+VOID heCalcCursorPosition ();
+VOID heGetString (PUCHAR s, USHORT len);
+VOID heRightOne ();
+VOID heLeftOne ();
+NTSTATUS heWriteFile (HANDLE h, PUCHAR buffer, ULONG len);
+NTSTATUS heReadFile (HANDLE h, PUCHAR buffer, ULONG len, PULONG br);
+NTSTATUS heOpenFile (PUCHAR Name, PHANDLE handle, ULONG access);
+
+
+
+/***
+ *
+ * HexEdit - Full screen HexEdit of data
+ *
+ * ename - pointer to name of what's being edited
+ * totlen - length of item being edited
+ * pRead - function which can read data from item
+ * pWrite - function which can write data to item
+ * handle - handle to pass to pRead & pWrite
+ * flag -
+ *
+ *
+ * All IO is assumed to be done on in 512 bytes on 512 byte boundrys
+ *
+ * pRead (handle, offset, data, &physloc)
+ * pWrite (handle, offset, data, &physloc)
+ *
+ */
+
+void HexEdit (pParm)
+struct HexEditParm *pParm;
+{
+ USHORT rc;
+ INPUT_RECORD Kd;
+ USHORT SkipCnt;
+ DWORD cEvents;
+ USHORT RepeatCnt;
+ BOOL bSuccess;
+ struct Global *PriorGlobal;
+
+ // code is not multi-threaded capable, but it can resurse.
+ vRecurseLevel++;
+ if (vRecurseLevel > 1) {
+ PriorGlobal = (struct Global *) GlobalAlloc (0, sizeof (HeGbl));
+ memcpy ((PUCHAR) PriorGlobal, (PUCHAR) &HeGbl, sizeof (HeGbl));
+ }
+
+ memset (&HeGbl, 0, sizeof (HeGbl));
+
+ HeGbl.Parm = pParm;
+ HeGbl.Flag = pParm->flag;
+ HeGbl.TotLen = pParm->totlen;
+ HeGbl.Read = pParm->read;
+ HeGbl.TotLen1 = HeGbl.TotLen ? HeGbl.TotLen - 1L : 0L;
+ pParm->flag = 0;
+
+ HeGbl.CurEditLoc = pParm->start; // Cursor starts here
+ HeGbl.CurOffset = HeGbl.CurEditLoc & LINEMASK; // Start at valid offset
+ HeGbl.CurFlag = FC_NIBBLE;
+ HeGbl.Console = INVALID_HANDLE_VALUE;
+ heSetDisplayMode ((HeGbl.Flag & FHE_DWORD) ? D_DWORD : D_BYTE);
+
+ HeGbl.AttrNorm = pParm->AttrNorm ? pParm->AttrNorm : 3;
+ HeGbl.AttrHigh = pParm->AttrHigh ? pParm->AttrHigh : 15;
+ HeGbl.AttrReverse = pParm->AttrReverse ? pParm->AttrReverse : 112;
+
+ HeGbl.SearchPattern = GlobalAlloc (0, 512);
+ memset (HeGbl.SearchPattern, 0, 512);
+
+ RepeatCnt = 0;
+ vUpdate = U_REDRAW;
+ heSetUpdate (U_NONE); // get screen to redraw
+
+ for (; ;) {
+ if (RepeatCnt <= 1) {
+ if (vUpdate != U_NONE) { // Something to update?
+
+ if (SkipCnt++ > 10) {
+ SkipCnt = 0;
+ heSetUpdate (U_NONE);
+ continue;
+ }
+
+ cEvents = 0;
+ bSuccess = PeekConsoleInput( HeGbl.StdIn,
+ &Kd,
+ 1,
+ &cEvents );
+
+ if (!bSuccess || cEvents == 0) {
+ heSetUpdate ((USHORT)(vUpdate-1));
+ continue;
+ }
+ } else {
+ SkipCnt = 0;
+ }
+
+ ReadConsoleInput (HeGbl.StdIn, &Kd, 1, &cEvents);
+
+ if (Kd.EventType != KEY_EVENT) {
+
+ if (Kd.EventType == MOUSE_EVENT &&
+ (Kd.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)) {
+ heFindMousePos(Kd.Event.MouseEvent.dwMousePosition);
+ }
+
+ continue; // Not a key
+ }
+
+
+ if (!Kd.Event.KeyEvent.bKeyDown)
+ continue; // Not a down stroke
+
+ if (Kd.Event.KeyEvent.wVirtualKeyCode == 0 || // ALT
+ Kd.Event.KeyEvent.wVirtualKeyCode == 0x10 || // SHIFT
+ Kd.Event.KeyEvent.wVirtualKeyCode == 0x11 || // CONTROL
+ Kd.Event.KeyEvent.wVirtualKeyCode == 0x14) // CAPITAL
+ continue;
+
+ RepeatCnt = Kd.Event.KeyEvent.wRepeatCount;
+ if (RepeatCnt > 20)
+ RepeatCnt = 20;
+ } else
+ RepeatCnt--;
+
+ switch (Kd.Event.KeyEvent.wVirtualKeyCode) {
+ case 0x21: /* PgUp */
+ if (HeGbl.CurOffset < HeGbl.PageSz)
+ HeGbl.CurOffset = 0L;
+ else HeGbl.CurOffset -= HeGbl.PageSz;
+
+ if (HeGbl.CurEditLoc < HeGbl.PageSz)
+ HeGbl.CurEditLoc = 0L;
+ else HeGbl.CurEditLoc -= HeGbl.PageSz;
+
+ heSetUpdate (U_SCREEN);
+ continue;
+
+ case 0x26: /* Up */
+ if (HeGbl.CurEditLoc >= LINESZ) {
+ HeGbl.CurEditLoc -= LINESZ;
+ heSetUpdate (U_NEWPOS);
+ }
+ continue;
+
+ case 0x22: /* PgDn */
+ if (HeGbl.TotLen > HeGbl.PageSz) {
+ if (HeGbl.CurOffset+HeGbl.PageSz+HeGbl.PageSz > HeGbl.TotLen1)
+ HeGbl.CurOffset = ((HeGbl.TotLen1-HeGbl.PageSz) & LINEMASK)+LINESZ;
+ else HeGbl.CurOffset += HeGbl.PageSz;
+
+ if (HeGbl.CurEditLoc+HeGbl.PageSz > HeGbl.TotLen1) {
+ HeGbl.CurEditLoc = HeGbl.TotLen1;
+ HeGbl.CurFlag &= ~FC_NIBBLE;
+ } else
+ HeGbl.CurEditLoc += HeGbl.PageSz;
+
+ heSetUpdate (U_SCREEN);
+ }
+ continue;
+
+
+ case 0x28: /* Down */
+ if (HeGbl.CurEditLoc+LINESZ <= HeGbl.TotLen1) {
+ HeGbl.CurEditLoc += LINESZ;
+ heSetUpdate (U_NEWPOS);
+ }
+ continue;
+
+ case 0x08: /* backspace */
+ case 0x25: /* Left */
+ if (HeGbl.CurFlag & FC_TEXT) {
+ if (HeGbl.CurEditLoc == 0L)
+ continue;
+
+ HeGbl.CurEditLoc--;
+ heSetUpdate (U_NEWPOS);
+ continue;
+ }
+
+ if (!(HeGbl.CurFlag & FC_NIBBLE)) {
+ HeGbl.CurFlag |= FC_NIBBLE;
+ heSetUpdate (U_NEWPOS);
+ continue;
+ }
+
+ HeGbl.CurFlag &= ~FC_NIBBLE;
+ heLeftOne ();
+ heSetUpdate (U_NEWPOS);
+ continue;
+
+
+ case 0x27: /* Right */
+ if (HeGbl.CurFlag & FC_TEXT) {
+ if (HeGbl.CurEditLoc >= HeGbl.TotLen1)
+ continue;
+
+ HeGbl.CurEditLoc++;
+ heSetUpdate (U_NEWPOS);
+ continue;
+ }
+
+ if (HeGbl.CurFlag & FC_NIBBLE) {
+ HeGbl.CurFlag &= ~FC_NIBBLE;
+ heSetUpdate (U_NEWPOS);
+ continue;
+ }
+
+ HeGbl.CurFlag |= FC_NIBBLE;
+ heRightOne ();
+ heSetUpdate (U_NEWPOS);
+ continue;
+
+ case 0x24: /* HOME */
+ if (Kd.Event.KeyEvent.dwControlKeyState &
+ (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) {
+ HeGbl.CurEditLoc = 0L;
+ } else {
+ HeGbl.CurEditLoc &= LINEMASK;
+ }
+
+ if ((HeGbl.CurFlag & FC_TEXT) == 0)
+ HeGbl.CurEditLoc += HeGbl.DisplayMode;
+
+ if (HeGbl.CurEditLoc > HeGbl.TotLen1)
+ HeGbl.CurEditLoc = HeGbl.TotLen1;
+
+ HeGbl.CurFlag |= FC_NIBBLE;
+ heSetUpdate (U_NEWPOS);
+ continue;
+
+
+ case 0x23: /* END */
+ if (Kd.Event.KeyEvent.dwControlKeyState &
+ (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) {
+ HeGbl.CurEditLoc = HeGbl.TotLen1;
+ } else {
+ HeGbl.CurEditLoc = (HeGbl.CurEditLoc & LINEMASK) + LINESZ - 1;
+ }
+
+ HeGbl.CurFlag &= ~FC_NIBBLE;
+ if ((HeGbl.CurFlag & FC_TEXT) == 0)
+ HeGbl.CurEditLoc -= HeGbl.DisplayMode;
+
+ if (HeGbl.CurEditLoc > HeGbl.TotLen1)
+ HeGbl.CurEditLoc = HeGbl.TotLen1;
+
+ heSetUpdate (U_NEWPOS);
+ continue;
+
+ case 0x70: /* F1 */
+ switch (HeGbl.DisplayMode) {
+ case D_BYTE: heSetDisplayMode(D_WORD); break;
+ case D_WORD: heSetDisplayMode(D_DWORD); break;
+ case D_DWORD: heSetDisplayMode(D_BYTE); break;
+ }
+ heSetDisp ();
+ heSetUpdate (U_SCREEN);
+ continue;
+
+ case 0x71: /* F2 */
+ heGotoPosition ();
+ continue;
+
+ case 0x72: /* F3 */
+ heSearch ();
+ break; // BUGBUG: not done
+
+ case 0x73: /* F4 */
+ heCopyOut ();
+ heSetDisp ();
+ heSetUpdate (U_SCREEN);
+ continue;
+
+ case 0x74: /* F5 */
+ heCopyIn ();
+ heSetDisp ();
+ heSetUpdate (U_SCREEN);
+ continue;
+
+ case 0x75: /* F6 */
+ heJumpToLink ();
+ break;
+
+ case 0x79: /* F10 */
+ heUndo ();
+ continue;
+
+ case 0x0d:
+ if (HeGbl.Flag & FHE_ENTER) {
+ HeGbl.Parm->flag |= FHE_ENTER;
+ Kd.Event.KeyEvent.uChar.AsciiChar = 27; // fake an exit
+ }
+ break;
+
+ //case 0x75: /* F6 */
+ // if (HeGbl.Flag & FHE_F6) {
+ // HeGbl.Parm->flag |= FHE_F6;
+ // Kd.Event.KeyEvent.uChar.AsciiChar = 27; // fake an exit
+ // }
+ // break;
+
+ }
+
+ // Now check for a known char code...
+
+ if (Kd.Event.KeyEvent.uChar.AsciiChar == 27)
+ break;
+
+ if (Kd.Event.KeyEvent.uChar.AsciiChar == 9) {
+ HeGbl.CurFlag ^= FC_TEXT;
+ HeGbl.CurFlag |= FC_NIBBLE;
+ heSetUpdate (U_NEWPOS);
+ continue;
+ }
+
+ if (HeGbl.CurFlag & FC_TEXT) {
+ if (Kd.Event.KeyEvent.uChar.AsciiChar == 0)
+ continue;
+
+ heSetCursorBuf ();
+
+ *HeGbl.CurPT = Kd.Event.KeyEvent.uChar.AsciiChar;
+ heUpdateCurLine ();
+
+ if (HeGbl.CurEditLoc < HeGbl.TotLen1)
+ HeGbl.CurEditLoc++;
+ } else {
+ if (Kd.Event.KeyEvent.uChar.AsciiChar >= 'a' &&
+ Kd.Event.KeyEvent.uChar.AsciiChar <= 'z')
+ Kd.Event.KeyEvent.uChar.AsciiChar -= ('a' - 'A');
+
+ if (!((Kd.Event.KeyEvent.uChar.AsciiChar >= '0' &&
+ Kd.Event.KeyEvent.uChar.AsciiChar <= '9') ||
+ (Kd.Event.KeyEvent.uChar.AsciiChar >= 'A' &&
+ Kd.Event.KeyEvent.uChar.AsciiChar <= 'F')))
+ continue;
+
+ heSetCursorBuf ();
+
+ if (Kd.Event.KeyEvent.uChar.AsciiChar >= 'A')
+ Kd.Event.KeyEvent.uChar.AsciiChar -= 'A' - 10;
+ else Kd.Event.KeyEvent.uChar.AsciiChar -= '0';
+
+
+ if (HeGbl.CurFlag & FC_NIBBLE) {
+ *HeGbl.CurPT = (*HeGbl.CurPT & 0x0F) |
+ (Kd.Event.KeyEvent.uChar.AsciiChar << 4);
+ heUpdateCurLine ();
+ } else {
+ *HeGbl.CurPT = (*HeGbl.CurPT & 0xF0) |
+ Kd.Event.KeyEvent.uChar.AsciiChar;
+ heUpdateCurLine ();
+ heRightOne ();
+ }
+
+ HeGbl.CurFlag ^= FC_NIBBLE;
+ }
+ }
+
+ /*
+ * Free buffer memory
+ */
+
+ for (; ;) {
+ rc = 0;
+ while (HeGbl.Buf) {
+ rc |= heFlushBuf (HeGbl.Buf);
+
+ HeGbl.CurBuf = HeGbl.Buf->next;
+ GlobalFree (HeGbl.Buf);
+ HeGbl.Buf = HeGbl.CurBuf;
+ }
+
+ if (!rc) // If something was flushed,
+ break; // then update the screen
+
+ heSetUpdate (U_SCREEN);
+ heSetUpdate (U_NONE);
+ } // and loop to free buffers (again)
+
+ vRecurseLevel--;
+ GlobalFree (HeGbl.SearchPattern);
+ heEndConsole ();
+
+ if (vRecurseLevel == 0) {
+ while (vBufFree) {
+ HeGbl.CurBuf = vBufFree->next;
+ GlobalFree (vBufFree);
+ vBufFree = HeGbl.CurBuf;
+ }
+ } else {
+ memcpy ((PUCHAR) &HeGbl, (PUCHAR) PriorGlobal, sizeof (HeGbl));
+ GlobalFree (PriorGlobal);
+ }
+}
+
+VOID heSetDisplayMode (ULONG mode)
+{
+ PUCHAR p;
+ UCHAR d,i,j,h,len;
+
+ HeGbl.DisplayMode = mode;
+ HeGbl.CurAscIndent = (UCHAR)vrgAscIndent[HeGbl.DisplayMode];
+ HeGbl.DWidth = vrgDWidth[HeGbl.DisplayMode];
+ HeGbl.ItemWrap = (HeGbl.DisplayMode << 1) | 1;
+
+ i = HeGbl.DWidth;
+ j = i >> 1;
+ h = HEXINDENT;
+ len = LINESZ;
+
+ p = HeGbl.rgCols;
+ while (len) {
+ for (d=0; d < i; d += 2) {
+ len--;
+ *(p++) = i - (d+2) + h;
+ }
+ h += i + 1;
+ }
+}
+
+VOID heRightOne ()
+{
+ if (HeGbl.CurEditLoc & HeGbl.DisplayMode) {
+ HeGbl.CurEditLoc--;
+ } else {
+ HeGbl.CurEditLoc += HeGbl.ItemWrap;
+ }
+
+ if (HeGbl.CurEditLoc > HeGbl.TotLen1) {
+ HeGbl.CurEditLoc = HeGbl.TotLen1 & ~HeGbl.DisplayMode;
+ }
+}
+
+
+VOID heLeftOne ()
+{
+ if ((HeGbl.CurEditLoc & HeGbl.DisplayMode) != HeGbl.DisplayMode) {
+ if (HeGbl.CurEditLoc < HeGbl.TotLen1) {
+ HeGbl.CurEditLoc++;
+ return ;
+ }
+ if (HeGbl.TotLen1 > HeGbl.DisplayMode) {
+ HeGbl.CurEditLoc |= HeGbl.DisplayMode;
+ }
+ }
+
+ if (HeGbl.CurEditLoc > HeGbl.ItemWrap) {
+ HeGbl.CurEditLoc -= HeGbl.ItemWrap;
+ return ;
+ }
+
+ HeGbl.CurEditLoc =
+ HeGbl.TotLen1 > HeGbl.DisplayMode ? HeGbl.DisplayMode : HeGbl.TotLen1;
+}
+
+
+
+
+VOID heUpdateCurLine ()
+{
+ USHORT line;
+
+
+ for (; ;) {
+ HeGbl.CurBuf->flag |= FB_DIRTY;
+ line = (USHORT) ((HeGbl.CurEditLoc - HeGbl.CurOffset) >> LINESHIFT);
+ if (line+TOPLINE < HeGbl.LineTot - 1)
+ break;
+
+ heSetUpdate (U_NEWPOS);
+ heSetUpdate (U_NONE);
+ HeGbl.CurBuf = heGetBuf (HeGbl.CurEditLoc);
+ }
+
+ heHexLine (HeGbl.CurBuf, (USHORT)((HeGbl.CurEditLoc & LINEMASK) - HeGbl.CurBuf->offset), line);
+ heShowBuf (line+TOPLINE, 1);
+ heSetUpdate (U_NEWPOS);
+ if (HeGbl.Flag & FHE_KICKDIRTY) {
+ HeGbl.Parm->flag |= FHE_DIRTY;
+ SetEvent (HeGbl.Parm->Kick);
+ }
+}
+
+
+void heFindMousePos (Pos)
+COORD Pos;
+{
+ ULONG HoldLocation;
+ USHORT HoldFlag;
+ USHORT i;
+
+ if (Pos.Y < TOPLINE || Pos.Y >= TOPLINE+HeGbl.Lines)
+ return ;
+
+
+ heSetUpdate (U_NONE);
+ HoldLocation = HeGbl.CurEditLoc;
+ HoldFlag = (USHORT)HeGbl.CurFlag;
+
+ //
+ // Take the cheap way out - simply run all the possibilities for the
+ // target line looking for a match
+ //
+
+ HeGbl.CurEditLoc = HeGbl.CurOffset + ((Pos.Y-TOPLINE) << LINESHIFT);
+ for (i=0; i < LINESZ; i++, HeGbl.CurEditLoc++) {
+ HeGbl.CurFlag &= ~(FC_NIBBLE | FC_TEXT);
+ heCalcCursorPosition ();
+ if (Pos.X == HeGbl.CursorPos.X)
+ break;
+
+ HeGbl.CurFlag |= FC_NIBBLE;
+ heCalcCursorPosition ();
+ if (Pos.X == HeGbl.CursorPos.X)
+ break;
+
+ HeGbl.CurFlag |= FC_TEXT;
+ heCalcCursorPosition ();
+ if (Pos.X == HeGbl.CursorPos.X)
+ break;
+ }
+
+ if (Pos.X == HeGbl.CursorPos.X) {
+ heSetUpdate (U_NEWPOS);
+ } else {
+ HeGbl.CurEditLoc = HoldLocation;
+ HeGbl.CurFlag = HoldFlag;
+ heCalcCursorPosition ();
+ }
+}
+
+
+
+VOID heSetUpdate (USHORT i)
+{
+ USHORT u;
+
+ if (vUpdate) {
+ /*
+ * There's already some outstanding update going on
+ * Get updat level down to current one.
+ */
+
+ while (vUpdate > i) {
+ vrgUpdateFnc [u=vUpdate] ();
+ if (u == vUpdate) // If vUpdate changed, then
+ vUpdate--; // we might have recursed
+ }
+ }
+
+ vUpdate = i;
+}
+
+int heSetCursorBuf ()
+{
+ // Calc HeGbl.CurBuf, HeGbl.CurPT
+
+ if (HeGbl.CurBuf) {
+ if (HeGbl.CurEditLoc >= HeGbl.CurBuf->offset &&
+ HeGbl.CurEditLoc < HeGbl.CurBuf->offset+BUFSZ ) {
+ HeGbl.CurPT = HeGbl.CurBuf->data + (HeGbl.CurEditLoc - HeGbl.CurBuf->offset);
+ return 0;
+ }
+ }
+
+ HeGbl.CurBuf = heGetBuf (HeGbl.CurEditLoc);
+ HeGbl.CurPT = HeGbl.CurBuf->data + (HeGbl.CurEditLoc - HeGbl.CurBuf->offset);
+ return 0;
+}
+
+
+int hePositionCursor ()
+{
+ heCalcCursorPosition ();
+ SetConsoleCursorPosition (HeGbl.Console, HeGbl.CursorPos);
+
+ if ((HeGbl.Flag & FHE_KICKMOVE) && (HeGbl.CurEditLoc != HeGbl.Parm->editloc)) {
+ HeGbl.Parm->editloc = HeGbl.CurEditLoc;
+ SetEvent (HeGbl.Parm->Kick);
+ }
+
+ return 0;
+}
+
+
+VOID heCalcCursorPosition ()
+{
+ USHORT lin, col;
+
+
+ // Verify HeGbl.CurOffset
+ if (HeGbl.CurEditLoc < HeGbl.CurOffset) {
+ HeGbl.CurOffset = HeGbl.CurEditLoc & LINEMASK;
+ if (HeGbl.CurFlag & FC_CURCENTER) {
+ if (HeGbl.CurOffset > (ULONG) HeGbl.PageSz / 2) {
+ HeGbl.CurOffset -= (HeGbl.PageSz / 2) & LINEMASK;
+ } else {
+ HeGbl.CurOffset = 0;
+ }
+ }
+ heSetUpdate (U_SCREEN);
+ }
+
+ if (HeGbl.CurEditLoc >= HeGbl.CurOffset+HeGbl.PageSz) {
+ HeGbl.CurOffset = ((HeGbl.CurEditLoc - HeGbl.PageSz) & LINEMASK) + LINESZ;
+ if (HeGbl.CurFlag & FC_CURCENTER) {
+ if (HeGbl.CurOffset+HeGbl.PageSz < HeGbl.TotLen) {
+ HeGbl.CurOffset += (HeGbl.PageSz / 2) & LINEMASK;
+ } else {
+ if (HeGbl.TotLen > HeGbl.PageSz) {
+ HeGbl.CurOffset = ((HeGbl.TotLen - HeGbl.PageSz) & LINEMASK) + LINESZ;
+ }
+ }
+ }
+ heSetUpdate (U_SCREEN);
+ }
+
+ lin = (USHORT) ((ULONG) HeGbl.CurEditLoc - HeGbl.CurOffset) >> LINESHIFT;
+
+ if (HeGbl.CurFlag & FC_TEXT) {
+ col = (USHORT) (HeGbl.CurEditLoc & ~LINEMASK) + HeGbl.CurAscIndent+1;
+ } else {
+ col = HeGbl.rgCols [HeGbl.CurEditLoc & ~LINEMASK] +
+ (HeGbl.CurFlag & FC_NIBBLE ? 0 : 1);
+ }
+
+ HeGbl.CursorPos.Y = lin + TOPLINE + HeGbl.TopLine;
+ HeGbl.CursorPos.X = col;
+}
+
+
+
+heUpdateAllLines ()
+{
+ struct Buffer *next, *pBuf;
+ USHORT line, u;
+ ULONG loc;
+
+
+ HeGbl.CurBuf = pBuf = NULL;
+
+ /*
+ * Free up any buffers which are before the HeGbl.CurOffset
+ */
+
+ if (!(HeGbl.CurFlag & FC_INFLUSHBUF)) {
+ while (HeGbl.Buf) {
+ if (HeGbl.Buf->offset+BUFSZ >= HeGbl.CurOffset)
+ break;
+
+ heFlushBuf (HeGbl.Buf);
+
+ /*
+ * Unlink buffer & put it on the free list
+ */
+ next = HeGbl.Buf->next;
+
+ HeGbl.Buf->next = vBufFree;
+ vBufFree = HeGbl.Buf;
+
+ HeGbl.Buf = next;
+ }
+ }
+
+ /*
+ * Display each hex line now
+ */
+
+ loc = HeGbl.CurOffset; // starting offset
+ for (line=0; line<HeGbl.Lines; line++) { // for each line
+
+ if (pBuf == NULL) { // do we have the buffer?
+ pBuf = heGetBuf (loc); // no, go get it
+ u = (USHORT) (loc - pBuf->offset); // calc offset into this buffer
+ }
+
+ heHexLine (pBuf, u, line); // dump this line
+
+ loc += LINESZ; // move offsets foreward one line
+ u += LINESZ;
+
+ if (u >= BUFSZ) { // did we exceed the current buf?
+ pBuf = pBuf->next; // yes, move to next one
+ u = 0;
+
+ if (pBuf && loc < pBuf->offset) // verify buffer is right offs
+ pBuf = NULL; // no, let heGetBuf find it
+ }
+ }
+
+ // Cause screen to be refreshed
+ heShowBuf (TOPLINE, HeGbl.Lines);
+
+ /*
+ * All lines have been displayed, free up any extra buffers
+ * at the end of the chain
+ */
+
+ if (pBuf && !(HeGbl.CurFlag & FC_INFLUSHBUF)) {
+ next = pBuf->next; // get extra buffers
+ pBuf->next = NULL; // terminate active list
+
+ pBuf = next;
+ while (pBuf) {
+ heFlushBuf (pBuf); // flush this buffer
+
+ next = pBuf->next; // move it to the free list
+ // and get next buffer to flush
+ pBuf->next = vBufFree;
+ vBufFree = pBuf;
+
+ pBuf = next;
+ }
+
+ }
+
+ HeGbl.CurFlag &= ~FC_CURCENTER;
+ return 0;
+}
+
+
+
+
+int heFlushBuf (pBuf)
+struct Buffer *pBuf;
+{
+ ULONG loc, ploc;
+ USHORT c;
+ NTSTATUS status;
+
+ if ((pBuf->flag & FB_DIRTY) == 0 ||
+ memcmp (pBuf->data, pBuf->orig, pBuf->len) == 0)
+ return (0); // buffer isn't dirty, return
+
+ // We may need to call heSetUpdate - setting this bit will
+ // stop FlushBuf from being recursed.
+
+ HeGbl.CurFlag |= FC_INFLUSHBUF;
+
+ loc = pBuf->offset;
+ ploc = pBuf->physloc;
+ if (HeGbl.Flag & (FHE_VERIFYONCE | FHE_VERIFYALL)) {
+ heSetUpdate (U_NONE); // make sure screen current
+
+ heBox (12, TOPLINE+1, 55, 8);
+ heDisp (TOPLINE+3, 14, "%HWrite changes to %S?", HeGbl.Parm->ename);
+ heDisp (TOPLINE+7, 14, "Press '%HY%N'es or '%HN%N'o");
+
+ if (HeGbl.Flag & FHE_VERIFYALL) {
+ if (HeGbl.Flag & FHE_PROMPTSEC) {
+ heDisp (TOPLINE+4, 14, "Sector %H%D%N has been modifed",ploc/BUFSZ);
+ } else {
+ heDisp (TOPLINE+4, 14, "Location %H%X%N-%H%X%N has been modifed",ploc,ploc+BUFSZ);
+ }
+ heDisp (TOPLINE+8, 14, "Press '%HA%N' to save all updates");
+ }
+ RefreshDisp ();
+
+ c = heGetChar ("YNA"); // wait for key stroke
+ heSetDisp (); // Get heBox off of screen
+ heSetUpdate (U_SCREEN); // we will need to update display
+
+ if (c == 'N') {
+ memcpy (pBuf->data, pBuf->orig, pBuf->len);
+ HeGbl.CurFlag &= ~FC_INFLUSHBUF;
+
+ if (HeGbl.Flag & FHE_KICKDIRTY) {
+ HeGbl.Parm->flag |= FHE_DIRTY;
+ SetEvent (HeGbl.Parm->Kick);
+ }
+ return (0);
+ }
+
+ if (c == 'A')
+ HeGbl.Flag &= ~FHE_VERIFYALL;
+ }
+
+
+ if (HeGbl.Parm->write) {
+ /*
+ * Write new buffer.
+ */
+ do {
+ status = HeGbl.Parm->write(HeGbl.Parm->handle, loc, pBuf->data,pBuf->len,ploc);
+ if (!status) {
+ pBuf->flag &= ~FB_DIRTY;
+ break;
+ }
+ } while (heIOErr ("WRITE ERROR!", loc, ploc, status) == 'R');
+ }
+
+ HeGbl.Flag &= ~FHE_VERIFYONCE;
+ HeGbl.CurFlag &= ~FC_INFLUSHBUF;
+ return (1);
+}
+
+
+VOID heJumpToLink ()
+{
+ PULONG p;
+ ULONG l;
+
+ if (HeGbl.DisplayMode != D_DWORD || (HeGbl.Flag & FHE_JUMP) == 0)
+ return;
+
+ if (((HeGbl.CurEditLoc & ~3) + 3) > HeGbl.TotLen1)
+ return;
+
+ heSetCursorBuf ();
+ p = (PULONG) (((ULONG) HeGbl.CurPT) & ~3); // Round to dword location
+
+ l = *p;
+ if ((l & 3) == 0)
+ l += 3;
+
+ if (l > HeGbl.TotLen1) {
+ Beep (500, 100);
+ return;
+ }
+
+ HeGbl.CurFlag |= FC_NIBBLE | FC_CURCENTER;
+ HeGbl.CurEditLoc = l;
+
+ heSetDisp (); // clear & restore orig screen (does not draw)
+ heSetUpdate (U_SCREEN); // redraw hex area
+}
+
+VOID heSearch ()
+{
+ ULONG i, j, sec, off, slen, len, upd;
+ struct HexEditParm ei;
+ PUCHAR data, data2;
+
+ if (vInSearch || HeGbl.Lines < 25) {
+ return ;
+ }
+
+ vInSearch = TRUE;
+
+ heFlushAllBufs (1); // Before we start flush & free all buffers
+ heSetUpdate (U_NONE);
+
+ memset ((PUCHAR) &ei, 0, sizeof (ei));
+ ei.ename = "Entering Search";
+ ei.flag = FHE_EDITMEM | FHE_ENTER;
+ ei.mem = HeGbl.SearchPattern;
+ ei.totlen = 512;
+ ei.ioalign = 1;
+ ei.Console = HeGbl.Console;
+ ei.AttrNorm = HeGbl.AttrNorm;
+ ei.AttrHigh = HeGbl.AttrHigh;
+ ei.AttrReverse = HeGbl.AttrReverse;
+ ei.CursorSize = HeGbl.Parm->CursorSize;
+
+ i = 24;
+ if (HeGbl.Lines < i) {
+ if (HeGbl.Lines < 12) {
+ goto abort;
+ }
+ i = HeGbl.Lines - 8;
+ }
+
+ ei.TopLine = HeGbl.Lines + TOPLINE - i;
+ ei.MaxLine = i + 1;
+ if (HeGbl.DisplayMode == D_DWORD) {
+ ei.flag |= FHE_DWORD;
+ }
+
+ HexEdit (&ei); // Get search parameters
+ vInSearch = FALSE;
+
+ if (!(ei.flag & FHE_ENTER))
+ goto abort;
+
+ for (i=0, slen=0; i < 512; i++) { // find last non-zero byte
+ if (HeGbl.SearchPattern[i]) { // in search patter
+ slen = i+1;
+ }
+ }
+
+ if (slen == 0) {
+ goto abort;
+ }
+
+ heBox (12, TOPLINE+1, 48, 6);
+ heDisp (TOPLINE+3, 14, "Searching for pattern");
+ SetCurPos (TOPLINE+5, 24);
+ RefreshDisp ();
+
+ i = HeGbl.CurEditLoc + 1;
+ sec = i & SECTORMASK; // current sector
+ off = i - sec; // offset within sector checking
+ upd = 0;
+
+ while (sec < HeGbl.TotLen) {
+ if (++upd >= 50) {
+ upd = 0;
+ heFlushAllBufs (0); // free memory
+ heDisp (TOPLINE+6, 14, "Searching offset %H%D ", sec);
+ heShowBuf (TOPLINE+6, 1);
+ }
+
+ data = heGetBuf(sec)->data;
+
+nextoff:
+ while (off < BUFSZ && data[off] != HeGbl.SearchPattern[0]) {
+ off++;
+ }
+
+ if (off >= BUFSZ) {
+ // next sector...
+ sec += BUFSZ;
+ off = 0;
+ continue;
+ }
+
+ len = (off + slen) > BUFSZ ? BUFSZ - off : slen;
+ for (i=0; i < len; i++) {
+ if (data[off+i] != HeGbl.SearchPattern[i]) {
+ off += 1;
+ goto nextoff;
+ }
+ }
+
+ if (i < slen) {
+ // data is continued in next buffer..
+ if (sec+BUFSZ >= HeGbl.TotLen) {
+ off += 1;
+ goto nextoff;
+ }
+
+ data2 = heGetBuf (sec+BUFSZ)->data;
+ j = (BUFSZ-off);
+ len = slen - j;
+ for (i=0; i < len; i++) {
+ if (data2[i] != HeGbl.SearchPattern[j+i]) {
+ off += 1;
+ goto nextoff;
+ }
+ }
+ }
+
+ // found match
+ if (sec + off + slen > HeGbl.TotLen1) {
+ break;
+ }
+
+ HeGbl.CurEditLoc = sec + off;
+ heSetDisp (); // clear & restore orig screen (does not draw)
+ heSetUpdate (U_SCREEN); // redraw hex area
+ return ;
+ }
+
+
+ heBox (12, TOPLINE+1, 48, 6);
+ heDisp (TOPLINE+3, 14, "Data was not found");
+ heDisp (TOPLINE+5, 17, "Press %HEnter%N to continue");
+ SetCurPos (TOPLINE+6, 17);
+ RefreshDisp ();
+ heGetChar ("\r");
+
+abort:
+ heSetDisp (); // clear & restore orig screen (does not draw)
+ heSetUpdate (U_SCREEN); // redraw hex area
+ return ;
+}
+
+
+VOID heGotoPosition ()
+{
+ UCHAR s[16];
+ ULONG l;
+
+ heSetUpdate (U_NONE);
+ heBox (12, TOPLINE+1, 41, 6);
+
+ heDisp (TOPLINE+3, 14, "Enter offset from %H%X%N - %H%X", 0L, HeGbl.TotLen1);
+ heDisp (TOPLINE+5, 14, "Offset: ");
+ SetCurPos (TOPLINE+5, 22);
+ RefreshDisp ();
+
+ heGetString (s, 10);
+
+ if (s[0]) {
+ l = heHtou (s);
+ if (l <= HeGbl.TotLen1) {
+ HeGbl.CurFlag |= FC_NIBBLE;
+ HeGbl.CurEditLoc = l;
+ }
+ }
+
+ if (!(HeGbl.CurFlag & FC_TEXT) && !(HeGbl.CurEditLoc & HeGbl.DisplayMode)) {
+ // On xword boundry and not in text mode, adjust so cursor
+ // is on the first byte which is being displayed of this
+ // xword
+
+ HeGbl.CurEditLoc += HeGbl.DisplayMode;
+ if (HeGbl.CurEditLoc > HeGbl.TotLen1)
+ HeGbl.CurEditLoc = HeGbl.TotLen1;
+ }
+
+
+
+ HeGbl.CurFlag |= FC_CURCENTER; // set cursor to center in window moves
+ heSetDisp (); // clear & restore orig screen (does not draw)
+ heSetUpdate (U_SCREEN); // redraw hex area
+}
+
+
+VOID heGetString (PUCHAR s, USHORT len)
+{
+ UCHAR i[50];
+ DWORD cb;
+
+ ReadFile( HeGbl.StdIn, i, 50, &cb, NULL );
+
+ if(cb >= 2 && (i[cb - 2] == 0x0d || i[cb - 2] == 0x0a) ) {
+ i[cb - 2] = 0; // Get rid of CR LF
+ }
+ i[ cb - 1] = 0;
+
+ memcpy (s, i, len);
+ s[len] = 0;
+}
+
+
+
+/***
+ * heCopyOut - Copies data to output filename
+ */
+VOID heCopyOut ()
+{
+ UCHAR s[24];
+ ULONG len, rem, upd, u;
+ HANDLE h;
+ NTSTATUS status;
+ struct Buffer *pB;
+
+ heFlushAllBufs (1); // Before we start flush & free all buffers
+ heSetUpdate (U_NONE);
+ heBox (12, TOPLINE+1, 48, 6);
+
+ heDisp (TOPLINE+3, 14, "Copy stream to filename (%H%D%N Bytes)", HeGbl.TotLen);
+ heDisp (TOPLINE+5, 14, "Filename: ");
+ SetCurPos (TOPLINE+5, 24);
+ RefreshDisp ();
+
+ heGetString (s, 19);
+ if (s[0] == 0)
+ return;
+
+ status = heOpenFile (s, &h, GENERIC_WRITE);
+ if (NT_SUCCESS(status)) {
+ len = upd = 0;
+ rem = HeGbl.TotLen;
+ while (NT_SUCCESS(status) && rem){
+ if (upd++ > 50) {
+ upd = 0;
+ heFlushAllBufs (0); // free memory
+ heDisp (TOPLINE+6, 14, "Bytes written %H%D ", len);
+ heShowBuf (TOPLINE+6, 1);
+ RefreshDisp ();
+ }
+
+ u = rem > BUFSZ ? BUFSZ : rem;
+ pB = heGetBuf (len);
+ status = heWriteFile (h, pB->data, u);
+ rem -= u;
+ len += BUFSZ;
+ }
+ CloseHandle(h);
+ }
+
+ if (!NT_SUCCESS(status)) {
+ heBox (15, TOPLINE+1, 33, 6);
+ heDisp (TOPLINE+3, 17, "%HCopy failed");
+ heDisp (TOPLINE+4, 17, "Error code %X", status);
+ heDisp (TOPLINE+5, 17, "Press %HA%N to abort");
+ RefreshDisp ();
+ heGetChar ("A");
+ }
+}
+
+
+
+/***
+ * heCopyIn - Copies data to output filename
+ */
+
+VOID
+heCopyIn ()
+{
+ UCHAR s[24];
+ ULONG holdEditLoc, rem, u, br;
+ struct Buffer *pB;
+ char *pErr;
+ HANDLE h;
+ NTSTATUS status;
+
+ heSetUpdate (U_NONE);
+ heBox (12, TOPLINE+1, 48, 6);
+
+ heDisp (TOPLINE+3, 14, "Input from filename (%H%D%N Bytes)", HeGbl.TotLen);
+ heDisp (TOPLINE+5, 14, "Filename: ");
+ SetCurPos (TOPLINE+5, 24);
+ RefreshDisp ();
+
+ heGetString (s, 19);
+ heSetDisp (); // Get heBox off of screen
+ if (s[0] == 0) {
+ return;
+ }
+
+ status = heOpenFile (s, &h, GENERIC_READ);
+ if (NT_SUCCESS(status)) {
+ rem = HeGbl.TotLen;
+ holdEditLoc = HeGbl.CurEditLoc;
+ HeGbl.CurEditLoc = 0;
+ while (NT_SUCCESS(status) && rem) {
+ pB = heGetBuf (HeGbl.CurEditLoc);
+ u = rem > BUFSZ ? BUFSZ : rem;
+ status = heReadFile (h, pB->data, u, &br);
+
+ if (memcmp (pB->data, pB->orig, pB->len)) {
+ pB->flag |= FB_DIRTY; // it's changed
+ HeGbl.CurFlag |= FC_CURCENTER;
+ heSetUpdate (U_SCREEN);
+ heSetUpdate (U_NONE); // Update screen
+ if (HeGbl.Flag & FHE_KICKDIRTY) {
+ HeGbl.Parm->flag |= FHE_DIRTY;
+ // DosSemClear (HeGbl.Parm->sem); BUGBUG
+ }
+ }
+ heFlushAllBufs (1);
+ if (NT_SUCCESS(status) && br != u) {
+ pErr = "Smaller then data";
+ }
+
+ rem -= u;
+ HeGbl.CurEditLoc += BUFSZ;
+ }
+
+ if (NT_SUCCESS(status)) {
+ heReadFile (h, s, 1, &br);
+ if (br) // then what we are editting
+ pErr = "Larger then data";
+ }
+
+ CloseHandle(h);
+ }
+
+ if (!NT_SUCCESS(status) || pErr) {
+ heBox (15, TOPLINE+1, 33, 6);
+ if (pErr) {
+ heDisp (TOPLINE+3, 17, "Import file is:");
+ heDisp (TOPLINE+4, 17, pErr);
+ heDisp (TOPLINE+5, 17, "Press %HC%N to continue");
+ } else {
+ heDisp (TOPLINE+3, 17, "%HImport failed");
+ heDisp (TOPLINE+4, 17, "Error code %X", status);
+ heDisp (TOPLINE+5, 17, "Press %HA%N to abort");
+ }
+ RefreshDisp ();
+ heGetChar ("CA");
+ }
+
+ HeGbl.CurEditLoc = holdEditLoc;
+}
+
+
+VOID
+heFlushAllBufs (USHORT update)
+{
+ struct Buffer *next;
+ USHORT rc;
+
+ for (; ;) {
+ rc = 0;
+ while (HeGbl.Buf) {
+ rc |= heFlushBuf (HeGbl.Buf);
+
+ next = HeGbl.Buf->next;
+ HeGbl.Buf->next = vBufFree;
+ vBufFree = HeGbl.Buf;
+ HeGbl.Buf = next;
+ }
+
+ if (!rc) // If something was flushed,
+ break; // then update the screen
+
+ if (update) {
+ heSetUpdate (U_SCREEN);
+ heSetUpdate (U_NONE);
+ }
+ } // and loop to free buffers (again)
+}
+
+
+
+
+VOID heBox (x, y, len_x, len_y)
+USHORT x, y, len_x, len_y;
+{
+ CHAR_INFO blank[CELLPERLINE];
+ PCHAR_INFO pt, pt1;
+ USHORT c, lc;
+
+ pt = blank;
+ for (c=len_x; c; c--) { /* Construct blank line */
+ PUTCHAR (pt, ' ', HeGbl.AttrNorm); /* with background color*/
+
+ }
+ blank[0].Char.AsciiChar = blank[lc=len_x-1].Char.AsciiChar = 'º';
+
+ for (c=0; c <= len_y; c++) /* blank each line */
+ memcpy (POS(c+y,x), blank, (pt - blank) * sizeof (CHAR_INFO));
+
+ pt = POS(y,x);
+ pt1 = POS(y+len_y, x);
+ for (c=0; c < len_x; c++) /* Draw horz lines */
+ pt[c].Char.AsciiChar = pt1[c].Char.AsciiChar = 'Í';
+
+ pt [ 0].Char.AsciiChar = 'É'; /* Put corners on */
+ pt [lc].Char.AsciiChar = '»';
+ pt1 [ 0].Char.AsciiChar = 'È';
+ pt1 [lc].Char.AsciiChar = '¼';
+}
+
+
+
+VOID heUndo ()
+{
+ struct Buffer *pBuf;
+ USHORT flag;
+
+ flag = 0;
+ for (pBuf=HeGbl.Buf; pBuf; pBuf = pBuf->next)
+ if (pBuf->flag & FB_DIRTY) {
+ flag = 1;
+ pBuf->flag &= ~FB_DIRTY;
+ memcpy (pBuf->data, pBuf->orig, pBuf->len);
+ }
+
+ if (flag) {
+ heSetUpdate (U_SCREEN);
+ if (HeGbl.Flag & FHE_KICKDIRTY) {
+ HeGbl.Parm->flag |= FHE_DIRTY;
+ SetEvent (HeGbl.Parm->Kick);
+ }
+ }
+}
+
+
+
+void heHexLine (pBuf, u, line)
+struct Buffer *pBuf;
+USHORT u, line;
+{
+ PCHAR_INFO pt, hex, asc;
+ UCHAR *data, *orig;
+ UCHAR len, mlen, c, d, i, j;
+ WORD a;
+ ULONG l;
+ WORD AttrNorm = HeGbl.AttrNorm;
+
+ data = pBuf->data + u;
+ orig = pBuf->orig + u;
+
+ pt = HeGbl.pVioBuf + (line+TOPLINE) * CELLPERLINE;
+ hex = pt + HEXINDENT;
+ asc = pt + HeGbl.CurAscIndent;
+
+ l = pBuf->offset + u;
+ if (l & ((ULONG) BUFSZ-1)) {
+ heHexDWord (pt+LINEINDENT, pBuf->physloc + u,
+ AttrNorm);
+ } else {
+ heHexDWord (pt+LINEINDENT, pBuf->physloc + u,
+ HeGbl.AttrHigh);
+ }
+
+ if (pBuf->flag & FB_BAD) { // If read error on
+ pt[LINEINDENT+8].Char.AsciiChar = 'E'; // this sector, then
+ pt[LINEINDENT+8].Attributes = HeGbl.AttrHigh; // flag it
+ } else
+ pt[LINEINDENT+8].Char.AsciiChar = ' ';
+
+ if (l + LINESZ > HeGbl.TotLen) { // if EOF
+ if (l >= HeGbl.TotLen) { // Totally blankline?
+ PUTCHAR (asc, ' ', AttrNorm);
+ PUTCHAR (asc, ' ', AttrNorm);
+ mlen = 0;
+
+ for (len=0; len < 9; len++)
+ pt[len].Char.AsciiChar = ' ';
+
+ goto blankline;
+ }
+ len = mlen = (UCHAR) (HeGbl.TotLen - l); // Clip line
+ } else
+ len = mlen = (UCHAR) LINESZ; // Full line
+
+
+ PUTCHAR (asc, '*', AttrNorm);
+
+ switch (HeGbl.DisplayMode) {
+ case D_BYTE:
+ while (len--) {
+ c = *(data++);
+ a = c == *(orig++) ? AttrNorm : HeGbl.AttrReverse;
+ PUTCHAR (hex, rghexc [c >> 4], a);
+ PUTCHAR (hex, rghexc [c & 0x0F], a);
+ hex++;
+
+ PUTCHAR (asc, (c < ' ' || c > '~') ? '.' : c, a);
+ }
+ pt[((LINESZ/2)*3+HEXINDENT)-1].Char.AsciiChar = '-';
+ break;
+
+ default:
+ hex--;
+ i = HeGbl.DWidth;
+ j = i >> 1;
+ while (len) {
+ hex += i;
+ for (d=0; d<j; d++) {
+ if (len) {
+ len--;
+ c = *(data++);
+ a = c == *(orig++) ? AttrNorm : HeGbl.AttrReverse;
+
+ hex->Attributes = a;
+ hex->Char.AsciiChar = rghexc[c & 0x0F];
+ hex--;
+ hex->Attributes = a;
+ hex->Char.AsciiChar = rghexc[c >> 4];
+ hex--;
+
+ PUTCHAR (asc, (c < ' ' || c > '~') ? '.' : c, a);
+ } else {
+ hex->Attributes = AttrNorm;
+ hex->Char.AsciiChar = '?';
+ hex--;
+ hex->Attributes = AttrNorm;
+ hex->Char.AsciiChar = '?';
+ hex--;
+ }
+ }
+ hex += i + 1;
+ }
+ break;
+ }
+
+ PUTCHAR (asc, '*', AttrNorm);
+
+blankline:
+ while (mlen++ < LINESZ)
+ PUTCHAR (asc, ' ', AttrNorm);
+
+ asc = pt + HeGbl.CurAscIndent;
+ while (hex < asc)
+ PUTCHAR (hex, ' ', AttrNorm);
+}
+
+
+heInitScr ()
+{
+ CONSOLE_SCREEN_BUFFER_INFO Mode;
+ CONSOLE_CURSOR_INFO CursorInfo;
+ USHORT li;
+
+ GetConsoleScreenBufferInfo(HeGbl.Console, &Mode);
+ if (HeGbl.Parm->MaxLine) {
+ HeGbl.TopLine = (USHORT)HeGbl.Parm->TopLine;
+ li = (USHORT)HeGbl.Parm->MaxLine; // +1; adjust for no fnc key line
+ } else {
+ li = Mode.srWindow.Bottom - Mode.srWindow.Top + 1;
+ if (li < 10)
+ li = 10;
+
+ Mode.dwSize.Y = li;
+ }
+
+ if (Mode.dwSize.X < 80)
+ Mode.dwSize.X = 80;
+
+ if (!SetConsoleScreenBufferSize(HeGbl.Console, Mode.dwSize)) {
+
+ Mode.srWindow.Bottom -= Mode.srWindow.Top;
+ Mode.srWindow.Right -= Mode.srWindow.Left;
+ Mode.srWindow.Top = 0;
+ Mode.srWindow.Left = 0;
+
+ SetConsoleWindowInfo(HeGbl.Console, TRUE, &Mode.srWindow);
+ SetConsoleScreenBufferSize(HeGbl.Console, Mode.dwSize);
+ }
+
+ HeGbl.Lines = li - TOPLINE - 1;
+ HeGbl.PageSz = HeGbl.Lines * LINESZ;
+ HeGbl.LineTot = li;
+
+ if (HeGbl.pVioBuf)
+ GlobalFree (HeGbl.pVioBuf);
+
+ HeGbl.pVioBuf = (PCHAR_INFO) GlobalAlloc (0,
+ (HeGbl.LineTot+1)*CELLPERLINE*sizeof(CHAR_INFO));
+
+ HeGbl.dwVioBufSize.X = CELLPERLINE;
+ HeGbl.dwVioBufSize.Y = HeGbl.LineTot +
+ (HeGbl.TopLine*CELLPERLINE*sizeof(CHAR_INFO));
+
+ GetConsoleCursorInfo (HeGbl.Console, &CursorInfo);
+ CursorInfo.bVisible = TRUE;
+ CursorInfo.dwSize = (ULONG) HeGbl.Parm->CursorSize ? HeGbl.Parm->CursorSize : 100;
+ SetConsoleCursorInfo (HeGbl.Console, &CursorInfo);
+
+ return heSetDisp ();
+}
+
+int heInitConsole ()
+{
+ CONSOLE_SCREEN_BUFFER_INFO screenMode;
+ DWORD mode;
+
+ HeGbl.StdIn = GetStdHandle (STD_INPUT_HANDLE);
+ GetConsoleMode (HeGbl.StdIn, &mode);
+ HeGbl.OrigMode = mode;
+ SetConsoleMode (HeGbl.StdIn, mode | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
+ ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT );
+
+
+ if (HeGbl.Flag & FHE_SAVESCRN) {
+ HeGbl.Console = CreateConsoleScreenBuffer(
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_TEXTMODE_BUFFER,
+ NULL );
+
+ SetConsoleActiveScreenBuffer (HeGbl.Console);
+ } else {
+ HeGbl.Console = HeGbl.Parm->Console;
+ if (HeGbl.Console == INVALID_HANDLE_VALUE)
+ HeGbl.Console = GetStdHandle( STD_OUTPUT_HANDLE );
+
+ GetConsoleScreenBufferInfo(HeGbl.Console, &screenMode);
+ HeGbl.dwSize = screenMode.dwSize;
+ }
+
+ GetConsoleCursorInfo(HeGbl.Console, &HeGbl.CursorInfo);
+ return 0;
+}
+
+
+VOID heEndConsole ()
+{
+ CONSOLE_SCREEN_BUFFER_INFO Mode;
+ PCHAR_INFO pt;
+ ULONG u;
+
+ SetConsoleMode (HeGbl.StdIn, HeGbl.OrigMode);
+
+ if (HeGbl.Flag & FHE_SAVESCRN) {
+ CloseHandle (HeGbl.Console);
+
+ if (HeGbl.Parm->Console == INVALID_HANDLE_VALUE)
+ SetConsoleActiveScreenBuffer (GetStdHandle(STD_OUTPUT_HANDLE));
+ else SetConsoleActiveScreenBuffer (HeGbl.Parm->Console);
+
+ } else {
+ if (!SetConsoleScreenBufferSize(HeGbl.Console, HeGbl.dwSize)) {
+
+ GetConsoleScreenBufferInfo(HeGbl.Console, &Mode);
+ Mode.srWindow.Bottom -= Mode.srWindow.Top;
+ Mode.srWindow.Right -= Mode.srWindow.Left;
+ Mode.srWindow.Top = 0;
+ Mode.srWindow.Left = 0;
+ SetConsoleWindowInfo(HeGbl.Console, TRUE, &Mode.srWindow);
+
+ SetConsoleScreenBufferSize(HeGbl.Console, HeGbl.dwSize);
+ }
+
+ if (HeGbl.LineTot <= HeGbl.dwSize.Y) {
+ HeGbl.dwSize.Y--;
+ pt = POS(HeGbl.LineTot - 1,0);
+ for (u=HeGbl.dwSize.X; u; u--) {
+ PUTCHAR (pt, ' ', HeGbl.AttrNorm);
+ }
+
+ heShowBuf (HeGbl.LineTot - 1, 1);
+ }
+
+ HeGbl.dwSize.X = 0;
+ SetConsoleCursorPosition (HeGbl.Console, HeGbl.dwSize);
+ SetConsoleCursorInfo (HeGbl.Console, &HeGbl.CursorInfo);
+ }
+
+ if (HeGbl.pVioBuf) {
+ GlobalFree (HeGbl.pVioBuf);
+ HeGbl.pVioBuf = NULL;
+ }
+}
+
+
+heRefresh ()
+{
+ RefreshDisp ();
+
+ if (HeGbl.Flag & FHE_KICKDIRTY) {
+ HeGbl.Parm->flag |= FHE_DIRTY;
+ SetEvent (HeGbl.Parm->Kick);
+ }
+ return 0;
+}
+
+
+int heSetDisp ()
+{
+ PCHAR_INFO pt, pt1;
+ USHORT u;
+
+ pt = POS(0,0);
+ for (u=HeGbl.LineTot * CELLPERLINE; u; u--) {
+ PUTCHAR (pt, ' ', HeGbl.AttrNorm);
+ }
+
+ heDisp (1, 5, "Edit: %H%S", HeGbl.Parm->ename);
+ heDisp (2, 5, "Size: %X (%D)", HeGbl.TotLen, HeGbl.TotLen);
+
+ heDisp (1, 40, "Position:");
+ for (pt1=POS(1,50), u=0; u<30; u++, pt1++)
+ pt1->Attributes = HeGbl.AttrHigh;
+
+ //if (HeGbl.Parm->MaxLine == 0) {
+ u = HeGbl.LineTot - 1;
+ heDisp (u, 0, "%HF1%N:Toggle");
+ heDisp (u,11, "%HF2%N:Goto");
+
+ if (!vInSearch) {
+ heDisp (u,20, "%HF3%N:Search");
+ }
+
+ heDisp (u,31, "%HF4%N:Export");
+ heDisp (u,42, "%HF5%N:Import");
+
+ if (HeGbl.DisplayMode == D_DWORD && (HeGbl.Flag & FHE_JUMP) != 0)
+ heDisp (u,53, "%HF6%N:Jump");
+ else heDisp (u,53, " ");
+
+ heDisp (u,66, "%HF10%N:Undo");
+
+ //if (HeGbl.Flag & FHE_F6)
+ // heDisp (u,51, "%HF6%N:PSec");
+ //}
+ return 0;
+}
+
+int heUpdateFncs ()
+{
+ heShowBuf (HeGbl.LineTot - 1, 1);
+ return 0;
+}
+
+
+int heUpdateStats ()
+{
+ COORD dwBufferCoord;
+ SMALL_RECT lpWriteRegion;
+
+ heHexDWord (POS(1, 50), HeGbl.CurEditLoc, HeGbl.AttrHigh);
+ heLtoa (POS(1, 60), HeGbl.CurEditLoc);
+
+ dwBufferCoord.X = 50;
+ dwBufferCoord.Y = 1;
+
+ lpWriteRegion.Left = 50;
+ lpWriteRegion.Top = HeGbl.TopLine + 1;
+ lpWriteRegion.Right = 74;
+ lpWriteRegion.Bottom = HeGbl.TopLine + 1;
+
+ WriteConsoleOutputA (
+ HeGbl.Console,
+ HeGbl.pVioBuf,
+ HeGbl.dwVioBufSize, // size of VioBuf
+ dwBufferCoord, // location in VioBuf to write
+ &lpWriteRegion // location to write on display
+ );
+
+ SetConsoleCursorPosition (HeGbl.Console, HeGbl.CursorPos); // redisplay cursor
+ return 0;
+}
+
+VOID heShowBuf (ULONG StartingLine, ULONG NoLines)
+{
+ COORD dwBufferCoord;
+ SMALL_RECT lpWriteRegion;
+
+ dwBufferCoord.X = (SHORT)0;
+ dwBufferCoord.Y = (SHORT)StartingLine;
+
+ StartingLine += HeGbl.TopLine;
+ lpWriteRegion.Left = (SHORT)0;
+ lpWriteRegion.Top = (SHORT)StartingLine;
+ lpWriteRegion.Right = (SHORT)(CELLPERLINE-1);
+ lpWriteRegion.Bottom = (SHORT)(StartingLine+NoLines-1);
+
+ WriteConsoleOutputA (
+ HeGbl.Console,
+ HeGbl.pVioBuf,
+ HeGbl.dwVioBufSize, // size of VioBuf
+ dwBufferCoord, // location in VioBuf to write
+ &lpWriteRegion // location to write on display
+ );
+}
+
+
+struct Buffer *heGetBuf (loc)
+ULONG loc;
+{
+ struct Buffer **ppBuf, *pBuf;
+ ULONG ioalign;
+ USHORT len;
+ NTSTATUS status;
+
+ loc &= SECTORMASK;
+
+ ppBuf = &HeGbl.Buf;
+ while (pBuf = *ppBuf) {
+ if (pBuf->offset >= loc) {
+ if (pBuf->offset == loc) // buffer the correct offset?
+ return pBuf; // yup - all done
+
+ break; // it's not here
+ }
+ ppBuf = &pBuf->next; // try the next one
+ }
+
+
+ /*
+ * buffer was not in list - it should be insterted before ppBuf
+ */
+
+ ioalign = HeGbl.Parm->ioalign;
+ if (vBufFree) {
+ pBuf = vBufFree;
+ vBufFree = vBufFree->next;
+ } else
+ pBuf = (struct Buffer *)
+ GlobalAlloc (0, sizeof(struct Buffer)+BUFSZ+ioalign);
+
+ pBuf->data = (PUCHAR)(((ULONG)pBuf+sizeof(struct Buffer)+ioalign)&~ioalign);
+ pBuf->offset = loc;
+ pBuf->physloc= loc; // Assume physloc is logical offset
+ pBuf->flag = 0;
+
+ // Link this buffer in now! In case we recurse (due to read-error)
+ pBuf->next = *ppBuf; // link in this new buffer
+ *ppBuf = pBuf;
+
+ if (loc + BUFSZ > HeGbl.TotLen) { // are we going to hit the EOF?
+ if (loc >= HeGbl.TotLen) { // is buffer completely passed EOF?
+ pBuf->len = 0;
+ goto nodata; // yes, then no data at all
+ }
+ len = (USHORT) (HeGbl.TotLen - loc); // else, clip to EOF
+ } else len = BUFSZ; // not pass eof, get a full buffer
+
+ pBuf->len = len;
+
+ if (HeGbl.Flag & FHE_EDITMEM) // Direct memory edit?
+ pBuf->data = HeGbl.Parm->mem + loc; // memory location of buffer
+
+ if (HeGbl.Read) {
+ /*
+ * Read buffer from file
+ */
+ status = HeGbl.Read (HeGbl.Parm->handle, loc, pBuf->data, len, &pBuf->physloc);
+ if (status) {
+ // If read error, we will always retry once. Also clear buffer
+ // before retry in case read retreives some info
+ for (; ;) {
+ memset (pBuf->data, 0, len); // Clear read area
+ memset (pBuf->orig,0xff, len); // good effect
+ status = HeGbl.Read (HeGbl.Parm->handle, loc, pBuf->data, len, &pBuf->physloc);
+
+ if (!status)
+ break;
+
+ if (heIOErr ("READ ERROR!", loc, pBuf->physloc, status) == 'I') {
+ pBuf->flag |= FB_BAD;
+ break;
+ }
+ }
+ }
+ }
+
+ memcpy (pBuf->orig, pBuf->data, len); // make a copy of the data
+
+nodata:
+ return pBuf;
+}
+
+
+USHORT heIOErr (UCHAR *str, ULONG loc, ULONG ploc, ULONG errcd)
+{
+ USHORT c;
+
+ if (errcd == 0xFFFFFFFF)
+ return 'I';
+
+ heSetUpdate (U_NONE);
+ heBox (12, TOPLINE+1, 55, 8);
+
+ heDisp (TOPLINE+3, 14, str);
+ heDisp (TOPLINE+4, 14, "Error code %H%D%N, Offset %Xh, Sector %D",
+ errcd, loc, ploc / BUFSZ);
+ heDisp (TOPLINE+7, 14, "Press '%HR%N' to retry IO, or '%HI%N' to ignore");
+ RefreshDisp ();
+
+ c = heGetChar ("RI");
+
+ heSetDisp (); // Get heBox off of screen
+ heSetUpdate (U_SCREEN);
+ return c;
+}
+
+
+UCHAR heGetChar (keys)
+PUCHAR keys;
+{
+ INPUT_RECORD Kd;
+ DWORD cEvents;
+ UCHAR *pt;
+
+ for (; ;) {
+ Beep (500, 100);
+
+ for (; ;) {
+ ReadConsoleInput (HeGbl.StdIn, &Kd, 1, &cEvents);
+
+ if (Kd.EventType != KEY_EVENT)
+ continue; // Not a key
+
+ if (!Kd.Event.KeyEvent.bKeyDown)
+ continue; // Not a down stroke
+
+ if (Kd.Event.KeyEvent.wVirtualKeyCode == 0 || // ALT
+ Kd.Event.KeyEvent.wVirtualKeyCode == 0x10 || // SHIFT
+ Kd.Event.KeyEvent.wVirtualKeyCode == 0x11 || // CONTROL
+ Kd.Event.KeyEvent.wVirtualKeyCode == 0x14) // CAPITAL
+ continue;
+
+ break;
+ }
+
+ if (Kd.Event.KeyEvent.wVirtualKeyCode >= 'a' &&
+ Kd.Event.KeyEvent.wVirtualKeyCode <= 'z')
+ Kd.Event.KeyEvent.wVirtualKeyCode -= ('a' - 'A');
+
+ for (pt=keys; *pt; pt++) // Is this a key we are
+ if (Kd.Event.KeyEvent.wVirtualKeyCode == *pt)
+ return *pt; // looking for?
+ }
+}
+
+
+VOID _CRTAPI1
+heDisp (line, col, pIn, ...)
+USHORT line, col;
+UCHAR *pIn;
+{
+ register char c;
+ PCHAR_INFO pOut;
+ WORD attr;
+ USHORT u;
+ UCHAR *pt;
+ va_list args;
+
+ attr = HeGbl.AttrNorm;
+ pOut = POS(line,col);
+
+ va_start(args,pIn);
+ while (c = *(pIn++)) {
+ if (c != '%') {
+ PUTCHAR (pOut, c, attr);
+ continue;
+ }
+
+ switch (*(pIn++)) {
+ case 'S':
+ pt = va_arg(args, CHAR *);
+ while (*pt) {
+ PUTCHAR (pOut, *(pt++), attr);
+ }
+ break;
+
+ case 'X': /* Long HEX, fixed len */
+ heHexDWord (pOut, va_arg(args, ULONG), attr);
+ pOut += 8;
+ break;
+
+ case 'D': /* Long dec, varible len */
+ u = heLtoa (pOut, va_arg(args, ULONG));
+ while (u--) {
+ pOut->Attributes = attr;
+ pOut++;
+ }
+ break;
+ case 'H':
+ attr = HeGbl.AttrHigh;
+ break;
+ case 'N':
+ attr = HeGbl.AttrNorm;
+ break;
+ }
+ }
+}
+
+
+
+
+void heHexDWord (s, l, attr)
+PCHAR_INFO s;
+ULONG l;
+WORD attr;
+{
+ UCHAR d, c;
+ UCHAR *pt;
+
+ s += 8-1;
+ pt = (UCHAR *) &l;
+
+ for (d=0; d<4; d++) {
+ c = *(pt++);
+ s->Attributes = attr;
+ s->Char.AsciiChar = rghexc[c & 0x0F];
+ s--;
+ s->Attributes = attr;
+ s->Char.AsciiChar = rghexc[c >> 4];
+ s--;
+ }
+}
+
+
+USHORT heLtoa (s, l)
+PCHAR_INFO s;
+ULONG l;
+{
+ static ULONG mask[] = { 0L,
+ 1L,
+ 10L,
+ 100L,
+ 1000L,
+ 10000L,
+ 100000L,
+ 1000000L,
+ 10000000L,
+ 100000000L,
+ 1000000000L,
+ };
+
+ static UCHAR comm[] = "xxxx,xx,xx,xx,xx";
+ PCHAR_INFO os;
+ UCHAR c;
+ USHORT i, j;
+ ULONG m;
+
+ if (l < 1000000000L) {
+ for (i=1; mask[i] <= l; i++) ;
+
+ if (l == 0L) // Make Zeros
+ i++;
+ } else
+ i = 11;
+
+ os = s;
+ j = i;
+ while (m = mask[--i]) {
+ c = (UCHAR) ((ULONG) l / m);
+ l -= m * c;
+ s->Char.AsciiChar = c + '0';
+ if (comm[i] == ',') {
+ s++;
+ s->Char.AsciiChar = ',';
+ }
+ s++;
+ }
+
+ i = (s - os); // remember how long the number was
+
+ while (j++ < 11) { /* Clear off some blank space after */
+ s->Char.AsciiChar = ' '; /* the number. */
+ s++;
+ }
+
+ return i;
+}
+
+
+ULONG heHtou (s)
+UCHAR *s;
+{
+ UCHAR c;
+ ULONG l;
+
+ l = 0;
+ for (; ;) {
+ c = *(s++);
+
+ if (c == 's' || c == 'S') { // Sector multiplier?
+ l = l * 512l;
+ break;
+ }
+
+ if (c >= 'a') c -= 'a' - 10;
+ else if (c >= 'A') c -= 'A' - 10;
+ else c -= '0';
+
+ if (c > 15)
+ break;
+
+ l = (l<<4) + c;
+ }
+ return l;
+}
+
+
+NTSTATUS
+heOpenFile (PUCHAR name, PHANDLE fhan, ULONG access)
+{
+ *fhan = CreateFile (
+ name,
+ access,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+
+ if (*fhan == INVALID_HANDLE_VALUE && (access & GENERIC_WRITE)) {
+ *fhan = CreateFile (
+ name,
+ access,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_NEW,
+ 0,
+ NULL );
+ }
+
+ return *fhan == INVALID_HANDLE_VALUE ? GetLastError() : STATUS_SUCCESS;
+}
+
+NTSTATUS
+heReadFile (HANDLE h, PUCHAR buffer, ULONG len, PULONG br)
+{
+ if (!ReadFile (h, buffer, len, br, NULL))
+ return GetLastError();
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+heWriteFile (HANDLE h, PUCHAR buffer, ULONG len)
+{
+ ULONG bw;
+
+ if (!WriteFile (h, buffer, len, &bw, NULL))
+ return GetLastError();
+ return (bw != len ? ERROR_WRITE_FAULT : STATUS_SUCCESS);
+}
diff --git a/private/sdktools/he/hexedit.h b/private/sdktools/he/hexedit.h
new file mode 100644
index 000000000..96d0bcfa4
--- /dev/null
+++ b/private/sdktools/he/hexedit.h
@@ -0,0 +1,79 @@
+
+/*****************************************************************/
+/** Microsoft LAN Manager **/
+/** Copyright(c) Microsoft Corp., 1988-1990 **/
+/*****************************************************************/
+
+/**** hexedit.h
+ *
+ * Structure and flags def's to call HexEdit
+ *
+ */
+
+
+struct HexEditParm {
+ ULONG flag; // edit flags
+ UCHAR *ename; // edit name (title)
+ ULONG totlen; // totlen (in bytes) being edited
+ ULONG start; // starting address of edit
+ NTSTATUS (*read)(); // (opt) fnc to read data
+ NTSTATUS (*write)(); // (opt) fnc to write changes
+ HANDLE handle; // (opt) passed to read/write functions
+ ULONG ioalign; // (opt) alignment when read/write (~editmem)
+ UCHAR *mem; // (opt) Only if FHE_EDITMEM
+ HANDLE Kick; // (opt) event to kick (editmem only)
+ HANDLE Console; // (opt) callers console handle
+ ULONG MaxLine; // (opt) if non-zero, # of lines HexEdit is to use
+ WORD AttrNorm; // (opt) Default attribute for text
+ WORD AttrHigh; // (opt) Default attribute for highlighted text
+ WORD AttrReverse; // (opt) Default attribute for reversed text
+ WORD CursorSize; // (opt) Default size of cursor
+ ULONG editloc; // Position exited/kicked at
+ ULONG TopLine; // (opt) Relative topline, requires MaxLine
+} ;
+
+
+#define FHE_VERIFYONCE 0x0001 // Prompt before updating (just once)
+#define FHE_VERIFYALL 0x0002 // Prompt before any change is written
+#define FHE_PROMPTSEC 0x0004 // Verify prompt is for sectors
+#define FHE_SAVESCRN 0x0008 // Save & Restore orig screen
+
+#define FHE_EDITMEM 0x0010 // Direct mem edit
+#define FHE_KICKDIRTY 0x0020 // Kick event if memory gets editted
+#define FHE_KICKMOVE 0x0040 // Kick event every time cursor is moved
+#define FHE_DIRTY 0x0080 // Set when data is dirtied
+//efine FHE_F6 0x0100 // Exit when F6 pressed
+#define FHE_ENTER 0x0800 // Exit when enter pressed
+
+#define FHE_DWORD 0x0200 // Default to dword edit
+#define FHE_JUMP 0x0400 // Support jump option
+
+void HexEdit (struct HexEditParm *);
+
+
+
+/*
+ * Read & Write functions are called as follows:
+ * (note: read & write can be NULL if fhe_editmem is set.
+ * if editmem is set & read&write are not NULL, then it is assumed
+ * that mem points to the memory image of what read&write are to
+ * read & write. (this is usefull for in-memory editing of items
+ * which also are to be read&write))
+ *
+ * rc = read (handle, offset, buf, len, &physloc)
+ *
+ * rc - returned, zero sucess. non-zero error code.
+ * handle - handle as passed into HexEdit
+ * offset - byte offset to read/write
+ * buf - address to read/write data
+ * len - len to read/write (probabily a sector, but may be less)
+ * physloc - address to put physcal sector number if known
+ *
+ *
+ *
+ * rc = write (handle, offset, buf, len, physloc)
+ *
+ * same as read params, expect 'physloc' is a long passed in and is
+ * whatever was returned to read.
+ *
+ */
diff --git a/private/sdktools/he/makefile b/private/sdktools/he/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/sdktools/he/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/he/makefile.inc b/private/sdktools/he/makefile.inc
new file mode 100644
index 000000000..801fd1b6b
--- /dev/null
+++ b/private/sdktools/he/makefile.inc
@@ -0,0 +1,2 @@
+obj\$(TARGET_DIRECTORY)\he.res: he.rc
+
diff --git a/private/sdktools/he/sources b/private/sdktools/he/sources
new file mode 100644
index 000000000..4b67757c4
--- /dev/null
+++ b/private/sdktools/he/sources
@@ -0,0 +1,27 @@
+!IF 0
+Sources file for building hexedit.lib & he.exe
+
+Author: kenr
+!ENDIF
+
+MAJORCOMP=sdktools
+MINORCOMP=he
+
+TARGETNAME=hexedit
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=LIBRARY
+
+INCLUDES=.
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=hexedit.c
+
+UMTYPE=console
+UMAPPL=he
+UMRES=$(@R).res
+UMLIBS=$(BASEDIR)\public\sdk\lib\*\hexedit.lib
+
+LINKLIBS=$(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+NTTARGETFILES=obj\*\he.res