You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2317 lines
65 KiB
2317 lines
65 KiB
|
|
/*****************************************************************/
|
|
/** 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 (HeGbl.BufferSize)
|
|
#define SECTORMASK (HeGbl.SectorMask)
|
|
#define SECTORSHIFT (HeGbl.SectorShift)
|
|
|
|
|
|
static UCHAR rghexc[] = "0123456789ABCDEF";
|
|
|
|
struct Buffer {
|
|
struct Buffer *next;
|
|
ULONGLONG offset;
|
|
ULONGLONG physloc;
|
|
USHORT flag;
|
|
USHORT len;
|
|
UCHAR *data;
|
|
UCHAR orig[0];
|
|
} ;
|
|
#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 0xFFFFFFFFFFFFFFF0
|
|
#define CELLPERLINE 88
|
|
|
|
struct Global {
|
|
struct HexEditParm *Parm;
|
|
HANDLE Console; // Internal console handle
|
|
HANDLE StdIn;
|
|
NTSTATUS (*Read)(HANDLE, ULONGLONG, PUCHAR, DWORD); // Copy of HeGbl.Parm->read
|
|
ULONG Flag; // Copy of HeGbl.Parm->flag
|
|
ULONGLONG TotLen; // Sizeof item being editted
|
|
ULONGLONG 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
|
|
ULONGLONG CurOffset; // Relative offset of first line
|
|
ULONGLONG 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
|
|
ULONGLONG 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;
|
|
USHORT BufferSize;
|
|
ULONGLONG SectorMask;
|
|
ULONG SectorShift;
|
|
} 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 __cdecl heDisp (USHORT, USHORT, PUCHAR, ...);
|
|
USHORT heIOErr (UCHAR *str, ULONGLONG loc, ULONGLONG 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 FILEINDEXWIDTH 16
|
|
#define HEXINDENT (FILEINDEXWIDTH + 2 + 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 (ULONGLONG);
|
|
void heSetUpdate (USHORT);
|
|
void heHexLine (struct Buffer *, USHORT, USHORT);
|
|
void heHexDWord (PCHAR_INFO, ULONG, WORD);
|
|
void heHexQWord (PCHAR_INFO, ULONGLONG, WORD);
|
|
USHORT heLtoa (PCHAR_INFO, ULONG);
|
|
ULONG heHtou (UCHAR *);
|
|
ULONGLONG heHtoLu (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);
|
|
|
|
|
|
ULONG
|
|
HighBit (
|
|
ULONG Word
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine discovers the highest set bit of the input word. It is
|
|
equivalent to the integer logarithim base 2.
|
|
|
|
Arguments:
|
|
|
|
Word - word to check
|
|
|
|
Return Value:
|
|
|
|
Bit offset of highest set bit. If no bit is set, return is zero.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Offset = 31;
|
|
ULONG Mask = (ULONG)(1 << 31);
|
|
|
|
if (Word == 0) {
|
|
|
|
return 0;
|
|
}
|
|
|
|
while ((Word & Mask) == 0) {
|
|
|
|
Offset--;
|
|
Mask >>= 1;
|
|
}
|
|
|
|
return Offset;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
*
|
|
* 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 (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));
|
|
if (!PriorGlobal) {
|
|
return;
|
|
}
|
|
memcpy ((PUCHAR) PriorGlobal, (PUCHAR) &HeGbl, sizeof (HeGbl));
|
|
}
|
|
|
|
memset (&HeGbl, 0, sizeof (HeGbl));
|
|
|
|
if (pParm->ioalign != 1) {
|
|
|
|
// operating on a device
|
|
HeGbl.BufferSize = (USHORT)pParm->ioalign;
|
|
HeGbl.SectorMask = ~(((ULONGLONG)pParm->ioalign) - 1);
|
|
HeGbl.SectorShift = HighBit( pParm->ioalign);
|
|
}
|
|
else {
|
|
|
|
// operating on a file, so just use 1k byte units
|
|
HeGbl.BufferSize = 0x400;
|
|
HeGbl.SectorMask = 0xfffffffffffffc00;
|
|
HeGbl.SectorShift = 9;
|
|
}
|
|
|
|
pParm->ioalign = 0;
|
|
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 : 0x07;
|
|
HeGbl.AttrHigh = pParm->AttrHigh ? pParm->AttrHigh : 0x70;
|
|
HeGbl.AttrReverse = pParm->AttrReverse ? pParm->AttrReverse : 0xf0;
|
|
|
|
HeGbl.SearchPattern = GlobalAlloc (0, BUFSZ);
|
|
if (!HeGbl.SearchPattern) {
|
|
memcpy((PUCHAR) &HeGbl, (PUCHAR) PriorGlobal, sizeof(HeGbl));
|
|
GlobalFree(PriorGlobal);
|
|
return;
|
|
}
|
|
memset (HeGbl.SearchPattern, 0, BUFSZ);
|
|
|
|
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;
|
|
|
|
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 & ~(ULONGLONG)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);
|
|
}
|
|
|
|
if (HeGbl.CurBuf) {
|
|
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;
|
|
{
|
|
ULONGLONG 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);
|
|
if (HeGbl.CurBuf)
|
|
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;
|
|
ULONGLONG 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
|
|
if (pBuf)
|
|
u = (USHORT) (loc - pBuf->offset); // calc offset into this buffer
|
|
}
|
|
|
|
if (pBuf) {
|
|
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;
|
|
{
|
|
ULONGLONG 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, 63, 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",(ULONG)(ploc/BUFSZ));
|
|
} else {
|
|
heDisp (TOPLINE+4, 14, "Location %H%Q%Nh-%H%Q%Nh 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);
|
|
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_PTR) 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 ()
|
|
{
|
|
struct Buffer *pBuf;
|
|
ULONGLONG j, sec, off, slen, len, upd;
|
|
ULONG i;
|
|
ULONGLONG iQ;
|
|
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 = BUFSZ;
|
|
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 < BUFSZ; 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 ();
|
|
|
|
iQ = HeGbl.CurEditLoc + 1;
|
|
sec = iQ & SECTORMASK; // current sector
|
|
off = iQ - 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%Qh ", sec);
|
|
heShowBuf (TOPLINE+6, 1);
|
|
}
|
|
|
|
pBuf = heGetBuf(sec);
|
|
if (pBuf) {
|
|
data = pBuf->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;
|
|
if (data2) {
|
|
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;
|
|
}
|
|
} else {
|
|
sec+=off;
|
|
}
|
|
|
|
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[24];
|
|
ULONGLONG l;
|
|
|
|
heSetUpdate (U_NONE);
|
|
heBox (12, TOPLINE+1, 49, 6);
|
|
|
|
heDisp (TOPLINE+3, 14, "Enter offset from %H%X%N - %H%Q", 0L, HeGbl.TotLen1);
|
|
heDisp (TOPLINE+5, 14, "Offset: ");
|
|
SetCurPos (TOPLINE+5, 22);
|
|
RefreshDisp ();
|
|
|
|
heGetString (s, 18);
|
|
|
|
if (s[0]) {
|
|
l = heHtoLu (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;
|
|
|
|
if (!ReadFile( HeGbl.StdIn, i, 50, &cb, NULL ))
|
|
return;
|
|
|
|
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[64];
|
|
ULONGLONG len, rem, upd;
|
|
ULONG 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%Q Bytes)", HeGbl.TotLen);
|
|
heDisp (TOPLINE+5, 14, "Filename: ");
|
|
SetCurPos (TOPLINE+5, 24);
|
|
RefreshDisp ();
|
|
|
|
heGetString (s, 59);
|
|
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%Q ", len);
|
|
heShowBuf (TOPLINE+6, 1);
|
|
RefreshDisp ();
|
|
}
|
|
|
|
u = rem > BUFSZ ? BUFSZ : (ULONG)rem;
|
|
pB = heGetBuf (len);
|
|
if (pB) {
|
|
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[64];
|
|
ULONGLONG holdEditLoc, rem;
|
|
ULONG 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%Q Bytes)", HeGbl.TotLen);
|
|
heDisp (TOPLINE+5, 14, "Filename: ");
|
|
SetCurPos (TOPLINE+5, 24);
|
|
RefreshDisp ();
|
|
|
|
heGetString (s, 59);
|
|
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);
|
|
if (pB) {
|
|
u = rem > BUFSZ ? BUFSZ : (ULONG)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;
|
|
}
|
|
}
|
|
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, (int)((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;
|
|
ULONGLONG 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;
|
|
|
|
//
|
|
// Write the file index. Highlight words falling on buffer (sector)
|
|
// boundries in white.
|
|
//
|
|
|
|
l = pBuf->offset + u;
|
|
if (l & ((ULONGLONG) BUFSZ-1)) {
|
|
heHexQWord (pt+LINEINDENT, pBuf->physloc + u, AttrNorm);
|
|
} else {
|
|
heHexQWord (pt+LINEINDENT, pBuf->physloc + u, HeGbl.AttrHigh);
|
|
}
|
|
|
|
if (pBuf->flag & FB_BAD) { // If read error on
|
|
pt[LINEINDENT+FILEINDEXWIDTH].Char.AsciiChar = 'E'; // this sector, then
|
|
pt[LINEINDENT+FILEINDEXWIDTH].Attributes = HeGbl.AttrHigh; // flag it
|
|
} else
|
|
pt[LINEINDENT+FILEINDEXWIDTH].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 < CELLPERLINE)
|
|
Mode.dwSize.X = CELLPERLINE;
|
|
|
|
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));
|
|
if (!HeGbl.pVioBuf) {
|
|
return 1;
|
|
}
|
|
|
|
HeGbl.dwVioBufSize.X = CELLPERLINE;
|
|
HeGbl.dwVioBufSize.Y = HeGbl.LineTot + 1;
|
|
|
|
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 = 0;
|
|
|
|
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 | FILE_SHARE_READ,
|
|
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: %Q ", HeGbl.TotLen);
|
|
if (HeGbl.TotLen < 0x100000000) {
|
|
heDisp (2, 28, "(%D)", (ULONG)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;
|
|
|
|
heHexQWord (POS(1, 50), HeGbl.CurEditLoc, HeGbl.AttrHigh);
|
|
|
|
if (HeGbl.TotLen < 0x100000000) {
|
|
|
|
heLtoa( POS(2, 50), (ULONG)HeGbl.CurEditLoc);
|
|
}
|
|
|
|
dwBufferCoord.X = 50;
|
|
dwBufferCoord.Y = 1;
|
|
|
|
lpWriteRegion.Left = 50;
|
|
lpWriteRegion.Top = HeGbl.TopLine + 1;
|
|
lpWriteRegion.Right = 74;
|
|
lpWriteRegion.Bottom = HeGbl.TopLine + 2;
|
|
|
|
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 (ULONGLONG loc)
|
|
{
|
|
struct Buffer **ppBuf, *pBuf;
|
|
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
|
|
*/
|
|
|
|
if (vBufFree) {
|
|
pBuf = vBufFree;
|
|
vBufFree = vBufFree->next;
|
|
} else {
|
|
pBuf = (struct Buffer *)
|
|
GlobalAlloc (0, sizeof(struct Buffer)+2*BUFSZ);
|
|
if (!pBuf) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
pBuf->data = (PUCHAR)(((ULONG_PTR)pBuf+sizeof(struct Buffer)+BUFSZ));
|
|
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);
|
|
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);
|
|
|
|
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, ULONGLONG loc, ULONGLONG 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 %Qh, Sector %D",
|
|
errcd, loc, (ULONG)(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 __cdecl
|
|
heDisp (USHORT line, USHORT col, PUCHAR 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 'Q': /* LongLong HEX, fixed len */
|
|
heHexQWord (pOut, va_arg(args, ULONGLONG), attr);
|
|
pOut += 16;
|
|
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--;
|
|
}
|
|
}
|
|
|
|
|
|
void heHexQWord (s, l, attr)
|
|
PCHAR_INFO s;
|
|
ULONGLONG l;
|
|
WORD attr;
|
|
{
|
|
UCHAR d, c;
|
|
UCHAR *pt;
|
|
|
|
s += 16-1;
|
|
pt = (UCHAR *) &l;
|
|
|
|
for (d=0; d<8; 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';
|
|
s->Attributes = HeGbl.AttrNorm;
|
|
if (comm[i] == ',') {
|
|
s++;
|
|
s->Attributes = HeGbl.AttrNorm;
|
|
s->Char.AsciiChar = ',';
|
|
}
|
|
s++;
|
|
}
|
|
|
|
i = (USHORT)(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 * (ULONG)BUFSZ;
|
|
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;
|
|
}
|
|
|
|
ULONGLONG heHtoLu (s)
|
|
UCHAR *s;
|
|
{
|
|
UCHAR c;
|
|
ULONGLONG l;
|
|
|
|
l = 0;
|
|
for (; ;) {
|
|
c = *(s++);
|
|
|
|
if (c == 's' || c == 'S') { // Sector multiplier?
|
|
l = l * (ULONG)BUFSZ;
|
|
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);
|
|
}
|