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.

718 lines
20 KiB

  1. #include <stdio.h>
  2. #include <malloc.h>
  3. #include <string.h>
  4. #include <memory.h>
  5. #include <windows.h>
  6. #include "list.h"
  7. // ReaderThread - Reads from the file
  8. //
  9. // This thread is woken up by clearing SemReader,
  10. // then vReaderFlag instructs the thread on the course of
  11. // action to take. When displaying gets to close to the end
  12. // of the buffer pool, vReadFlag is set and this thread is
  13. // started.
  14. #if _MSC_FULL_VER >= 13008827
  15. #pragma warning(push)
  16. #pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
  17. #endif
  18. DWORD
  19. ReaderThread (
  20. DWORD dwParameter
  21. )
  22. {
  23. unsigned rc, code, curPri = 0;
  24. UNREFERENCED_PARAMETER(dwParameter);
  25. for (; ;) {
  26. // go into 'boosted' pririoty until we start
  27. // working on 'non-critical' read ahead. (Ie, far away).
  28. if (curPri != vReadPriBoost) {
  29. SetThreadPriority( GetCurrentThread(),
  30. vReadPriBoost );
  31. curPri = vReadPriBoost;
  32. }
  33. WaitForSingleObject(vSemReader, WAITFOREVER);
  34. ResetEvent(vSemReader);
  35. code = vReaderFlag;
  36. for (; ;) {
  37. // Due to this loop, a new command may have arrived
  38. // which takes presidence over the automated command
  39. rc = WaitForSingleObject (vSemReader, DONTWAIT);
  40. if (rc == 0) // New command has arrived
  41. break;
  42. switch (code) {
  43. case F_NEXT: // NEXT FILE
  44. NewFile ();
  45. ReadDirect (vDirOffset);
  46. // Hack... adjust priority to make first screen look
  47. // fast. (Ie, reader thread will have lower priority
  48. // at first; eventhough the display is really close
  49. // to the end of the buffer)
  50. SetThreadPriority( GetCurrentThread(),
  51. vReadPriNormal );
  52. break;
  53. case F_HOME: // HOME of FILE
  54. vTopLine = 0L;
  55. ReadDirect (0L);
  56. break;
  57. case F_DIRECT:
  58. ReadDirect (vDirOffset);
  59. break;
  60. case F_DOWN:
  61. ReadNext ();
  62. break;
  63. case F_UP:
  64. ReadPrev ();
  65. break;
  66. case F_END:
  67. break;
  68. case F_SYNC:
  69. ResetEvent(vSemMoreData);
  70. SetEvent(vSemSync);
  71. WaitForSingleObject(vSemReader, WAITFOREVER);
  72. ResetEvent(vSemReader);
  73. ResetEvent(vSemSync); // Reset trigger for
  74. // Next use.
  75. code = vReaderFlag;
  76. continue; // Execute Syncronized command
  77. case F_CHECK: // No command.
  78. break;
  79. default:
  80. ckdebug (1, "Bad Reader Flag");
  81. }
  82. // Command has been processed.
  83. // Now check to see if read ahead is low, if so set
  84. // command and loop.
  85. if (vpTail->offset - vpCur->offset < vThreshold &&
  86. vpTail->flag != F_EOF) {
  87. code = F_DOWN; // Too close to ending
  88. continue;
  89. }
  90. if (vpCur->offset - vpHead->offset < vThreshold &&
  91. vpHead->offset != vpFlCur->SlimeTOF) {
  92. code = F_UP; // Too close to begining
  93. continue;
  94. }
  95. // Not critical, read ahead logic. The current file
  96. // Normal priority (below display thread) for this
  97. if (curPri != vReadPriNormal) {
  98. SetThreadPriority( GetCurrentThread(),
  99. vReadPriNormal );
  100. curPri = vReadPriNormal;
  101. }
  102. if (vCntBlks == vMaxBlks) // All blks in use for
  103. break; // this one file?
  104. if (vpTail->flag != F_EOF) {
  105. code = F_DOWN;
  106. continue;
  107. }
  108. if (vpHead->offset != vpFlCur->SlimeTOF) {
  109. code = F_UP;
  110. continue;
  111. }
  112. if (vFhandle != 0) { // Must have whole file read in
  113. CloseHandle (vFhandle); // Close the file, and set flag
  114. vFhandle = 0;
  115. if (!(vStatCode & S_INSEARCH)) {
  116. ScrLock (1);
  117. Update_head ();
  118. vDate [ST_MEMORY] = 'M';
  119. dis_str ((Uchar)(vWidth - ST_ADJUST), 0, vDate);
  120. ScrUnLock ();
  121. }
  122. }
  123. break; // Nothing to do. Wait
  124. }
  125. }
  126. return(0);
  127. }
  128. #if _MSC_FULL_VER >= 13008827
  129. #pragma warning(pop)
  130. #endif
  131. // WARNING: Microsoft Confidential!!!
  132. void
  133. NewFile ()
  134. {
  135. char s [60];
  136. char h, c;
  137. SYSTEMTIME SystemTime;
  138. FILETIME LocalFileTime;
  139. long *pLine;
  140. HANDLE TempHandle;
  141. struct Block **pBlk, **pBlkCache;
  142. if (vFhandle)
  143. CloseHandle (vFhandle);
  144. vFType = 0;
  145. vCurOffset = 0L;
  146. // WARNING: Microsoft Confidential!!!
  147. strcpy (s, "Listing ");
  148. strcpy (s+8, vpFname);
  149. // Design change per DougHo.. open files in read-only deny-none mode.
  150. vFhandle = CreateFile( vpFlCur->fname,
  151. GENERIC_READ,
  152. FILE_SHARE_READ|FILE_SHARE_WRITE,
  153. NULL,
  154. OPEN_EXISTING,
  155. 0,
  156. NULL );
  157. if (vFhandle == (HANDLE)(-1)) {
  158. if (vpFlCur->prev == NULL && vpFlCur->next == NULL) {
  159. // Only one file specified?
  160. printf ("Could not open file '%Fs': %s",
  161. (CFP) vpFlCur->fname, GetErrorCode( GetLastError() ));
  162. CleanUp();
  163. ExitProcess(0);
  164. }
  165. vFhandle = 0; // Error. Set externals to "safe"
  166. vFInfo.nFileSizeLow = (unsigned)-1L; // settings. Flag error by setting
  167. vNLine = 1; // file_size = -1
  168. vLastLine = NOLASTLINE;
  169. vDirOffset = vTopLine = 0L;
  170. SetLoffset(0L);
  171. memset (vprgLineTable, 0, sizeof (long *) * MAXTPAGE);
  172. vprgLineTable[0] = (LFP) alloc_page ();
  173. if (!vprgLineTable[0]) {
  174. return;
  175. }
  176. vprgLineTable[0][0] = 0L; // 1st line always starts @ 0
  177. strncpy (vDate, GetErrorCode( GetLastError() ), 20);
  178. vDate[20] = 0;
  179. return ;
  180. }
  181. TempHandle = FindFirstFile( vpFlCur->fname,
  182. &vFInfo );
  183. if( TempHandle == (HANDLE)(-1) ){
  184. ckerr (GetLastError(), "FindFirstFile");
  185. if (!FindClose( TempHandle ))
  186. ckerr (GetLastError(), "FindCloseFile");
  187. }
  188. FileTimeToLocalFileTime( &(vFInfo.ftLastWriteTime), &LocalFileTime );
  189. FileTimeToSystemTime( &LocalFileTime, &SystemTime );
  190. h = (char)SystemTime.wHour;
  191. c = 'a';
  192. if (h >= 12) {
  193. c = 'p'; // pm
  194. if (h > 12) // convert 13-23 --> 1pm-11pm
  195. h -= 12;
  196. }
  197. if (h == 0) // convert 0 --> 12am
  198. h = 12;
  199. sprintf (vDate, "%c%c %c%c%c%c %2d/%02d/%02d %2d:%02d%c",
  200. // File is in memory
  201. // Search is set for mult files
  202. vStatCode & S_MFILE ? '*' : ' ', // File is in memory
  203. vFType & 0x8000 ? 'N' : ' ', // Network
  204. vFInfo.dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? 'R' : ' ', // Readonly
  205. vFInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? 'H' : ' ', // Hidden
  206. vFInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? 'S' : ' ', // System
  207. ' ', // Vio
  208. SystemTime.wMonth,
  209. SystemTime.wDay,
  210. SystemTime.wYear,
  211. h,
  212. SystemTime.wMinute,
  213. c);
  214. pBlkCache = &vpBCache;
  215. if (CompareFileTime( &vFInfo.ftLastWriteTime, &vpFlCur->FileTime ) != 0) {
  216. vpFlCur->NLine = 1L; // Something has changed.
  217. vpFlCur->LastLine = NOLASTLINE; // Scrap the old info, and
  218. vpFlCur->HighTop = -1; // start over
  219. vpFlCur->TopLine = 0L;
  220. vpFlCur->Loffset = vpFlCur->SlimeTOF;
  221. FreePages (vpFlCur);
  222. memset (vpFlCur->prgLineTable, 0, sizeof (long *) * MAXTPAGE);
  223. vpFlCur->FileTime = vFInfo.ftLastWriteTime;
  224. pBlkCache = &vpBFree; // Move blks to free list, not cache list
  225. }
  226. // Restore last known information
  227. vTopLine = vpFlCur->TopLine;
  228. SetLoffset(vpFlCur->Loffset);
  229. vLastLine = vpFlCur->LastLine;
  230. vNLine = vpFlCur->NLine;
  231. vOffTop = 0;
  232. if (vpFlCur->Wrap)
  233. vWrap = vpFlCur->Wrap;
  234. memcpy (vprgLineTable, vpFlCur->prgLineTable, sizeof (long *) * MAXTPAGE);
  235. if (vLastLine == NOLASTLINE) {
  236. pLine = vprgLineTable [vNLine/PLINES] + vNLine % PLINES;
  237. }
  238. if (vprgLineTable[0] == NULL) {
  239. vprgLineTable[0] = (LFP) alloc_page ();
  240. if (!vprgLineTable[0]) {
  241. return;
  242. }
  243. vprgLineTable[0][0] = vpFlCur->SlimeTOF;
  244. }
  245. vDirOffset = vprgLineTable[vTopLine/PLINES][vTopLine%PLINES];
  246. vDirOffset -= vDirOffset % ((long)BLOCKSIZE);
  247. // Adjust buffers..
  248. // Move cur buffers to other list
  249. // Move cache buffers to other list
  250. // Scan other list for cache blks, and move to cache (or free) list
  251. if (vpHead) {
  252. vpTail->next = vpBOther; // move them into the other
  253. vpBOther = vpHead; // list
  254. vpHead = NULL;
  255. }
  256. pBlk = &vpBCache;
  257. while (*pBlk)
  258. MoveBlk (pBlk, &vpBOther) ;
  259. pBlk = &vpBOther;
  260. while (*pBlk) {
  261. if ((*pBlk)->pFile == vpFlCur)
  262. MoveBlk (pBlk, pBlkCache);
  263. else pBlk = &(*pBlk)->next;
  264. }
  265. }
  266. // ReadDirect - Moves to the direct position in the file
  267. //
  268. // First check to see if start of buffers have direct position file,
  269. // if so then do nothing. If not, clear all buffers and start
  270. // reading blocks.
  271. void
  272. ReadDirect (
  273. long offset
  274. )
  275. {
  276. WaitForSingleObject(vSemBrief, WAITFOREVER);
  277. ResetEvent(vSemBrief);
  278. if (vpHead) {
  279. vpTail->next = vpBCache; // move them into the cache
  280. vpBCache = vpHead; // list
  281. }
  282. vpTail = vpHead = vpCur = alloc_block (offset);
  283. vpHead->next = vpTail->prev = NULL;
  284. vCntBlks = 1;
  285. // Freeing is complete, now read in the first block.
  286. // and process lines.
  287. ReadBlock (vpHead, offset);
  288. // maybe it fixes the bug
  289. vpBlockTop = vpHead;
  290. if (GetLoffset() <= vpHead->offset)
  291. add_more_lines (vpHead, NULL);
  292. SetEvent (vSemBrief);
  293. SetEvent (vSemMoreData); // Signal another BLK read
  294. }
  295. // ReadNext - To read further into file
  296. void
  297. ReadNext ()
  298. {
  299. struct Block *pt;
  300. long offset;
  301. if (vpTail->flag == F_EOF) {
  302. // No next to get, Trip
  303. SetEvent (vSemMoreData); // moredata just in case
  304. return; // t1 has blocked on it
  305. // No next to get, Trip
  306. }
  307. offset = vpTail->offset+BLOCKSIZE;
  308. // Get a block
  309. if (vCntBlks == vMaxBlks) {
  310. WaitForSingleObject(vSemBrief, WAITFOREVER);
  311. ResetEvent(vSemBrief);
  312. if (vpHead == vpCur) {
  313. SetEvent (vSemBrief);
  314. if ((GetLoffset() > vpTail->offset) && (GetLoffset() <= (vpTail->offset + BLOCKSIZE))) {
  315. offset = GetLoffset();
  316. }
  317. ReadDirect (offset);
  318. return;
  319. }
  320. pt = vpHead;
  321. vpHead = vpHead->next;
  322. vpHead->prev = NULL;
  323. SetEvent (vSemBrief);
  324. } else
  325. pt = alloc_block (offset);
  326. pt->next = NULL;
  327. // Before linking record into chain, or signaling MoreData
  328. // line info is processed
  329. ReadBlock (pt, offset);
  330. if (GetLoffset() <= pt->offset)
  331. add_more_lines (pt, vpTail);
  332. WaitForSingleObject(vSemBrief, WAITFOREVER);
  333. ResetEvent(vSemBrief); // Link in new
  334. vpTail->next = pt; // block, then
  335. pt->prev = vpTail; // signal
  336. vpTail = pt;
  337. SetEvent (vSemBrief);
  338. SetEvent (vSemMoreData); // Signal another BLK read
  339. }
  340. void
  341. add_more_lines (
  342. struct Block *cur,
  343. struct Block *prev
  344. )
  345. {
  346. char *pData;
  347. long *pLine;
  348. Uchar LineLen;
  349. Uchar c;
  350. unsigned LineIndex;
  351. unsigned DataIndex;
  352. enum{ CT_ANK, CT_LEAD, CT_TRAIL } charType = CT_ANK;
  353. BOOL fLastBlock;
  354. static UINT cp = 0;
  355. long xNLine;
  356. // doesn't work w/ tabs... it should count the line len
  357. // with a different param, and figure in the TABs
  358. if (vLastLine != NOLASTLINE)
  359. return;
  360. if (vNLine/PLINES >= MAXTPAGE) {
  361. puts("Sorry, This file is too big for LIST to handle - MAXTPAGE limit exceeded\n");
  362. CleanUp();
  363. ExitProcess(0);
  364. }
  365. // Find starting data position
  366. if (GetLoffset() < cur->offset) {
  367. DataIndex = (unsigned)(BLOCKSIZE - (GetLoffset() - prev->offset));
  368. pData = prev->Data + BLOCKSIZE - DataIndex;
  369. fLastBlock = FALSE;
  370. } else {
  371. DataIndex = cur->size; // Use cur->size, in case EOF
  372. pData = cur->Data;
  373. fLastBlock = TRUE;
  374. }
  375. // Get starting line length table position
  376. LineIndex = (unsigned)(vNLine % PLINES);
  377. pLine = vprgLineTable [vNLine / PLINES] + LineIndex;
  378. LineLen = 0;
  379. if (cp==0) {
  380. cp = GetConsoleCP();
  381. }
  382. // Look for lines in the file
  383. for (; ;) {
  384. c = *(pData++);
  385. switch (cp) {
  386. case 932:
  387. if( charType != CT_LEAD )
  388. charType = IsDBCSLeadByte(c) ? CT_LEAD : CT_ANK;
  389. else
  390. charType = CT_TRAIL;
  391. break;
  392. default:
  393. break;
  394. }
  395. if (--DataIndex == 0) {
  396. if (fLastBlock)
  397. break; // Last block to scan?
  398. DataIndex = cur->size; // No, move onto next
  399. pData = cur->Data; // Block of data
  400. fLastBlock = TRUE;
  401. }
  402. LineLen++;
  403. if ((c == '\n') ||
  404. (c == '\r') ||
  405. (LineLen == vWrap) ||
  406. ((LineLen == vWrap-1) && (charType != CT_LEAD) && IsDBCSLeadByte(*pData))
  407. )
  408. {
  409. // Got a line. Check for CR/LF sequence, then record
  410. // it's length.
  411. if ( (c == '\n' && *pData == '\r') ||
  412. (c == '\r' && *pData == '\n'))
  413. {
  414. LineLen++;
  415. pData++;
  416. if (--DataIndex == 0) {
  417. if (fLastBlock)
  418. break;
  419. DataIndex = cur->size;
  420. pData = cur->Data;
  421. fLastBlock = TRUE;
  422. }
  423. }
  424. SetLoffset(GetLoffset() + LineLen);
  425. *(pLine++) = GetLoffset();
  426. LineLen = 0;
  427. vNLine++;
  428. if (++LineIndex >= PLINES) { // Overflowed table
  429. LineIndex = 0;
  430. vprgLineTable[vNLine / PLINES] = pLine = (LFP) alloc_page();
  431. }
  432. }
  433. }
  434. // Was last line just processed?
  435. // ... 0 len lines past EOF
  436. if (cur->flag & F_EOF) {
  437. if (LineLen) {
  438. SetLoffset(GetLoffset() + LineLen);
  439. *(pLine++) = GetLoffset();
  440. vNLine++;
  441. LineIndex++;
  442. }
  443. vLastLine = vNLine-1;
  444. xNLine = vNLine;
  445. for (c=0; c<MAXLINES; c++) {
  446. xNLine++;
  447. if (++LineIndex >= PLINES) {
  448. LineIndex = 0;
  449. vprgLineTable[xNLine / PLINES] = pLine = (LFP) alloc_page();
  450. }
  451. *(pLine++) = GetLoffset();
  452. }
  453. // Free the memory we don't need
  454. }
  455. }
  456. // ReadPrev - To read backwards into file
  457. void
  458. ReadPrev ()
  459. {
  460. struct Block *pt;
  461. long offset;
  462. if (vpHead->offset == 0L) { // No next to get, Trip
  463. SetEvent (vSemMoreData); // moredata just in case
  464. return; // t1 has blocked on it
  465. }
  466. if (vpHead->offset == 0L) { // No next to get, Trip
  467. return; // t1 has blocked on it
  468. }
  469. offset = vpHead->offset-BLOCKSIZE;
  470. // Get a block
  471. if (vCntBlks == vMaxBlks) {
  472. WaitForSingleObject(vSemBrief, WAITFOREVER);
  473. ResetEvent(vSemBrief);
  474. if (vpHead == vpCur) {
  475. SetEvent (vSemBrief);
  476. ReadDirect (offset);
  477. return;
  478. }
  479. pt = vpTail;
  480. vpTail = vpTail->prev;
  481. vpTail->next = NULL;
  482. SetEvent (vSemBrief);
  483. } else
  484. pt = alloc_block (offset);
  485. pt->prev = NULL;
  486. ReadBlock (pt, offset);
  487. WaitForSingleObject(vSemBrief, WAITFOREVER);
  488. ResetEvent(vSemBrief); // Link in new
  489. vpHead->prev = pt; // block, then
  490. pt->next = vpHead; // signal
  491. vpHead = pt;
  492. SetEvent (vSemBrief);
  493. SetEvent (vSemMoreData); // Signal another BLK read
  494. }
  495. // ReadBlock - Read in one block
  496. void
  497. ReadBlock (
  498. struct Block *pt,
  499. long offset
  500. )
  501. {
  502. long l;
  503. DWORD dwSize;
  504. if (pt->offset == offset)
  505. return;
  506. pt->offset = offset;
  507. if (vFhandle == 0) { // No file?
  508. pt->size = 1;
  509. pt->flag = F_EOF;
  510. pt->Data[0] = '\n';
  511. return;
  512. }
  513. if (offset != vCurOffset) {
  514. l = SetFilePointer( vFhandle, offset, NULL, FILE_BEGIN );
  515. if (l == -1) {
  516. ckerr (GetLastError(), "SetFilePointer");
  517. }
  518. }
  519. if( !ReadFile (vFhandle, pt->Data, BLOCKSIZE, &dwSize, NULL) ) {
  520. ckerr ( GetLastError(), "ReadFile" );
  521. }
  522. pt->size = (USHORT) dwSize;
  523. if (pt->size != BLOCKSIZE) {
  524. pt->Data[pt->size++] = '\n';
  525. memset (pt->Data + pt->size, 0, BLOCKSIZE-pt->size);
  526. pt->flag = F_EOF;
  527. vCurOffset += pt->size;
  528. } else {
  529. pt->flag = 0;
  530. vCurOffset += BLOCKSIZE;
  531. }
  532. }
  533. void
  534. SyncReader ()
  535. {
  536. vReaderFlag = F_SYNC;
  537. SetEvent (vSemReader);
  538. WaitForSingleObject(vSemSync, WAITFOREVER);
  539. ResetEvent(vSemSync);
  540. }
  541. // These functions are used for the call to HexEdit()
  542. NTSTATUS
  543. fncRead (
  544. HANDLE h,
  545. DWORD loc,
  546. char *data,
  547. DWORD len,
  548. ULONG *ploc
  549. )
  550. {
  551. DWORD l, br;
  552. l = SetFilePointer (h, loc, NULL, FILE_BEGIN);
  553. if (l == -1)
  554. return GetLastError();
  555. if (!ReadFile (h, data, len, &br, NULL))
  556. return GetLastError();
  557. return (br != len ? ERROR_READ_FAULT : 0);
  558. }
  559. NTSTATUS
  560. fncWrite (
  561. HANDLE h,
  562. DWORD loc,
  563. char *data,
  564. DWORD len,
  565. ULONG ploc
  566. )
  567. {
  568. DWORD l, bw;
  569. l = SetFilePointer (h, loc, NULL, FILE_BEGIN);
  570. if (l == -1)
  571. return GetLastError();
  572. if (!WriteFile (h, data, len, &bw, NULL))
  573. return GetLastError();
  574. return (bw != len ? ERROR_WRITE_FAULT : 0);
  575. }
  576. long CurrentLineOffset;
  577. long GetLoffset() {
  578. return(CurrentLineOffset);
  579. }
  580. void SetLoffset(long l) {
  581. CurrentLineOffset = l;
  582. return;
  583. }