Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2317 lines
65 KiB

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