|
|
/*****************************************************************/ /** 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)(); // 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 (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)); 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 : 3; HeGbl.AttrHigh = pParm->AttrHigh ? pParm->AttrHigh : 15; HeGbl.AttrReverse = pParm->AttrReverse ? pParm->AttrReverse : 112;
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); }
|