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/he | |
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/he')
-rw-r--r-- | private/sdktools/he/he.c | 386 | ||||
-rw-r--r-- | private/sdktools/he/he.rc | 11 | ||||
-rw-r--r-- | private/sdktools/he/hexedit.c | 2156 | ||||
-rw-r--r-- | private/sdktools/he/hexedit.h | 79 | ||||
-rw-r--r-- | private/sdktools/he/makefile | 6 | ||||
-rw-r--r-- | private/sdktools/he/makefile.inc | 2 | ||||
-rw-r--r-- | private/sdktools/he/sources | 27 |
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 |