Source code of Windows XP (NT5)
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.

2318 lines
63 KiB

  1. /*****************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1988-1990 **/
  4. /*****************************************************************/
  5. /**** hexedit.c - Generic sector based hex editor function call
  6. *
  7. * Fill out a HexEditParm structure, and call HexEdit. It provides
  8. * a simple hex editor with a few misc features.
  9. *
  10. * Is single threaded & non-reentrant, but can be called from any thread.
  11. *
  12. * External uses:
  13. * he - allows editing of a file
  14. *
  15. * Written: Ken Reneris 2/25/91
  16. *
  17. */
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <stdio.h>
  22. #include <windows.h>
  23. #include "hexedit.h"
  24. #include <stdarg.h>
  25. #define LOCAL static
  26. // #define LOCAL
  27. #define BUFSZ (HeGbl.BufferSize)
  28. #define SECTORMASK (HeGbl.SectorMask)
  29. #define SECTORSHIFT (HeGbl.SectorShift)
  30. static UCHAR rghexc[] = "0123456789ABCDEF";
  31. struct Buffer {
  32. struct Buffer *next;
  33. ULONGLONG offset;
  34. ULONGLONG physloc;
  35. USHORT flag;
  36. USHORT len;
  37. UCHAR *data;
  38. UCHAR orig[0];
  39. } ;
  40. #define FB_DIRTY 0x0001 // Buffer may be dirty
  41. #define FB_BAD 0x0002 // Buffer had an error when read in
  42. #define LINESZ 16 // 16 bytes per display line
  43. #define LINESHIFT 4L
  44. #define LINEMASK 0xFFFFFFFFFFFFFFF0
  45. #define CELLPERLINE 88
  46. struct Global {
  47. struct HexEditParm *Parm;
  48. HANDLE Console; // Internal console handle
  49. HANDLE StdIn;
  50. NTSTATUS (*Read)(); // Copy of HeGbl.Parm->read
  51. ULONG Flag; // Copy of HeGbl.Parm->flag
  52. ULONGLONG TotLen; // Sizeof item being editted
  53. ULONGLONG TotLen1; // Sizeof item being editted - 1
  54. USHORT Lines; // # of lines in edit screen
  55. USHORT LineTot; // # of lines totaly in use
  56. USHORT PageSz; // sizeof page in bytes
  57. USHORT TopLine; // TopLine edit starts at
  58. ULONGLONG CurOffset; // Relative offset of first line
  59. ULONGLONG CurEditLoc; // Location with cursor
  60. UCHAR *CurPT; // Pointer to data where cursor is
  61. UCHAR CurAscIndent;
  62. UCHAR DWidth; // width of dispalymode
  63. UCHAR na;
  64. struct Buffer *CurBuf; // Buffer which cursor is in
  65. ULONG CurFlag; // Cursor info
  66. ULONG DisplayMode; // Mask of displaymode
  67. ULONG ItemWrap; // Mask of displaymode wrap
  68. UCHAR rgCols[LINESZ]; // Location within lines
  69. ULONGLONG UpdatePos; // Location waitin to be updated
  70. struct Buffer *Buf; // List of buffer's read in
  71. PCHAR_INFO pVioBuf; // Virtual screen
  72. COORD dwVioBufSize; // Dimensions of HeGbl.pVioBuf
  73. COORD CursorPos; // Position of cursor
  74. WORD AttrNorm; // Attribute of plain text
  75. WORD AttrHigh; // Attribute of highlighted text
  76. WORD AttrReverse; // Attribute of reverse text
  77. WORD na3;
  78. COORD dwSize; // Original screen size
  79. ULONG OrigMode; // Original screen mode
  80. CONSOLE_CURSOR_INFO CursorInfo; // Original cursor info
  81. PUCHAR SearchPattern;
  82. USHORT BufferSize;
  83. ULONGLONG SectorMask;
  84. ULONG SectorShift;
  85. } HeGbl;
  86. #define D_BYTE 0 // DisplayMode
  87. #define D_WORD 1
  88. #define D_DWORD 3
  89. #define FC_NIBBLE 0x0001 // Cursor on lower or upper nibble?
  90. #define FC_TEXT 0x0002 // Cursor on Hex or Text
  91. #define FC_INFLUSHBUF 0x1000 // So we don't recurse
  92. #define FC_CURCENTER 0x2000 // if jumping to cursor, put in center
  93. #define PUTCHAR(a,b,c) { a->Char.AsciiChar=b; a->Attributes=c; a++; }
  94. //
  95. // Internal prototypes
  96. //
  97. int heUpdateStats(), hePositionCursor(), heRefresh(), heSetDisp();
  98. int heInitConsole(), heUpdateAllLines(), heInitScr(), heSetCursorBuf(), heUpdateFncs();
  99. VOID __cdecl heDisp (USHORT, USHORT, PUCHAR, ...);
  100. USHORT heIOErr (UCHAR *str, ULONGLONG loc, ULONGLONG ploc, ULONG errcd);
  101. int heFlushBuf (struct Buffer *pBuf);
  102. VOID heEndConsole(), heGotoPosition(), heJumpToLink();
  103. VOID heUpdateCurLine(), heUndo(), heCopyOut(), heCopyIn(), heSearch();
  104. VOID heBox (USHORT x, USHORT y, USHORT len_x, USHORT len_y);
  105. UCHAR heGetChar (PUCHAR keys);
  106. VOID heFlushAllBufs (USHORT update);
  107. VOID heFindMousePos (COORD);
  108. VOID heShowBuf (ULONG, ULONG);
  109. VOID heSetDisplayMode (ULONG mode);
  110. #define RefreshDisp() heShowBuf(0, HeGbl.LineTot)
  111. #define SetCurPos(a,b) { \
  112. HeGbl.CursorPos.X = b; \
  113. HeGbl.CursorPos.Y = a + HeGbl.TopLine; \
  114. SetConsoleCursorPosition (HeGbl.Console, HeGbl.CursorPos); \
  115. }
  116. int (*vrgUpdateFnc[])() = {
  117. NULL, // 0 - No update
  118. heUpdateStats, // 1 - Update stats
  119. hePositionCursor, // 2 - Cursor has new position
  120. heUpdateAllLines, // 3 - Update all lines
  121. heUpdateFncs, // 4 -
  122. hePositionCursor, // 5 - Calc cursor before AllLines
  123. heRefresh, // 6 - Clear lines
  124. heSetDisp, // 7 - Draws init screen
  125. // the following functions are only called once during init
  126. heInitScr, // 8 - get's video mode, etc.
  127. heInitConsole // 9 - setup console handle
  128. } ;
  129. #define U_NONE 0
  130. #define U_NEWPOS 2
  131. #define U_SCREEN 5
  132. #define U_REDRAW 9
  133. #define TOPLINE 4
  134. #define LINEINDENT 1
  135. #define FILEINDEXWIDTH 16
  136. #define HEXINDENT (FILEINDEXWIDTH + 2 + LINEINDENT)
  137. #define ASCINDENT_BYTE (3*16 + HEXINDENT + 1)
  138. #define ASCINDENT_WORD (5*8 + HEXINDENT + 1)
  139. #define ASCINDENT_DWORD (9*4 + HEXINDENT + 1)
  140. #define POS(l,c) (HeGbl.pVioBuf+CELLPERLINE*(l)+c)
  141. USHORT vrgAscIndent[] = {
  142. ASCINDENT_BYTE, ASCINDENT_WORD, 0, ASCINDENT_DWORD
  143. };
  144. UCHAR vrgDWidth[] = { 2, 4, 0, 8 };
  145. LOCAL struct Buffer *vBufFree; // List of free buffers
  146. LOCAL USHORT vUpdate;
  147. LOCAL USHORT vRecurseLevel = 0;
  148. LOCAL BOOL vInSearch = FALSE;
  149. /*
  150. * Prototypes
  151. */
  152. struct Buffer *heGetBuf (ULONGLONG);
  153. void heSetUpdate (USHORT);
  154. void heHexLine (struct Buffer *, USHORT, USHORT);
  155. void heHexDWord (PCHAR_INFO, ULONG, WORD);
  156. void heHexQWord (PCHAR_INFO, ULONGLONG, WORD);
  157. USHORT heLtoa (PCHAR_INFO, ULONG);
  158. ULONG heHtou (UCHAR *);
  159. ULONGLONG heHtoLu (UCHAR *);
  160. VOID heCalcCursorPosition ();
  161. VOID heGetString (PUCHAR s, USHORT len);
  162. VOID heRightOne ();
  163. VOID heLeftOne ();
  164. NTSTATUS heWriteFile (HANDLE h, PUCHAR buffer, ULONG len);
  165. NTSTATUS heReadFile (HANDLE h, PUCHAR buffer, ULONG len, PULONG br);
  166. NTSTATUS heOpenFile (PUCHAR Name, PHANDLE handle, ULONG access);
  167. ULONG
  168. HighBit (
  169. ULONG Word
  170. )
  171. /*++
  172. Routine Description:
  173. This routine discovers the highest set bit of the input word. It is
  174. equivalent to the integer logarithim base 2.
  175. Arguments:
  176. Word - word to check
  177. Return Value:
  178. Bit offset of highest set bit. If no bit is set, return is zero.
  179. --*/
  180. {
  181. ULONG Offset = 31;
  182. ULONG Mask = (ULONG)(1 << 31);
  183. if (Word == 0) {
  184. return 0;
  185. }
  186. while ((Word & Mask) == 0) {
  187. Offset--;
  188. Mask >>= 1;
  189. }
  190. return Offset;
  191. }
  192. /***
  193. *
  194. * HexEdit - Full screen HexEdit of data
  195. *
  196. * ename - pointer to name of what's being edited
  197. * totlen - length of item being edited
  198. * pRead - function which can read data from item
  199. * pWrite - function which can write data to item
  200. * handle - handle to pass to pRead & pWrite
  201. * flag -
  202. *
  203. *
  204. * All IO is assumed to be done on in 512 bytes on 512 byte boundrys
  205. *
  206. * pRead (handle, offset, data, &physloc)
  207. * pWrite (handle, offset, data, &physloc)
  208. *
  209. */
  210. void HexEdit (pParm)
  211. struct HexEditParm *pParm;
  212. {
  213. USHORT rc;
  214. INPUT_RECORD Kd;
  215. USHORT SkipCnt;
  216. DWORD cEvents;
  217. USHORT RepeatCnt;
  218. BOOL bSuccess;
  219. struct Global *PriorGlobal;
  220. // code is not multi-threaded capable, but it can resurse.
  221. vRecurseLevel++;
  222. if (vRecurseLevel > 1) {
  223. PriorGlobal = (struct Global *) GlobalAlloc (0, sizeof (HeGbl));
  224. if (!PriorGlobal) {
  225. return;
  226. }
  227. memcpy ((PUCHAR) PriorGlobal, (PUCHAR) &HeGbl, sizeof (HeGbl));
  228. }
  229. memset (&HeGbl, 0, sizeof (HeGbl));
  230. if (pParm->ioalign != 1) {
  231. // operating on a device
  232. HeGbl.BufferSize = (USHORT)pParm->ioalign;
  233. HeGbl.SectorMask = ~(((ULONGLONG)pParm->ioalign) - 1);
  234. HeGbl.SectorShift = HighBit( pParm->ioalign);
  235. }
  236. else {
  237. // operating on a file, so just use 1k byte units
  238. HeGbl.BufferSize = 0x400;
  239. HeGbl.SectorMask = 0xfffffffffffffc00;
  240. HeGbl.SectorShift = 9;
  241. }
  242. pParm->ioalign = 0;
  243. HeGbl.Parm = pParm;
  244. HeGbl.Flag = pParm->flag;
  245. HeGbl.TotLen = pParm->totlen;
  246. HeGbl.Read = pParm->read;
  247. HeGbl.TotLen1 = HeGbl.TotLen ? HeGbl.TotLen - 1L : 0L;
  248. pParm->flag = 0;
  249. HeGbl.CurEditLoc = pParm->start; // Cursor starts here
  250. HeGbl.CurOffset = HeGbl.CurEditLoc & LINEMASK; // Start at valid offset
  251. HeGbl.CurFlag = FC_NIBBLE;
  252. HeGbl.Console = INVALID_HANDLE_VALUE;
  253. heSetDisplayMode ((HeGbl.Flag & FHE_DWORD) ? D_DWORD : D_BYTE);
  254. HeGbl.AttrNorm = pParm->AttrNorm ? pParm->AttrNorm : 3;
  255. HeGbl.AttrHigh = pParm->AttrHigh ? pParm->AttrHigh : 15;
  256. HeGbl.AttrReverse = pParm->AttrReverse ? pParm->AttrReverse : 112;
  257. HeGbl.SearchPattern = GlobalAlloc (0, BUFSZ);
  258. if (!HeGbl.SearchPattern) {
  259. memcpy((PUCHAR) &HeGbl, (PUCHAR) PriorGlobal, sizeof(HeGbl));
  260. GlobalFree(PriorGlobal);
  261. return;
  262. }
  263. memset (HeGbl.SearchPattern, 0, BUFSZ);
  264. RepeatCnt = 0;
  265. vUpdate = U_REDRAW;
  266. heSetUpdate (U_NONE); // get screen to redraw
  267. for (; ;) {
  268. if (RepeatCnt <= 1) {
  269. if (vUpdate != U_NONE) { // Something to update?
  270. if (SkipCnt++ > 10) {
  271. SkipCnt = 0;
  272. heSetUpdate (U_NONE);
  273. continue;
  274. }
  275. cEvents = 0;
  276. bSuccess = PeekConsoleInput( HeGbl.StdIn,
  277. &Kd,
  278. 1,
  279. &cEvents );
  280. if (!bSuccess || cEvents == 0) {
  281. heSetUpdate ((USHORT)(vUpdate-1));
  282. continue;
  283. }
  284. } else {
  285. SkipCnt = 0;
  286. }
  287. ReadConsoleInput (HeGbl.StdIn, &Kd, 1, &cEvents);
  288. if (Kd.EventType != KEY_EVENT) {
  289. if (Kd.EventType == MOUSE_EVENT &&
  290. (Kd.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)) {
  291. heFindMousePos(Kd.Event.MouseEvent.dwMousePosition);
  292. }
  293. continue; // Not a key
  294. }
  295. if (!Kd.Event.KeyEvent.bKeyDown)
  296. continue; // Not a down stroke
  297. if (Kd.Event.KeyEvent.wVirtualKeyCode == 0 || // ALT
  298. Kd.Event.KeyEvent.wVirtualKeyCode == 0x10 || // SHIFT
  299. Kd.Event.KeyEvent.wVirtualKeyCode == 0x11 || // CONTROL
  300. Kd.Event.KeyEvent.wVirtualKeyCode == 0x14) // CAPITAL
  301. continue;
  302. RepeatCnt = Kd.Event.KeyEvent.wRepeatCount;
  303. if (RepeatCnt > 20)
  304. RepeatCnt = 20;
  305. } else
  306. RepeatCnt--;
  307. switch (Kd.Event.KeyEvent.wVirtualKeyCode) {
  308. case 0x21: /* PgUp */
  309. if (HeGbl.CurOffset < HeGbl.PageSz)
  310. HeGbl.CurOffset = 0L;
  311. else HeGbl.CurOffset -= HeGbl.PageSz;
  312. if (HeGbl.CurEditLoc < HeGbl.PageSz)
  313. HeGbl.CurEditLoc = 0L;
  314. else HeGbl.CurEditLoc -= HeGbl.PageSz;
  315. heSetUpdate (U_SCREEN);
  316. continue;
  317. case 0x26: /* Up */
  318. if (HeGbl.CurEditLoc >= LINESZ) {
  319. HeGbl.CurEditLoc -= LINESZ;
  320. heSetUpdate (U_NEWPOS);
  321. }
  322. continue;
  323. case 0x22: /* PgDn */
  324. if (HeGbl.TotLen > HeGbl.PageSz) {
  325. if (HeGbl.CurOffset+HeGbl.PageSz+HeGbl.PageSz > HeGbl.TotLen1)
  326. HeGbl.CurOffset = ((HeGbl.TotLen1-HeGbl.PageSz) & LINEMASK)+LINESZ;
  327. else HeGbl.CurOffset += HeGbl.PageSz;
  328. if (HeGbl.CurEditLoc+HeGbl.PageSz > HeGbl.TotLen1) {
  329. HeGbl.CurEditLoc = HeGbl.TotLen1;
  330. HeGbl.CurFlag &= ~FC_NIBBLE;
  331. } else
  332. HeGbl.CurEditLoc += HeGbl.PageSz;
  333. heSetUpdate (U_SCREEN);
  334. }
  335. continue;
  336. case 0x28: /* Down */
  337. if (HeGbl.CurEditLoc+LINESZ <= HeGbl.TotLen1) {
  338. HeGbl.CurEditLoc += LINESZ;
  339. heSetUpdate (U_NEWPOS);
  340. }
  341. continue;
  342. case 0x08: /* backspace */
  343. case 0x25: /* Left */
  344. if (HeGbl.CurFlag & FC_TEXT) {
  345. if (HeGbl.CurEditLoc == 0L)
  346. continue;
  347. HeGbl.CurEditLoc--;
  348. heSetUpdate (U_NEWPOS);
  349. continue;
  350. }
  351. if (!(HeGbl.CurFlag & FC_NIBBLE)) {
  352. HeGbl.CurFlag |= FC_NIBBLE;
  353. heSetUpdate (U_NEWPOS);
  354. continue;
  355. }
  356. HeGbl.CurFlag &= ~FC_NIBBLE;
  357. heLeftOne ();
  358. heSetUpdate (U_NEWPOS);
  359. continue;
  360. case 0x27: /* Right */
  361. if (HeGbl.CurFlag & FC_TEXT) {
  362. if (HeGbl.CurEditLoc >= HeGbl.TotLen1)
  363. continue;
  364. HeGbl.CurEditLoc++;
  365. heSetUpdate (U_NEWPOS);
  366. continue;
  367. }
  368. if (HeGbl.CurFlag & FC_NIBBLE) {
  369. HeGbl.CurFlag &= ~FC_NIBBLE;
  370. heSetUpdate (U_NEWPOS);
  371. continue;
  372. }
  373. HeGbl.CurFlag |= FC_NIBBLE;
  374. heRightOne ();
  375. heSetUpdate (U_NEWPOS);
  376. continue;
  377. case 0x24: /* HOME */
  378. if (Kd.Event.KeyEvent.dwControlKeyState &
  379. (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) {
  380. HeGbl.CurEditLoc = 0L;
  381. } else {
  382. HeGbl.CurEditLoc &= LINEMASK;
  383. }
  384. if ((HeGbl.CurFlag & FC_TEXT) == 0)
  385. HeGbl.CurEditLoc += HeGbl.DisplayMode;
  386. if (HeGbl.CurEditLoc > HeGbl.TotLen1)
  387. HeGbl.CurEditLoc = HeGbl.TotLen1;
  388. HeGbl.CurFlag |= FC_NIBBLE;
  389. heSetUpdate (U_NEWPOS);
  390. continue;
  391. case 0x23: /* END */
  392. if (Kd.Event.KeyEvent.dwControlKeyState &
  393. (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) {
  394. HeGbl.CurEditLoc = HeGbl.TotLen1;
  395. } else {
  396. HeGbl.CurEditLoc = (HeGbl.CurEditLoc & LINEMASK) + LINESZ - 1;
  397. }
  398. HeGbl.CurFlag &= ~FC_NIBBLE;
  399. if ((HeGbl.CurFlag & FC_TEXT) == 0)
  400. HeGbl.CurEditLoc -= HeGbl.DisplayMode;
  401. if (HeGbl.CurEditLoc > HeGbl.TotLen1)
  402. HeGbl.CurEditLoc = HeGbl.TotLen1;
  403. heSetUpdate (U_NEWPOS);
  404. continue;
  405. case 0x70: /* F1 */
  406. switch (HeGbl.DisplayMode) {
  407. case D_BYTE: heSetDisplayMode(D_WORD); break;
  408. case D_WORD: heSetDisplayMode(D_DWORD); break;
  409. case D_DWORD: heSetDisplayMode(D_BYTE); break;
  410. }
  411. heSetDisp ();
  412. heSetUpdate (U_SCREEN);
  413. continue;
  414. case 0x71: /* F2 */
  415. heGotoPosition ();
  416. continue;
  417. case 0x72: /* F3 */
  418. heSearch ();
  419. break;
  420. case 0x73: /* F4 */
  421. heCopyOut ();
  422. heSetDisp ();
  423. heSetUpdate (U_SCREEN);
  424. continue;
  425. case 0x74: /* F5 */
  426. heCopyIn ();
  427. heSetDisp ();
  428. heSetUpdate (U_SCREEN);
  429. continue;
  430. case 0x75: /* F6 */
  431. heJumpToLink ();
  432. break;
  433. case 0x79: /* F10 */
  434. heUndo ();
  435. continue;
  436. case 0x0d:
  437. if (HeGbl.Flag & FHE_ENTER) {
  438. HeGbl.Parm->flag |= FHE_ENTER;
  439. Kd.Event.KeyEvent.uChar.AsciiChar = 27; // fake an exit
  440. }
  441. break;
  442. //case 0x75: /* F6 */
  443. // if (HeGbl.Flag & FHE_F6) {
  444. // HeGbl.Parm->flag |= FHE_F6;
  445. // Kd.Event.KeyEvent.uChar.AsciiChar = 27; // fake an exit
  446. // }
  447. // break;
  448. }
  449. // Now check for a known char code...
  450. if (Kd.Event.KeyEvent.uChar.AsciiChar == 27)
  451. break;
  452. if (Kd.Event.KeyEvent.uChar.AsciiChar == 9) {
  453. HeGbl.CurFlag ^= FC_TEXT;
  454. HeGbl.CurFlag |= FC_NIBBLE;
  455. heSetUpdate (U_NEWPOS);
  456. continue;
  457. }
  458. if (HeGbl.CurFlag & FC_TEXT) {
  459. if (Kd.Event.KeyEvent.uChar.AsciiChar == 0)
  460. continue;
  461. heSetCursorBuf ();
  462. *HeGbl.CurPT = Kd.Event.KeyEvent.uChar.AsciiChar;
  463. heUpdateCurLine ();
  464. if (HeGbl.CurEditLoc < HeGbl.TotLen1)
  465. HeGbl.CurEditLoc++;
  466. } else {
  467. if (Kd.Event.KeyEvent.uChar.AsciiChar >= 'a' &&
  468. Kd.Event.KeyEvent.uChar.AsciiChar <= 'z')
  469. Kd.Event.KeyEvent.uChar.AsciiChar -= ('a' - 'A');
  470. if (!((Kd.Event.KeyEvent.uChar.AsciiChar >= '0' &&
  471. Kd.Event.KeyEvent.uChar.AsciiChar <= '9') ||
  472. (Kd.Event.KeyEvent.uChar.AsciiChar >= 'A' &&
  473. Kd.Event.KeyEvent.uChar.AsciiChar <= 'F')))
  474. continue;
  475. heSetCursorBuf ();
  476. if (Kd.Event.KeyEvent.uChar.AsciiChar >= 'A')
  477. Kd.Event.KeyEvent.uChar.AsciiChar -= 'A' - 10;
  478. else Kd.Event.KeyEvent.uChar.AsciiChar -= '0';
  479. if (HeGbl.CurFlag & FC_NIBBLE) {
  480. *HeGbl.CurPT = (*HeGbl.CurPT & 0x0F) |
  481. (Kd.Event.KeyEvent.uChar.AsciiChar << 4);
  482. heUpdateCurLine ();
  483. } else {
  484. *HeGbl.CurPT = (*HeGbl.CurPT & 0xF0) |
  485. Kd.Event.KeyEvent.uChar.AsciiChar;
  486. heUpdateCurLine ();
  487. heRightOne ();
  488. }
  489. HeGbl.CurFlag ^= FC_NIBBLE;
  490. }
  491. }
  492. /*
  493. * Free buffer memory
  494. */
  495. for (; ;) {
  496. rc = 0;
  497. while (HeGbl.Buf) {
  498. rc |= heFlushBuf (HeGbl.Buf);
  499. HeGbl.CurBuf = HeGbl.Buf->next;
  500. GlobalFree (HeGbl.Buf);
  501. HeGbl.Buf = HeGbl.CurBuf;
  502. }
  503. if (!rc) // If something was flushed,
  504. break; // then update the screen
  505. heSetUpdate (U_SCREEN);
  506. heSetUpdate (U_NONE);
  507. } // and loop to free buffers (again)
  508. vRecurseLevel--;
  509. GlobalFree (HeGbl.SearchPattern);
  510. heEndConsole ();
  511. if (vRecurseLevel == 0) {
  512. while (vBufFree) {
  513. HeGbl.CurBuf = vBufFree->next;
  514. GlobalFree (vBufFree);
  515. vBufFree = HeGbl.CurBuf;
  516. }
  517. } else {
  518. memcpy ((PUCHAR) &HeGbl, (PUCHAR) PriorGlobal, sizeof (HeGbl));
  519. GlobalFree (PriorGlobal);
  520. }
  521. }
  522. VOID heSetDisplayMode (ULONG mode)
  523. {
  524. PUCHAR p;
  525. UCHAR d,i,j,h,len;
  526. HeGbl.DisplayMode = mode;
  527. HeGbl.CurAscIndent = (UCHAR)vrgAscIndent[HeGbl.DisplayMode];
  528. HeGbl.DWidth = vrgDWidth[HeGbl.DisplayMode];
  529. HeGbl.ItemWrap = (HeGbl.DisplayMode << 1) | 1;
  530. i = HeGbl.DWidth;
  531. j = i >> 1;
  532. h = HEXINDENT;
  533. len = LINESZ;
  534. p = HeGbl.rgCols;
  535. while (len) {
  536. for (d=0; d < i; d += 2) {
  537. len--;
  538. *(p++) = i - (d+2) + h;
  539. }
  540. h += i + 1;
  541. }
  542. }
  543. VOID heRightOne ()
  544. {
  545. if (HeGbl.CurEditLoc & HeGbl.DisplayMode) {
  546. HeGbl.CurEditLoc--;
  547. } else {
  548. HeGbl.CurEditLoc += HeGbl.ItemWrap;
  549. }
  550. if (HeGbl.CurEditLoc > HeGbl.TotLen1) {
  551. HeGbl.CurEditLoc = HeGbl.TotLen1 & ~(ULONGLONG)HeGbl.DisplayMode;
  552. }
  553. }
  554. VOID heLeftOne ()
  555. {
  556. if ((HeGbl.CurEditLoc & HeGbl.DisplayMode) != HeGbl.DisplayMode) {
  557. if (HeGbl.CurEditLoc < HeGbl.TotLen1) {
  558. HeGbl.CurEditLoc++;
  559. return ;
  560. }
  561. if (HeGbl.TotLen1 > HeGbl.DisplayMode) {
  562. HeGbl.CurEditLoc |= HeGbl.DisplayMode;
  563. }
  564. }
  565. if (HeGbl.CurEditLoc > HeGbl.ItemWrap) {
  566. HeGbl.CurEditLoc -= HeGbl.ItemWrap;
  567. return ;
  568. }
  569. HeGbl.CurEditLoc =
  570. HeGbl.TotLen1 > HeGbl.DisplayMode ? HeGbl.DisplayMode : HeGbl.TotLen1;
  571. }
  572. VOID heUpdateCurLine ()
  573. {
  574. USHORT line;
  575. for (; ;) {
  576. HeGbl.CurBuf->flag |= FB_DIRTY;
  577. line = (USHORT) ((HeGbl.CurEditLoc - HeGbl.CurOffset) >> LINESHIFT);
  578. if (line+TOPLINE < HeGbl.LineTot - 1)
  579. break;
  580. heSetUpdate (U_NEWPOS);
  581. heSetUpdate (U_NONE);
  582. HeGbl.CurBuf = heGetBuf (HeGbl.CurEditLoc);
  583. }
  584. if (HeGbl.CurBuf) {
  585. heHexLine (HeGbl.CurBuf, (USHORT)((HeGbl.CurEditLoc & LINEMASK) - HeGbl.CurBuf->offset), line);
  586. heShowBuf (line+TOPLINE, 1);
  587. heSetUpdate (U_NEWPOS);
  588. if (HeGbl.Flag & FHE_KICKDIRTY) {
  589. HeGbl.Parm->flag |= FHE_DIRTY;
  590. SetEvent (HeGbl.Parm->Kick);
  591. }
  592. }
  593. }
  594. void heFindMousePos (Pos)
  595. COORD Pos;
  596. {
  597. ULONGLONG HoldLocation;
  598. USHORT HoldFlag;
  599. USHORT i;
  600. if (Pos.Y < TOPLINE || Pos.Y >= TOPLINE+HeGbl.Lines)
  601. return ;
  602. heSetUpdate (U_NONE);
  603. HoldLocation = HeGbl.CurEditLoc;
  604. HoldFlag = (USHORT)HeGbl.CurFlag;
  605. //
  606. // Take the cheap way out - simply run all the possibilities for the
  607. // target line looking for a match
  608. //
  609. HeGbl.CurEditLoc = HeGbl.CurOffset + ((Pos.Y-TOPLINE) << LINESHIFT);
  610. for (i=0; i < LINESZ; i++, HeGbl.CurEditLoc++) {
  611. HeGbl.CurFlag &= ~(FC_NIBBLE | FC_TEXT);
  612. heCalcCursorPosition ();
  613. if (Pos.X == HeGbl.CursorPos.X)
  614. break;
  615. HeGbl.CurFlag |= FC_NIBBLE;
  616. heCalcCursorPosition ();
  617. if (Pos.X == HeGbl.CursorPos.X)
  618. break;
  619. HeGbl.CurFlag |= FC_TEXT;
  620. heCalcCursorPosition ();
  621. if (Pos.X == HeGbl.CursorPos.X)
  622. break;
  623. }
  624. if (Pos.X == HeGbl.CursorPos.X) {
  625. heSetUpdate (U_NEWPOS);
  626. } else {
  627. HeGbl.CurEditLoc = HoldLocation;
  628. HeGbl.CurFlag = HoldFlag;
  629. heCalcCursorPosition ();
  630. }
  631. }
  632. VOID heSetUpdate (USHORT i)
  633. {
  634. USHORT u;
  635. if (vUpdate) {
  636. /*
  637. * There's already some outstanding update going on
  638. * Get updat level down to current one.
  639. */
  640. while (vUpdate > i) {
  641. vrgUpdateFnc [u=vUpdate] ();
  642. if (u == vUpdate) // If vUpdate changed, then
  643. vUpdate--; // we might have recursed
  644. }
  645. }
  646. vUpdate = i;
  647. }
  648. int heSetCursorBuf ()
  649. {
  650. // Calc HeGbl.CurBuf, HeGbl.CurPT
  651. if (HeGbl.CurBuf) {
  652. if (HeGbl.CurEditLoc >= HeGbl.CurBuf->offset &&
  653. HeGbl.CurEditLoc < HeGbl.CurBuf->offset+BUFSZ ) {
  654. HeGbl.CurPT = HeGbl.CurBuf->data + (HeGbl.CurEditLoc - HeGbl.CurBuf->offset);
  655. return 0;
  656. }
  657. }
  658. HeGbl.CurBuf = heGetBuf (HeGbl.CurEditLoc);
  659. if (HeGbl.CurBuf)
  660. HeGbl.CurPT = HeGbl.CurBuf->data + (HeGbl.CurEditLoc - HeGbl.CurBuf->offset);
  661. return 0;
  662. }
  663. int hePositionCursor ()
  664. {
  665. heCalcCursorPosition ();
  666. SetConsoleCursorPosition (HeGbl.Console, HeGbl.CursorPos);
  667. if ((HeGbl.Flag & FHE_KICKMOVE) && (HeGbl.CurEditLoc != HeGbl.Parm->editloc)) {
  668. HeGbl.Parm->editloc = HeGbl.CurEditLoc;
  669. SetEvent (HeGbl.Parm->Kick);
  670. }
  671. return 0;
  672. }
  673. VOID heCalcCursorPosition ()
  674. {
  675. USHORT lin, col;
  676. // Verify HeGbl.CurOffset
  677. if (HeGbl.CurEditLoc < HeGbl.CurOffset) {
  678. HeGbl.CurOffset = HeGbl.CurEditLoc & LINEMASK;
  679. if (HeGbl.CurFlag & FC_CURCENTER) {
  680. if (HeGbl.CurOffset > (ULONG) HeGbl.PageSz / 2) {
  681. HeGbl.CurOffset -= (HeGbl.PageSz / 2) & LINEMASK;
  682. } else {
  683. HeGbl.CurOffset = 0;
  684. }
  685. }
  686. heSetUpdate (U_SCREEN);
  687. }
  688. if (HeGbl.CurEditLoc >= HeGbl.CurOffset+HeGbl.PageSz) {
  689. HeGbl.CurOffset = ((HeGbl.CurEditLoc - HeGbl.PageSz) & LINEMASK) + LINESZ;
  690. if (HeGbl.CurFlag & FC_CURCENTER) {
  691. if (HeGbl.CurOffset+HeGbl.PageSz < HeGbl.TotLen) {
  692. HeGbl.CurOffset += (HeGbl.PageSz / 2) & LINEMASK;
  693. } else {
  694. if (HeGbl.TotLen > HeGbl.PageSz) {
  695. HeGbl.CurOffset = ((HeGbl.TotLen - HeGbl.PageSz) & LINEMASK) + LINESZ;
  696. }
  697. }
  698. }
  699. heSetUpdate (U_SCREEN);
  700. }
  701. lin = (USHORT) ((ULONG) HeGbl.CurEditLoc - HeGbl.CurOffset) >> LINESHIFT;
  702. if (HeGbl.CurFlag & FC_TEXT) {
  703. col = (USHORT) (HeGbl.CurEditLoc & ~LINEMASK) + HeGbl.CurAscIndent+1;
  704. } else {
  705. col = HeGbl.rgCols [HeGbl.CurEditLoc & ~LINEMASK] +
  706. (HeGbl.CurFlag & FC_NIBBLE ? 0 : 1);
  707. }
  708. HeGbl.CursorPos.Y = lin + TOPLINE + HeGbl.TopLine;
  709. HeGbl.CursorPos.X = col;
  710. }
  711. heUpdateAllLines ()
  712. {
  713. struct Buffer *next, *pBuf;
  714. USHORT line, u;
  715. ULONGLONG loc;
  716. HeGbl.CurBuf = pBuf = NULL;
  717. /*
  718. * Free up any buffers which are before the HeGbl.CurOffset
  719. */
  720. if (!(HeGbl.CurFlag & FC_INFLUSHBUF)) {
  721. while (HeGbl.Buf) {
  722. if (HeGbl.Buf->offset+BUFSZ >= HeGbl.CurOffset)
  723. break;
  724. heFlushBuf (HeGbl.Buf);
  725. /*
  726. * Unlink buffer & put it on the free list
  727. */
  728. next = HeGbl.Buf->next;
  729. HeGbl.Buf->next = vBufFree;
  730. vBufFree = HeGbl.Buf;
  731. HeGbl.Buf = next;
  732. }
  733. }
  734. /*
  735. * Display each hex line now
  736. */
  737. loc = HeGbl.CurOffset; // starting offset
  738. for (line=0; line<HeGbl.Lines; line++) { // for each line
  739. if (pBuf == NULL) { // do we have the buffer?
  740. pBuf = heGetBuf (loc); // no, go get it
  741. if (pBuf)
  742. u = (USHORT) (loc - pBuf->offset); // calc offset into this buffer
  743. }
  744. if (pBuf) {
  745. heHexLine (pBuf, u, line); // dump this line
  746. loc += LINESZ; // move offsets foreward one line
  747. u += LINESZ;
  748. if (u >= BUFSZ) { // did we exceed the current buf?
  749. pBuf = pBuf->next; // yes, move to next one
  750. u = 0;
  751. if (pBuf && loc < pBuf->offset) // verify buffer is right offs
  752. pBuf = NULL; // no, let heGetBuf find it
  753. }
  754. }
  755. }
  756. // Cause screen to be refreshed
  757. heShowBuf (TOPLINE, HeGbl.Lines);
  758. /*
  759. * All lines have been displayed, free up any extra buffers
  760. * at the end of the chain
  761. */
  762. if (pBuf && !(HeGbl.CurFlag & FC_INFLUSHBUF)) {
  763. next = pBuf->next; // get extra buffers
  764. pBuf->next = NULL; // terminate active list
  765. pBuf = next;
  766. while (pBuf) {
  767. heFlushBuf (pBuf); // flush this buffer
  768. next = pBuf->next; // move it to the free list
  769. // and get next buffer to flush
  770. pBuf->next = vBufFree;
  771. vBufFree = pBuf;
  772. pBuf = next;
  773. }
  774. }
  775. HeGbl.CurFlag &= ~FC_CURCENTER;
  776. return 0;
  777. }
  778. int heFlushBuf (pBuf)
  779. struct Buffer *pBuf;
  780. {
  781. ULONGLONG loc, ploc;
  782. USHORT c;
  783. NTSTATUS status;
  784. if ((pBuf->flag & FB_DIRTY) == 0 ||
  785. memcmp (pBuf->data, pBuf->orig, pBuf->len) == 0)
  786. return (0); // buffer isn't dirty, return
  787. // We may need to call heSetUpdate - setting this bit will
  788. // stop FlushBuf from being recursed.
  789. HeGbl.CurFlag |= FC_INFLUSHBUF;
  790. loc = pBuf->offset;
  791. ploc = pBuf->physloc;
  792. if (HeGbl.Flag & (FHE_VERIFYONCE | FHE_VERIFYALL)) {
  793. heSetUpdate (U_NONE); // make sure screen current
  794. heBox (12, TOPLINE+1, 63, 8);
  795. heDisp (TOPLINE+3, 14, "%HWrite changes to %S?", HeGbl.Parm->ename);
  796. heDisp (TOPLINE+7, 14, "Press '%HY%N'es or '%HN%N'o");
  797. if (HeGbl.Flag & FHE_VERIFYALL) {
  798. if (HeGbl.Flag & FHE_PROMPTSEC) {
  799. heDisp (TOPLINE+4, 14, "Sector %H%D%N has been modifed",(ULONG)(ploc/BUFSZ));
  800. } else {
  801. heDisp (TOPLINE+4, 14, "Location %H%Q%Nh-%H%Q%Nh has been modifed",ploc,ploc+BUFSZ);
  802. }
  803. heDisp (TOPLINE+8, 14, "Press '%HA%N' to save all updates");
  804. }
  805. RefreshDisp ();
  806. c = heGetChar ("YNA"); // wait for key stroke
  807. heSetDisp (); // Get heBox off of screen
  808. heSetUpdate (U_SCREEN); // we will need to update display
  809. if (c == 'N') {
  810. memcpy (pBuf->data, pBuf->orig, pBuf->len);
  811. HeGbl.CurFlag &= ~FC_INFLUSHBUF;
  812. if (HeGbl.Flag & FHE_KICKDIRTY) {
  813. HeGbl.Parm->flag |= FHE_DIRTY;
  814. SetEvent (HeGbl.Parm->Kick);
  815. }
  816. return (0);
  817. }
  818. if (c == 'A')
  819. HeGbl.Flag &= ~FHE_VERIFYALL;
  820. }
  821. if (HeGbl.Parm->write) {
  822. /*
  823. * Write new buffer.
  824. */
  825. do {
  826. status = HeGbl.Parm->write(HeGbl.Parm->handle, loc, pBuf->data,pBuf->len);
  827. if (!status) {
  828. pBuf->flag &= ~FB_DIRTY;
  829. break;
  830. }
  831. } while (heIOErr ("WRITE ERROR!", loc, ploc, status) == 'R');
  832. }
  833. HeGbl.Flag &= ~FHE_VERIFYONCE;
  834. HeGbl.CurFlag &= ~FC_INFLUSHBUF;
  835. return (1);
  836. }
  837. VOID heJumpToLink ()
  838. {
  839. PULONG p;
  840. ULONG l;
  841. if (HeGbl.DisplayMode != D_DWORD || (HeGbl.Flag & FHE_JUMP) == 0)
  842. return;
  843. if (((HeGbl.CurEditLoc & ~3) + 3) > HeGbl.TotLen1)
  844. return;
  845. heSetCursorBuf ();
  846. p = (PULONG) (((ULONG_PTR) HeGbl.CurPT) & ~3); // Round to dword location
  847. l = *p;
  848. if ((l & 3) == 0)
  849. l += 3;
  850. if (l > HeGbl.TotLen1) {
  851. Beep (500, 100);
  852. return;
  853. }
  854. HeGbl.CurFlag |= FC_NIBBLE | FC_CURCENTER;
  855. HeGbl.CurEditLoc = l;
  856. heSetDisp (); // clear & restore orig screen (does not draw)
  857. heSetUpdate (U_SCREEN); // redraw hex area
  858. }
  859. VOID heSearch ()
  860. {
  861. struct Buffer *pBuf;
  862. ULONGLONG j, sec, off, slen, len, upd;
  863. ULONG i;
  864. ULONGLONG iQ;
  865. struct HexEditParm ei;
  866. PUCHAR data, data2;
  867. if (vInSearch || HeGbl.Lines < 25) {
  868. return ;
  869. }
  870. vInSearch = TRUE;
  871. heFlushAllBufs (1); // Before we start flush & free all buffers
  872. heSetUpdate (U_NONE);
  873. memset ((PUCHAR) &ei, 0, sizeof (ei));
  874. ei.ename = "Entering Search";
  875. ei.flag = FHE_EDITMEM | FHE_ENTER;
  876. ei.mem = HeGbl.SearchPattern;
  877. ei.totlen = BUFSZ;
  878. ei.ioalign = 1;
  879. ei.Console = HeGbl.Console;
  880. ei.AttrNorm = HeGbl.AttrNorm;
  881. ei.AttrHigh = HeGbl.AttrHigh;
  882. ei.AttrReverse = HeGbl.AttrReverse;
  883. ei.CursorSize = HeGbl.Parm->CursorSize;
  884. i = 24;
  885. if (HeGbl.Lines < i) {
  886. if (HeGbl.Lines < 12) {
  887. goto abort;
  888. }
  889. i = HeGbl.Lines - 8;
  890. }
  891. ei.TopLine = HeGbl.Lines + TOPLINE - i;
  892. ei.MaxLine = i + 1;
  893. if (HeGbl.DisplayMode == D_DWORD) {
  894. ei.flag |= FHE_DWORD;
  895. }
  896. HexEdit (&ei); // Get search parameters
  897. vInSearch = FALSE;
  898. if (!(ei.flag & FHE_ENTER))
  899. goto abort;
  900. for (i=0, slen=0; i < BUFSZ; i++) { // find last non-zero byte
  901. if (HeGbl.SearchPattern[i]) { // in search patter
  902. slen = i+1;
  903. }
  904. }
  905. if (slen == 0) {
  906. goto abort;
  907. }
  908. heBox (12, TOPLINE+1, 48, 6);
  909. heDisp (TOPLINE+3, 14, "Searching for pattern");
  910. SetCurPos (TOPLINE+5, 24);
  911. RefreshDisp ();
  912. iQ = HeGbl.CurEditLoc + 1;
  913. sec = iQ & SECTORMASK; // current sector
  914. off = iQ - sec; // offset within sector checking
  915. upd = 0;
  916. while (sec < HeGbl.TotLen) {
  917. if (++upd >= 50) {
  918. upd = 0;
  919. heFlushAllBufs (0); // free memory
  920. heDisp (TOPLINE+6, 14, "Searching offset %H%Qh ", sec);
  921. heShowBuf (TOPLINE+6, 1);
  922. }
  923. pBuf = heGetBuf(sec);
  924. if (pBuf) {
  925. data = pBuf->data;
  926. nextoff:
  927. while (off < BUFSZ && data[off] != HeGbl.SearchPattern[0]) {
  928. off++;
  929. }
  930. if (off >= BUFSZ) {
  931. // next sector...
  932. sec += BUFSZ;
  933. off = 0;
  934. continue;
  935. }
  936. len = (off + slen) > BUFSZ ? BUFSZ - off : slen;
  937. for (i=0; i < len; i++) {
  938. if (data[off+i] != HeGbl.SearchPattern[i]) {
  939. off += 1;
  940. goto nextoff;
  941. }
  942. }
  943. if (i < slen) {
  944. // data is continued in next buffer..
  945. if (sec+BUFSZ >= HeGbl.TotLen) {
  946. off += 1;
  947. goto nextoff;
  948. }
  949. data2 = heGetBuf (sec+BUFSZ)->data;
  950. if (data2) {
  951. j = (BUFSZ-off);
  952. len = slen - j;
  953. for (i=0; i < len; i++) {
  954. if (data2[i] != HeGbl.SearchPattern[j+i]) {
  955. off += 1;
  956. goto nextoff;
  957. }
  958. }
  959. }
  960. }
  961. // found match
  962. if (sec + off + slen > HeGbl.TotLen1) {
  963. break;
  964. }
  965. } else {
  966. sec+=off;
  967. }
  968. HeGbl.CurEditLoc = sec + off;
  969. heSetDisp (); // clear & restore orig screen (does not draw)
  970. heSetUpdate (U_SCREEN); // redraw hex area
  971. return ;
  972. }
  973. heBox (12, TOPLINE+1, 48, 6);
  974. heDisp (TOPLINE+3, 14, "Data was not found");
  975. heDisp (TOPLINE+5, 17, "Press %HEnter%N to continue");
  976. SetCurPos (TOPLINE+6, 17);
  977. RefreshDisp ();
  978. heGetChar ("\r");
  979. abort:
  980. heSetDisp (); // clear & restore orig screen (does not draw)
  981. heSetUpdate (U_SCREEN); // redraw hex area
  982. return ;
  983. }
  984. VOID heGotoPosition ()
  985. {
  986. UCHAR s[24];
  987. ULONGLONG l;
  988. heSetUpdate (U_NONE);
  989. heBox (12, TOPLINE+1, 49, 6);
  990. heDisp (TOPLINE+3, 14, "Enter offset from %H%X%N - %H%Q", 0L, HeGbl.TotLen1);
  991. heDisp (TOPLINE+5, 14, "Offset: ");
  992. SetCurPos (TOPLINE+5, 22);
  993. RefreshDisp ();
  994. heGetString (s, 18);
  995. if (s[0]) {
  996. l = heHtoLu (s);
  997. if (l <= HeGbl.TotLen1) {
  998. HeGbl.CurFlag |= FC_NIBBLE;
  999. HeGbl.CurEditLoc = l;
  1000. }
  1001. }
  1002. if (!(HeGbl.CurFlag & FC_TEXT) && !(HeGbl.CurEditLoc & HeGbl.DisplayMode)) {
  1003. // On xword boundry and not in text mode, adjust so cursor
  1004. // is on the first byte which is being displayed of this
  1005. // xword
  1006. HeGbl.CurEditLoc += HeGbl.DisplayMode;
  1007. if (HeGbl.CurEditLoc > HeGbl.TotLen1)
  1008. HeGbl.CurEditLoc = HeGbl.TotLen1;
  1009. }
  1010. HeGbl.CurFlag |= FC_CURCENTER; // set cursor to center in window moves
  1011. heSetDisp (); // clear & restore orig screen (does not draw)
  1012. heSetUpdate (U_SCREEN); // redraw hex area
  1013. }
  1014. VOID heGetString (PUCHAR s, USHORT len)
  1015. {
  1016. UCHAR i[50];
  1017. DWORD cb;
  1018. if (!ReadFile( HeGbl.StdIn, i, 50, &cb, NULL ))
  1019. return;
  1020. if(cb >= 2 && (i[cb - 2] == 0x0d || i[cb - 2] == 0x0a) ) {
  1021. i[cb - 2] = 0; // Get rid of CR LF
  1022. }
  1023. i[ cb - 1] = 0;
  1024. memcpy (s, i, len);
  1025. s[len] = 0;
  1026. }
  1027. /***
  1028. * heCopyOut - Copies data to output filename
  1029. */
  1030. VOID heCopyOut ()
  1031. {
  1032. UCHAR s[64];
  1033. ULONGLONG len, rem, upd;
  1034. ULONG u;
  1035. HANDLE h;
  1036. NTSTATUS status;
  1037. struct Buffer *pB;
  1038. heFlushAllBufs (1); // Before we start flush & free all buffers
  1039. heSetUpdate (U_NONE);
  1040. heBox (12, TOPLINE+1, 48, 6);
  1041. heDisp (TOPLINE+3, 14, "Copy stream to filename (%H%D%Q Bytes)", HeGbl.TotLen);
  1042. heDisp (TOPLINE+5, 14, "Filename: ");
  1043. SetCurPos (TOPLINE+5, 24);
  1044. RefreshDisp ();
  1045. heGetString (s, 59);
  1046. if (s[0] == 0)
  1047. return;
  1048. status = heOpenFile (s, &h, GENERIC_WRITE);
  1049. if (NT_SUCCESS(status)) {
  1050. len = upd = 0;
  1051. rem = HeGbl.TotLen;
  1052. while (NT_SUCCESS(status) && rem){
  1053. if (upd++ > 50) {
  1054. upd = 0;
  1055. heFlushAllBufs (0); // free memory
  1056. heDisp (TOPLINE+6, 14, "Bytes written %H%Q ", len);
  1057. heShowBuf (TOPLINE+6, 1);
  1058. RefreshDisp ();
  1059. }
  1060. u = rem > BUFSZ ? BUFSZ : (ULONG)rem;
  1061. pB = heGetBuf (len);
  1062. if (pB) {
  1063. status = heWriteFile (h, pB->data, u);
  1064. rem -= u;
  1065. len += BUFSZ;
  1066. }
  1067. }
  1068. CloseHandle(h);
  1069. }
  1070. if (!NT_SUCCESS(status)) {
  1071. heBox (15, TOPLINE+1, 33, 6);
  1072. heDisp (TOPLINE+3, 17, "%HCopy failed");
  1073. heDisp (TOPLINE+4, 17, "Error code %X", status);
  1074. heDisp (TOPLINE+5, 17, "Press %HA%N to abort");
  1075. RefreshDisp ();
  1076. heGetChar ("A");
  1077. }
  1078. }
  1079. /***
  1080. * heCopyIn - Copies data to output filename
  1081. */
  1082. VOID
  1083. heCopyIn ()
  1084. {
  1085. UCHAR s[64];
  1086. ULONGLONG holdEditLoc, rem;
  1087. ULONG u, br;
  1088. struct Buffer *pB;
  1089. char *pErr;
  1090. HANDLE h;
  1091. NTSTATUS status;
  1092. heSetUpdate (U_NONE);
  1093. heBox (12, TOPLINE+1, 48, 6);
  1094. heDisp (TOPLINE+3, 14, "Input from filename (%H%D%Q Bytes)", HeGbl.TotLen);
  1095. heDisp (TOPLINE+5, 14, "Filename: ");
  1096. SetCurPos (TOPLINE+5, 24);
  1097. RefreshDisp ();
  1098. heGetString (s, 59);
  1099. heSetDisp (); // Get heBox off of screen
  1100. if (s[0] == 0) {
  1101. return;
  1102. }
  1103. status = heOpenFile (s, &h, GENERIC_READ);
  1104. if (NT_SUCCESS(status)) {
  1105. rem = HeGbl.TotLen;
  1106. holdEditLoc = HeGbl.CurEditLoc;
  1107. HeGbl.CurEditLoc = 0;
  1108. while (NT_SUCCESS(status) && rem) {
  1109. pB = heGetBuf (HeGbl.CurEditLoc);
  1110. if (pB) {
  1111. u = rem > BUFSZ ? BUFSZ : (ULONG)rem;
  1112. status = heReadFile (h, pB->data, u, &br);
  1113. if (memcmp (pB->data, pB->orig, pB->len)) {
  1114. pB->flag |= FB_DIRTY; // it's changed
  1115. HeGbl.CurFlag |= FC_CURCENTER;
  1116. heSetUpdate (U_SCREEN);
  1117. heSetUpdate (U_NONE); // Update screen
  1118. if (HeGbl.Flag & FHE_KICKDIRTY) {
  1119. HeGbl.Parm->flag |= FHE_DIRTY;
  1120. }
  1121. }
  1122. heFlushAllBufs (1);
  1123. if (NT_SUCCESS(status) && br != u) {
  1124. pErr = "Smaller then data";
  1125. }
  1126. rem -= u;
  1127. HeGbl.CurEditLoc += BUFSZ;
  1128. }
  1129. }
  1130. if (NT_SUCCESS(status)) {
  1131. heReadFile (h, s, 1, &br);
  1132. if (br) // then what we are editting
  1133. pErr = "Larger then data";
  1134. }
  1135. CloseHandle(h);
  1136. }
  1137. if (!NT_SUCCESS(status) || pErr) {
  1138. heBox (15, TOPLINE+1, 33, 6);
  1139. if (pErr) {
  1140. heDisp (TOPLINE+3, 17, "Import file is:");
  1141. heDisp (TOPLINE+4, 17, pErr);
  1142. heDisp (TOPLINE+5, 17, "Press %HC%N to continue");
  1143. } else {
  1144. heDisp (TOPLINE+3, 17, "%HImport failed");
  1145. heDisp (TOPLINE+4, 17, "Error code %X", status);
  1146. heDisp (TOPLINE+5, 17, "Press %HA%N to abort");
  1147. }
  1148. RefreshDisp ();
  1149. heGetChar ("CA");
  1150. }
  1151. HeGbl.CurEditLoc = holdEditLoc;
  1152. }
  1153. VOID
  1154. heFlushAllBufs (USHORT update)
  1155. {
  1156. struct Buffer *next;
  1157. USHORT rc;
  1158. for (; ;) {
  1159. rc = 0;
  1160. while (HeGbl.Buf) {
  1161. rc |= heFlushBuf (HeGbl.Buf);
  1162. next = HeGbl.Buf->next;
  1163. HeGbl.Buf->next = vBufFree;
  1164. vBufFree = HeGbl.Buf;
  1165. HeGbl.Buf = next;
  1166. }
  1167. if (!rc) // If something was flushed,
  1168. break; // then update the screen
  1169. if (update) {
  1170. heSetUpdate (U_SCREEN);
  1171. heSetUpdate (U_NONE);
  1172. }
  1173. } // and loop to free buffers (again)
  1174. }
  1175. VOID heBox (x, y, len_x, len_y)
  1176. USHORT x, y, len_x, len_y;
  1177. {
  1178. CHAR_INFO blank[CELLPERLINE];
  1179. PCHAR_INFO pt, pt1;
  1180. USHORT c, lc;
  1181. pt = blank;
  1182. for (c=len_x; c; c--) { /* Construct blank line */
  1183. PUTCHAR (pt, ' ', HeGbl.AttrNorm); /* with background color*/
  1184. }
  1185. blank[0].Char.AsciiChar = blank[lc=len_x-1].Char.AsciiChar = '';
  1186. for (c=0; c <= len_y; c++) /* blank each line */
  1187. memcpy (POS(c+y,x), blank, (int)((pt - blank) * sizeof (CHAR_INFO)));
  1188. pt = POS(y,x);
  1189. pt1 = POS(y+len_y, x);
  1190. for (c=0; c < len_x; c++) /* Draw horz lines */
  1191. pt[c].Char.AsciiChar = pt1[c].Char.AsciiChar = '';
  1192. pt [ 0].Char.AsciiChar = ''; /* Put corners on */
  1193. pt [lc].Char.AsciiChar = '';
  1194. pt1 [ 0].Char.AsciiChar = '';
  1195. pt1 [lc].Char.AsciiChar = '';
  1196. }
  1197. VOID heUndo ()
  1198. {
  1199. struct Buffer *pBuf;
  1200. USHORT flag;
  1201. flag = 0;
  1202. for (pBuf=HeGbl.Buf; pBuf; pBuf = pBuf->next)
  1203. if (pBuf->flag & FB_DIRTY) {
  1204. flag = 1;
  1205. pBuf->flag &= ~FB_DIRTY;
  1206. memcpy (pBuf->data, pBuf->orig, pBuf->len);
  1207. }
  1208. if (flag) {
  1209. heSetUpdate (U_SCREEN);
  1210. if (HeGbl.Flag & FHE_KICKDIRTY) {
  1211. HeGbl.Parm->flag |= FHE_DIRTY;
  1212. SetEvent (HeGbl.Parm->Kick);
  1213. }
  1214. }
  1215. }
  1216. void heHexLine (pBuf, u, line)
  1217. struct Buffer *pBuf;
  1218. USHORT u, line;
  1219. {
  1220. PCHAR_INFO pt, hex, asc;
  1221. UCHAR *data, *orig;
  1222. UCHAR len, mlen, c, d, i, j;
  1223. WORD a;
  1224. ULONGLONG l;
  1225. WORD AttrNorm = HeGbl.AttrNorm;
  1226. data = pBuf->data + u;
  1227. orig = pBuf->orig + u;
  1228. pt = HeGbl.pVioBuf + (line+TOPLINE) * CELLPERLINE;
  1229. hex = pt + HEXINDENT;
  1230. asc = pt + HeGbl.CurAscIndent;
  1231. //
  1232. // Write the file index. Highlight words falling on buffer (sector)
  1233. // boundries in white.
  1234. //
  1235. l = pBuf->offset + u;
  1236. if (l & ((ULONGLONG) BUFSZ-1)) {
  1237. heHexQWord (pt+LINEINDENT, pBuf->physloc + u, AttrNorm);
  1238. } else {
  1239. heHexQWord (pt+LINEINDENT, pBuf->physloc + u, HeGbl.AttrHigh);
  1240. }
  1241. if (pBuf->flag & FB_BAD) { // If read error on
  1242. pt[LINEINDENT+FILEINDEXWIDTH].Char.AsciiChar = 'E'; // this sector, then
  1243. pt[LINEINDENT+FILEINDEXWIDTH].Attributes = HeGbl.AttrHigh; // flag it
  1244. } else
  1245. pt[LINEINDENT+FILEINDEXWIDTH].Char.AsciiChar = ' ';
  1246. if (l + LINESZ > HeGbl.TotLen) { // if EOF
  1247. if (l >= HeGbl.TotLen) { // Totally blankline?
  1248. PUTCHAR (asc, ' ', AttrNorm);
  1249. PUTCHAR (asc, ' ', AttrNorm);
  1250. mlen = 0;
  1251. for (len=0; len < 9; len++)
  1252. pt[len].Char.AsciiChar = ' ';
  1253. goto blankline;
  1254. }
  1255. len = mlen = (UCHAR) (HeGbl.TotLen - l); // Clip line
  1256. } else
  1257. len = mlen = (UCHAR) LINESZ; // Full line
  1258. PUTCHAR (asc, '*', AttrNorm);
  1259. switch (HeGbl.DisplayMode) {
  1260. case D_BYTE:
  1261. while (len--) {
  1262. c = *(data++);
  1263. a = c == *(orig++) ? AttrNorm : HeGbl.AttrReverse;
  1264. PUTCHAR (hex, rghexc [c >> 4], a);
  1265. PUTCHAR (hex, rghexc [c & 0x0F], a);
  1266. hex++;
  1267. PUTCHAR (asc, (c < ' ' || c > '~') ? '.' : c, a);
  1268. }
  1269. pt[((LINESZ/2)*3+HEXINDENT)-1].Char.AsciiChar = '-';
  1270. break;
  1271. default:
  1272. hex--;
  1273. i = HeGbl.DWidth;
  1274. j = i >> 1;
  1275. while (len) {
  1276. hex += i;
  1277. for (d=0; d<j; d++) {
  1278. if (len) {
  1279. len--;
  1280. c = *(data++);
  1281. a = c == *(orig++) ? AttrNorm : HeGbl.AttrReverse;
  1282. hex->Attributes = a;
  1283. hex->Char.AsciiChar = rghexc[c & 0x0F];
  1284. hex--;
  1285. hex->Attributes = a;
  1286. hex->Char.AsciiChar = rghexc[c >> 4];
  1287. hex--;
  1288. PUTCHAR (asc, (c < ' ' || c > '~') ? '.' : c, a);
  1289. } else {
  1290. hex->Attributes = AttrNorm;
  1291. hex->Char.AsciiChar = '?';
  1292. hex--;
  1293. hex->Attributes = AttrNorm;
  1294. hex->Char.AsciiChar = '?';
  1295. hex--;
  1296. }
  1297. }
  1298. hex += i + 1;
  1299. }
  1300. break;
  1301. }
  1302. PUTCHAR (asc, '*', AttrNorm);
  1303. blankline:
  1304. while (mlen++ < LINESZ)
  1305. PUTCHAR (asc, ' ', AttrNorm);
  1306. asc = pt + HeGbl.CurAscIndent;
  1307. while (hex < asc)
  1308. PUTCHAR (hex, ' ', AttrNorm);
  1309. }
  1310. heInitScr ()
  1311. {
  1312. CONSOLE_SCREEN_BUFFER_INFO Mode;
  1313. CONSOLE_CURSOR_INFO CursorInfo;
  1314. USHORT li;
  1315. GetConsoleScreenBufferInfo(HeGbl.Console, &Mode);
  1316. if (HeGbl.Parm->MaxLine) {
  1317. HeGbl.TopLine = (USHORT)HeGbl.Parm->TopLine;
  1318. li = (USHORT)HeGbl.Parm->MaxLine; // +1; adjust for no fnc key line
  1319. } else {
  1320. li = Mode.srWindow.Bottom - Mode.srWindow.Top + 1;
  1321. if (li < 10)
  1322. li = 10;
  1323. Mode.dwSize.Y = li;
  1324. }
  1325. if (Mode.dwSize.X < CELLPERLINE)
  1326. Mode.dwSize.X = CELLPERLINE;
  1327. if (!SetConsoleScreenBufferSize(HeGbl.Console, Mode.dwSize)) {
  1328. Mode.srWindow.Bottom -= Mode.srWindow.Top;
  1329. Mode.srWindow.Right -= Mode.srWindow.Left;
  1330. Mode.srWindow.Top = 0;
  1331. Mode.srWindow.Left = 0;
  1332. SetConsoleWindowInfo(HeGbl.Console, TRUE, &Mode.srWindow);
  1333. SetConsoleScreenBufferSize(HeGbl.Console, Mode.dwSize);
  1334. }
  1335. HeGbl.Lines = li - TOPLINE - 1;
  1336. HeGbl.PageSz = HeGbl.Lines * LINESZ;
  1337. HeGbl.LineTot = li;
  1338. if (HeGbl.pVioBuf)
  1339. GlobalFree (HeGbl.pVioBuf);
  1340. HeGbl.pVioBuf = (PCHAR_INFO) GlobalAlloc (0,
  1341. (HeGbl.LineTot+1)*CELLPERLINE*sizeof(CHAR_INFO));
  1342. if (!HeGbl.pVioBuf) {
  1343. return 1;
  1344. }
  1345. HeGbl.dwVioBufSize.X = CELLPERLINE;
  1346. HeGbl.dwVioBufSize.Y = HeGbl.LineTot + 1;
  1347. GetConsoleCursorInfo (HeGbl.Console, &CursorInfo);
  1348. CursorInfo.bVisible = TRUE;
  1349. CursorInfo.dwSize = (ULONG) HeGbl.Parm->CursorSize ? HeGbl.Parm->CursorSize : 100;
  1350. SetConsoleCursorInfo (HeGbl.Console, &CursorInfo);
  1351. return heSetDisp ();
  1352. }
  1353. int heInitConsole ()
  1354. {
  1355. CONSOLE_SCREEN_BUFFER_INFO screenMode;
  1356. DWORD mode = 0;
  1357. HeGbl.StdIn = GetStdHandle (STD_INPUT_HANDLE);
  1358. GetConsoleMode (HeGbl.StdIn, &mode);
  1359. HeGbl.OrigMode = mode;
  1360. SetConsoleMode (HeGbl.StdIn, mode | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
  1361. ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT );
  1362. if (HeGbl.Flag & FHE_SAVESCRN) {
  1363. HeGbl.Console = CreateConsoleScreenBuffer(
  1364. GENERIC_WRITE | GENERIC_READ,
  1365. FILE_SHARE_WRITE | FILE_SHARE_READ,
  1366. NULL,
  1367. CONSOLE_TEXTMODE_BUFFER,
  1368. NULL );
  1369. SetConsoleActiveScreenBuffer (HeGbl.Console);
  1370. } else {
  1371. HeGbl.Console = HeGbl.Parm->Console;
  1372. if (HeGbl.Console == INVALID_HANDLE_VALUE)
  1373. HeGbl.Console = GetStdHandle( STD_OUTPUT_HANDLE );
  1374. GetConsoleScreenBufferInfo(HeGbl.Console, &screenMode);
  1375. HeGbl.dwSize = screenMode.dwSize;
  1376. }
  1377. GetConsoleCursorInfo(HeGbl.Console, &HeGbl.CursorInfo);
  1378. return 0;
  1379. }
  1380. VOID heEndConsole ()
  1381. {
  1382. CONSOLE_SCREEN_BUFFER_INFO Mode;
  1383. PCHAR_INFO pt;
  1384. ULONG u;
  1385. SetConsoleMode (HeGbl.StdIn, HeGbl.OrigMode);
  1386. if (HeGbl.Flag & FHE_SAVESCRN) {
  1387. CloseHandle (HeGbl.Console);
  1388. if (HeGbl.Parm->Console == INVALID_HANDLE_VALUE)
  1389. SetConsoleActiveScreenBuffer (GetStdHandle(STD_OUTPUT_HANDLE));
  1390. else SetConsoleActiveScreenBuffer (HeGbl.Parm->Console);
  1391. } else {
  1392. if (!SetConsoleScreenBufferSize(HeGbl.Console, HeGbl.dwSize)) {
  1393. GetConsoleScreenBufferInfo(HeGbl.Console, &Mode);
  1394. Mode.srWindow.Bottom -= Mode.srWindow.Top;
  1395. Mode.srWindow.Right -= Mode.srWindow.Left;
  1396. Mode.srWindow.Top = 0;
  1397. Mode.srWindow.Left = 0;
  1398. SetConsoleWindowInfo(HeGbl.Console, TRUE, &Mode.srWindow);
  1399. SetConsoleScreenBufferSize(HeGbl.Console, HeGbl.dwSize);
  1400. }
  1401. if (HeGbl.LineTot <= HeGbl.dwSize.Y) {
  1402. HeGbl.dwSize.Y--;
  1403. pt = POS(HeGbl.LineTot - 1,0);
  1404. for (u=HeGbl.dwSize.X; u; u--) {
  1405. PUTCHAR (pt, ' ', HeGbl.AttrNorm);
  1406. }
  1407. heShowBuf (HeGbl.LineTot - 1, 1);
  1408. }
  1409. HeGbl.dwSize.X = 0;
  1410. SetConsoleCursorPosition (HeGbl.Console, HeGbl.dwSize);
  1411. SetConsoleCursorInfo (HeGbl.Console, &HeGbl.CursorInfo);
  1412. }
  1413. if (HeGbl.pVioBuf) {
  1414. GlobalFree (HeGbl.pVioBuf);
  1415. HeGbl.pVioBuf = NULL;
  1416. }
  1417. }
  1418. heRefresh ()
  1419. {
  1420. RefreshDisp ();
  1421. if (HeGbl.Flag & FHE_KICKDIRTY) {
  1422. HeGbl.Parm->flag |= FHE_DIRTY;
  1423. SetEvent (HeGbl.Parm->Kick);
  1424. }
  1425. return 0;
  1426. }
  1427. int heSetDisp ()
  1428. {
  1429. PCHAR_INFO pt, pt1;
  1430. USHORT u;
  1431. pt = POS(0,0);
  1432. for (u=HeGbl.LineTot * CELLPERLINE; u; u--) {
  1433. PUTCHAR (pt, ' ', HeGbl.AttrNorm);
  1434. }
  1435. heDisp (1, 5, "Edit: %H%S", HeGbl.Parm->ename);
  1436. heDisp (2, 5, "Size: %Q ", HeGbl.TotLen);
  1437. if (HeGbl.TotLen < 0x100000000) {
  1438. heDisp (2, 28, "(%D)", (ULONG)HeGbl.TotLen);
  1439. }
  1440. heDisp (1, 40, "Position:");
  1441. for (pt1=POS(1,50), u=0; u<30; u++, pt1++)
  1442. pt1->Attributes = HeGbl.AttrHigh;
  1443. //if (HeGbl.Parm->MaxLine == 0) {
  1444. u = HeGbl.LineTot - 1;
  1445. heDisp (u, 0, "%HF1%N:Toggle");
  1446. heDisp (u,11, "%HF2%N:Goto");
  1447. if (!vInSearch) {
  1448. heDisp (u,20, "%HF3%N:Search");
  1449. }
  1450. heDisp (u,31, "%HF4%N:Export");
  1451. heDisp (u,42, "%HF5%N:Import");
  1452. if (HeGbl.DisplayMode == D_DWORD && (HeGbl.Flag & FHE_JUMP) != 0)
  1453. heDisp (u,53, "%HF6%N:Jump");
  1454. else heDisp (u,53, " ");
  1455. heDisp (u,66, "%HF10%N:Undo");
  1456. //if (HeGbl.Flag & FHE_F6)
  1457. // heDisp (u,51, "%HF6%N:PSec");
  1458. //}
  1459. return 0;
  1460. }
  1461. int heUpdateFncs ()
  1462. {
  1463. heShowBuf (HeGbl.LineTot - 1, 1);
  1464. return 0;
  1465. }
  1466. int heUpdateStats ()
  1467. {
  1468. COORD dwBufferCoord;
  1469. SMALL_RECT lpWriteRegion;
  1470. heHexQWord (POS(1, 50), HeGbl.CurEditLoc, HeGbl.AttrHigh);
  1471. if (HeGbl.TotLen < 0x100000000) {
  1472. heLtoa( POS(2, 50), (ULONG)HeGbl.CurEditLoc);
  1473. }
  1474. dwBufferCoord.X = 50;
  1475. dwBufferCoord.Y = 1;
  1476. lpWriteRegion.Left = 50;
  1477. lpWriteRegion.Top = HeGbl.TopLine + 1;
  1478. lpWriteRegion.Right = 74;
  1479. lpWriteRegion.Bottom = HeGbl.TopLine + 2;
  1480. WriteConsoleOutputA (
  1481. HeGbl.Console,
  1482. HeGbl.pVioBuf,
  1483. HeGbl.dwVioBufSize, // size of VioBuf
  1484. dwBufferCoord, // location in VioBuf to write
  1485. &lpWriteRegion // location to write on display
  1486. );
  1487. SetConsoleCursorPosition (HeGbl.Console, HeGbl.CursorPos); // redisplay cursor
  1488. return 0;
  1489. }
  1490. VOID heShowBuf (ULONG StartingLine, ULONG NoLines)
  1491. {
  1492. COORD dwBufferCoord;
  1493. SMALL_RECT lpWriteRegion;
  1494. dwBufferCoord.X = (SHORT)0;
  1495. dwBufferCoord.Y = (SHORT)StartingLine;
  1496. StartingLine += HeGbl.TopLine;
  1497. lpWriteRegion.Left = (SHORT)0;
  1498. lpWriteRegion.Top = (SHORT)StartingLine;
  1499. lpWriteRegion.Right = (SHORT)(CELLPERLINE-1);
  1500. lpWriteRegion.Bottom = (SHORT)(StartingLine+NoLines-1);
  1501. WriteConsoleOutputA (
  1502. HeGbl.Console,
  1503. HeGbl.pVioBuf,
  1504. HeGbl.dwVioBufSize, // size of VioBuf
  1505. dwBufferCoord, // location in VioBuf to write
  1506. &lpWriteRegion // location to write on display
  1507. );
  1508. }
  1509. struct Buffer *heGetBuf (ULONGLONG loc)
  1510. {
  1511. struct Buffer **ppBuf, *pBuf;
  1512. USHORT len;
  1513. NTSTATUS status;
  1514. loc &= SECTORMASK;
  1515. ppBuf = &HeGbl.Buf;
  1516. while (pBuf = *ppBuf) {
  1517. if (pBuf->offset >= loc) {
  1518. if (pBuf->offset == loc) // buffer the correct offset?
  1519. return pBuf; // yup - all done
  1520. break; // it's not here
  1521. }
  1522. ppBuf = &pBuf->next; // try the next one
  1523. }
  1524. /*
  1525. * buffer was not in list - it should be insterted before ppBuf
  1526. */
  1527. if (vBufFree) {
  1528. pBuf = vBufFree;
  1529. vBufFree = vBufFree->next;
  1530. } else {
  1531. pBuf = (struct Buffer *)
  1532. GlobalAlloc (0, sizeof(struct Buffer)+2*BUFSZ);
  1533. if (!pBuf) {
  1534. return NULL;
  1535. }
  1536. }
  1537. pBuf->data = (PUCHAR)(((ULONG_PTR)pBuf+sizeof(struct Buffer)+BUFSZ));
  1538. pBuf->offset = loc;
  1539. pBuf->physloc= loc; // Assume physloc is logical offset
  1540. pBuf->flag = 0;
  1541. // Link this buffer in now! In case we recurse (due to read-error)
  1542. pBuf->next = *ppBuf; // link in this new buffer
  1543. *ppBuf = pBuf;
  1544. if (loc + BUFSZ > HeGbl.TotLen) { // are we going to hit the EOF?
  1545. if (loc >= HeGbl.TotLen) { // is buffer completely passed EOF?
  1546. pBuf->len = 0;
  1547. goto nodata; // yes, then no data at all
  1548. }
  1549. len = (USHORT) (HeGbl.TotLen - loc); // else, clip to EOF
  1550. } else len = BUFSZ; // not pass eof, get a full buffer
  1551. pBuf->len = len;
  1552. if (HeGbl.Flag & FHE_EDITMEM) // Direct memory edit?
  1553. pBuf->data = HeGbl.Parm->mem + loc; // memory location of buffer
  1554. if (HeGbl.Read) {
  1555. /*
  1556. * Read buffer from file
  1557. */
  1558. status = HeGbl.Read (HeGbl.Parm->handle, loc, pBuf->data, len);
  1559. if (status) {
  1560. // If read error, we will always retry once. Also clear buffer
  1561. // before retry in case read retreives some info
  1562. for (; ;) {
  1563. memset (pBuf->data, 0, len); // Clear read area
  1564. memset (pBuf->orig,0xff, len); // good effect
  1565. status = HeGbl.Read (HeGbl.Parm->handle, loc, pBuf->data, len);
  1566. if (!status)
  1567. break;
  1568. if (heIOErr ("READ ERROR!", loc, pBuf->physloc, status) == 'I') {
  1569. pBuf->flag |= FB_BAD;
  1570. break;
  1571. }
  1572. }
  1573. }
  1574. }
  1575. memcpy (pBuf->orig, pBuf->data, len); // make a copy of the data
  1576. nodata:
  1577. return pBuf;
  1578. }
  1579. USHORT heIOErr (UCHAR *str, ULONGLONG loc, ULONGLONG ploc, ULONG errcd)
  1580. {
  1581. USHORT c;
  1582. if (errcd == 0xFFFFFFFF)
  1583. return 'I';
  1584. heSetUpdate (U_NONE);
  1585. heBox (12, TOPLINE+1, 55, 8);
  1586. heDisp (TOPLINE+3, 14, str);
  1587. heDisp (TOPLINE+4, 14, "Error code %H%D%N, Offset %Qh, Sector %D",
  1588. errcd, loc, (ULONG)(ploc / BUFSZ));
  1589. heDisp (TOPLINE+7, 14, "Press '%HR%N' to retry IO, or '%HI%N' to ignore");
  1590. RefreshDisp ();
  1591. c = heGetChar ("RI");
  1592. heSetDisp (); // Get heBox off of screen
  1593. heSetUpdate (U_SCREEN);
  1594. return c;
  1595. }
  1596. UCHAR heGetChar (keys)
  1597. PUCHAR keys;
  1598. {
  1599. INPUT_RECORD Kd;
  1600. DWORD cEvents;
  1601. UCHAR *pt;
  1602. for (; ;) {
  1603. Beep (500, 100);
  1604. for (; ;) {
  1605. ReadConsoleInput (HeGbl.StdIn, &Kd, 1, &cEvents);
  1606. if (Kd.EventType != KEY_EVENT)
  1607. continue; // Not a key
  1608. if (!Kd.Event.KeyEvent.bKeyDown)
  1609. continue; // Not a down stroke
  1610. if (Kd.Event.KeyEvent.wVirtualKeyCode == 0 || // ALT
  1611. Kd.Event.KeyEvent.wVirtualKeyCode == 0x10 || // SHIFT
  1612. Kd.Event.KeyEvent.wVirtualKeyCode == 0x11 || // CONTROL
  1613. Kd.Event.KeyEvent.wVirtualKeyCode == 0x14) // CAPITAL
  1614. continue;
  1615. break;
  1616. }
  1617. if (Kd.Event.KeyEvent.wVirtualKeyCode >= 'a' &&
  1618. Kd.Event.KeyEvent.wVirtualKeyCode <= 'z')
  1619. Kd.Event.KeyEvent.wVirtualKeyCode -= ('a' - 'A');
  1620. for (pt=keys; *pt; pt++) // Is this a key we are
  1621. if (Kd.Event.KeyEvent.wVirtualKeyCode == *pt)
  1622. return *pt; // looking for?
  1623. }
  1624. }
  1625. VOID __cdecl
  1626. heDisp (USHORT line, USHORT col, PUCHAR pIn, ...)
  1627. {
  1628. register char c;
  1629. PCHAR_INFO pOut;
  1630. WORD attr;
  1631. USHORT u;
  1632. UCHAR *pt;
  1633. va_list args;
  1634. attr = HeGbl.AttrNorm;
  1635. pOut = POS(line,col);
  1636. va_start(args,pIn);
  1637. while (c = *(pIn++)) {
  1638. if (c != '%') {
  1639. PUTCHAR (pOut, c, attr);
  1640. continue;
  1641. }
  1642. switch (*(pIn++)) {
  1643. case 'S':
  1644. pt = va_arg(args, CHAR *);
  1645. while (*pt) {
  1646. PUTCHAR (pOut, *(pt++), attr);
  1647. }
  1648. break;
  1649. case 'X': /* Long HEX, fixed len */
  1650. heHexDWord (pOut, va_arg(args, ULONG), attr);
  1651. pOut += 8;
  1652. break;
  1653. case 'Q': /* LongLong HEX, fixed len */
  1654. heHexQWord (pOut, va_arg(args, ULONGLONG), attr);
  1655. pOut += 16;
  1656. break;
  1657. case 'D': /* Long dec, varible len */
  1658. u = heLtoa (pOut, va_arg(args, ULONG));
  1659. while (u--) {
  1660. pOut->Attributes = attr;
  1661. pOut++;
  1662. }
  1663. break;
  1664. case 'H':
  1665. attr = HeGbl.AttrHigh;
  1666. break;
  1667. case 'N':
  1668. attr = HeGbl.AttrNorm;
  1669. break;
  1670. }
  1671. }
  1672. }
  1673. void heHexDWord (s, l, attr)
  1674. PCHAR_INFO s;
  1675. ULONG l;
  1676. WORD attr;
  1677. {
  1678. UCHAR d, c;
  1679. UCHAR *pt;
  1680. s += 8-1;
  1681. pt = (UCHAR *) &l;
  1682. for (d=0; d<4; d++) {
  1683. c = *(pt++);
  1684. s->Attributes = attr;
  1685. s->Char.AsciiChar = rghexc[c & 0x0F];
  1686. s--;
  1687. s->Attributes = attr;
  1688. s->Char.AsciiChar = rghexc[c >> 4];
  1689. s--;
  1690. }
  1691. }
  1692. void heHexQWord (s, l, attr)
  1693. PCHAR_INFO s;
  1694. ULONGLONG l;
  1695. WORD attr;
  1696. {
  1697. UCHAR d, c;
  1698. UCHAR *pt;
  1699. s += 16-1;
  1700. pt = (UCHAR *) &l;
  1701. for (d=0; d<8; d++) {
  1702. c = *(pt++);
  1703. s->Attributes = attr;
  1704. s->Char.AsciiChar = rghexc[c & 0x0F];
  1705. s--;
  1706. s->Attributes = attr;
  1707. s->Char.AsciiChar = rghexc[c >> 4];
  1708. s--;
  1709. }
  1710. }
  1711. USHORT heLtoa (s, l)
  1712. PCHAR_INFO s;
  1713. ULONG l;
  1714. {
  1715. static ULONG mask[] = { 0L,
  1716. 1L,
  1717. 10L,
  1718. 100L,
  1719. 1000L,
  1720. 10000L,
  1721. 100000L,
  1722. 1000000L,
  1723. 10000000L,
  1724. 100000000L,
  1725. 1000000000L,
  1726. };
  1727. static UCHAR comm[] = "xxxx,xx,xx,xx,xx";
  1728. PCHAR_INFO os;
  1729. UCHAR c;
  1730. USHORT i, j;
  1731. ULONG m;
  1732. if (l < 1000000000L) {
  1733. for (i=1; mask[i] <= l; i++) ;
  1734. if (l == 0L) // Make Zeros
  1735. i++;
  1736. } else
  1737. i = 11;
  1738. os = s;
  1739. j = i;
  1740. while (m = mask[--i]) {
  1741. c = (UCHAR) ((ULONG) l / m);
  1742. l -= m * c;
  1743. s->Char.AsciiChar = c + '0';
  1744. s->Attributes = HeGbl.AttrNorm;
  1745. if (comm[i] == ',') {
  1746. s++;
  1747. s->Attributes = HeGbl.AttrNorm;
  1748. s->Char.AsciiChar = ',';
  1749. }
  1750. s++;
  1751. }
  1752. i = (USHORT)(s - os); // remember how long the number was
  1753. while (j++ < 11) { /* Clear off some blank space after */
  1754. s->Char.AsciiChar = ' '; /* the number. */
  1755. s++;
  1756. }
  1757. return i;
  1758. }
  1759. ULONG heHtou (s)
  1760. UCHAR *s;
  1761. {
  1762. UCHAR c;
  1763. ULONG l;
  1764. l = 0;
  1765. for (; ;) {
  1766. c = *(s++);
  1767. if (c == 's' || c == 'S') { // Sector multiplier?
  1768. l = l * (ULONG)BUFSZ;
  1769. break;
  1770. }
  1771. if (c >= 'a') c -= 'a' - 10;
  1772. else if (c >= 'A') c -= 'A' - 10;
  1773. else c -= '0';
  1774. if (c > 15)
  1775. break;
  1776. l = (l<<4) + c;
  1777. }
  1778. return l;
  1779. }
  1780. ULONGLONG heHtoLu (s)
  1781. UCHAR *s;
  1782. {
  1783. UCHAR c;
  1784. ULONGLONG l;
  1785. l = 0;
  1786. for (; ;) {
  1787. c = *(s++);
  1788. if (c == 's' || c == 'S') { // Sector multiplier?
  1789. l = l * (ULONG)BUFSZ;
  1790. break;
  1791. }
  1792. if (c >= 'a') c -= 'a' - 10;
  1793. else if (c >= 'A') c -= 'A' - 10;
  1794. else c -= '0';
  1795. if (c > 15)
  1796. break;
  1797. l = (l<<4) + c;
  1798. }
  1799. return l;
  1800. }
  1801. NTSTATUS
  1802. heOpenFile (PUCHAR name, PHANDLE fhan, ULONG access)
  1803. {
  1804. *fhan = CreateFile (
  1805. name,
  1806. access,
  1807. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1808. NULL,
  1809. OPEN_EXISTING,
  1810. 0,
  1811. NULL );
  1812. if (*fhan == INVALID_HANDLE_VALUE && (access & GENERIC_WRITE)) {
  1813. *fhan = CreateFile (
  1814. name,
  1815. access,
  1816. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1817. NULL,
  1818. CREATE_NEW,
  1819. 0,
  1820. NULL );
  1821. }
  1822. return *fhan == INVALID_HANDLE_VALUE ? GetLastError() : STATUS_SUCCESS;
  1823. }
  1824. NTSTATUS
  1825. heReadFile (HANDLE h, PUCHAR buffer, ULONG len, PULONG br)
  1826. {
  1827. if (!ReadFile (h, buffer, len, br, NULL))
  1828. return GetLastError();
  1829. return STATUS_SUCCESS;
  1830. }
  1831. NTSTATUS
  1832. heWriteFile (HANDLE h, PUCHAR buffer, ULONG len)
  1833. {
  1834. ULONG bw;
  1835. if (!WriteFile (h, buffer, len, &bw, NULL))
  1836. return GetLastError();
  1837. return (bw != len ? ERROR_WRITE_FAULT : STATUS_SUCCESS);
  1838. }