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.

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. WIN32_FILE_ATTRIBUTE_DATA fd;
  140. long *pLine;
  141. HANDLE TempHandle;
  142. struct Block **pBlk, **pBlkCache;
  143. if (vFhandle)
  144. CloseHandle (vFhandle);
  145. vFType = 0;
  146. vCurOffset = 0L;
  147. // WARNING: Microsoft Confidential!!!
  148. strcpy (s, "Listing ");
  149. strcpy (s+8, vpFname);
  150. // Design change per DougHo.. open files in read-only deny-none mode.
  151. vFhandle = CreateFile( vpFlCur->fname,
  152. GENERIC_READ,
  153. FILE_SHARE_READ|FILE_SHARE_WRITE,
  154. NULL,
  155. OPEN_EXISTING,
  156. 0,
  157. NULL );
  158. if (vFhandle == (HANDLE)(-1)) {
  159. if (vpFlCur->prev == NULL && vpFlCur->next == NULL) {
  160. // Only one file specified?
  161. printf ("Could not open file '%Fs': %s",
  162. (CFP) vpFlCur->fname, GetErrorCode( GetLastError() ));
  163. CleanUp();
  164. ExitProcess(0);
  165. }
  166. vFhandle = 0; // Error. Set externals to "safe"
  167. vFSize = (unsigned)-1L; // settings. Flag error by setting
  168. vNLine = 1; // file_size = -1
  169. vLastLine = NOLASTLINE;
  170. vDirOffset = vTopLine = 0L;
  171. SetLoffset(0L);
  172. memset (vprgLineTable, 0, sizeof (long *) * MAXTPAGE);
  173. vprgLineTable[0] = (LFP) alloc_page ();
  174. if (!vprgLineTable[0]) {
  175. return;
  176. }
  177. vprgLineTable[0][0] = 0L; // 1st line always starts @ 0
  178. strncpy (vDate, GetErrorCode( GetLastError() ), 20);
  179. vDate[20] = 0;
  180. return ;
  181. }
  182. vFSize = GetFileSize(vFhandle, NULL);
  183. if (!GetFileAttributesEx( vpFlCur->fname, GetFileExInfoStandard, &fd )) {
  184. ckerr( GetLastError(), "GetFileAttributesEx" );
  185. }
  186. FileTimeToLocalFileTime( &(fd.ftLastWriteTime), &LocalFileTime );
  187. FileTimeToSystemTime( &LocalFileTime, &SystemTime );
  188. h = (char)SystemTime.wHour;
  189. c = 'a';
  190. if (h >= 12) {
  191. c = 'p'; // pm
  192. if (h > 12) // convert 13-23 --> 1pm-11pm
  193. h -= 12;
  194. }
  195. if (h == 0) // convert 0 --> 12am
  196. h = 12;
  197. sprintf (vDate, "%c%c %c%c%c%c %2d/%02d/%02d %2d:%02d%c",
  198. // File is in memory
  199. // Search is set for mult files
  200. vStatCode & S_MFILE ? '*' : ' ', // File is in memory
  201. vFType & 0x8000 ? 'N' : ' ', // Network
  202. fd.dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? 'R' : ' ', // Readonly
  203. fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? 'H' : ' ', // Hidden
  204. fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? 'S' : ' ', // System
  205. ' ', // Vio
  206. SystemTime.wMonth,
  207. SystemTime.wDay,
  208. SystemTime.wYear,
  209. h,
  210. SystemTime.wMinute,
  211. c);
  212. pBlkCache = &vpBCache;
  213. if (CompareFileTime( &fd.ftLastWriteTime, &vpFlCur->FileTime ) != 0) {
  214. vpFlCur->NLine = 1L; // Something has changed.
  215. vpFlCur->LastLine = NOLASTLINE; // Scrap the old info, and
  216. vpFlCur->HighTop = -1; // start over
  217. vpFlCur->TopLine = 0L;
  218. vpFlCur->Loffset = vpFlCur->SlimeTOF;
  219. FreePages (vpFlCur);
  220. memset (vpFlCur->prgLineTable, 0, sizeof (long *) * MAXTPAGE);
  221. vpFlCur->FileTime = fd.ftLastWriteTime;
  222. pBlkCache = &vpBFree; // Move blks to free list, not cache list
  223. }
  224. // Restore last known information
  225. vTopLine = vpFlCur->TopLine;
  226. SetLoffset(vpFlCur->Loffset);
  227. vLastLine = vpFlCur->LastLine;
  228. vNLine = vpFlCur->NLine;
  229. vOffTop = 0;
  230. if (vpFlCur->Wrap)
  231. vWrap = vpFlCur->Wrap;
  232. memcpy (vprgLineTable, vpFlCur->prgLineTable, sizeof (long *) * MAXTPAGE);
  233. if (vLastLine == NOLASTLINE) {
  234. pLine = vprgLineTable [vNLine/PLINES] + vNLine % PLINES;
  235. }
  236. if (vprgLineTable[0] == NULL) {
  237. vprgLineTable[0] = (LFP) alloc_page ();
  238. if (!vprgLineTable[0]) {
  239. return;
  240. }
  241. vprgLineTable[0][0] = vpFlCur->SlimeTOF;
  242. }
  243. vDirOffset = vprgLineTable[vTopLine/PLINES][vTopLine%PLINES];
  244. vDirOffset -= vDirOffset % ((long)BLOCKSIZE);
  245. // Adjust buffers..
  246. // Move cur buffers to other list
  247. // Move cache buffers to other list
  248. // Scan other list for cache blks, and move to cache (or free) list
  249. if (vpHead) {
  250. vpTail->next = vpBOther; // move them into the other
  251. vpBOther = vpHead; // list
  252. vpHead = NULL;
  253. }
  254. pBlk = &vpBCache;
  255. while (*pBlk)
  256. MoveBlk (pBlk, &vpBOther) ;
  257. pBlk = &vpBOther;
  258. while (*pBlk) {
  259. if ((*pBlk)->pFile == vpFlCur)
  260. MoveBlk (pBlk, pBlkCache);
  261. else pBlk = &(*pBlk)->next;
  262. }
  263. }
  264. // ReadDirect - Moves to the direct position in the file
  265. //
  266. // First check to see if start of buffers have direct position file,
  267. // if so then do nothing. If not, clear all buffers and start
  268. // reading blocks.
  269. void
  270. ReadDirect (
  271. long offset
  272. )
  273. {
  274. WaitForSingleObject(vSemBrief, WAITFOREVER);
  275. ResetEvent(vSemBrief);
  276. if (vpHead) {
  277. vpTail->next = vpBCache; // move them into the cache
  278. vpBCache = vpHead; // list
  279. }
  280. vpTail = vpHead = vpCur = alloc_block (offset);
  281. vpHead->next = vpTail->prev = NULL;
  282. vCntBlks = 1;
  283. // Freeing is complete, now read in the first block.
  284. // and process lines.
  285. ReadBlock (vpHead, offset);
  286. // maybe it fixes the bug
  287. vpBlockTop = vpHead;
  288. if (GetLoffset() <= vpHead->offset)
  289. add_more_lines (vpHead, NULL);
  290. SetEvent (vSemBrief);
  291. SetEvent (vSemMoreData); // Signal another BLK read
  292. }
  293. // ReadNext - To read further into file
  294. void
  295. ReadNext ()
  296. {
  297. struct Block *pt;
  298. long offset;
  299. if (vpTail->flag == F_EOF) {
  300. // No next to get, Trip
  301. SetEvent (vSemMoreData); // moredata just in case
  302. return; // t1 has blocked on it
  303. // No next to get, Trip
  304. }
  305. offset = vpTail->offset+BLOCKSIZE;
  306. // Get a block
  307. if (vCntBlks == vMaxBlks) {
  308. WaitForSingleObject(vSemBrief, WAITFOREVER);
  309. ResetEvent(vSemBrief);
  310. if (vpHead == vpCur) {
  311. SetEvent (vSemBrief);
  312. if ((GetLoffset() > vpTail->offset) && (GetLoffset() <= (vpTail->offset + BLOCKSIZE))) {
  313. offset = GetLoffset();
  314. }
  315. ReadDirect (offset);
  316. return;
  317. }
  318. pt = vpHead;
  319. vpHead = vpHead->next;
  320. vpHead->prev = NULL;
  321. SetEvent (vSemBrief);
  322. } else
  323. pt = alloc_block (offset);
  324. pt->next = NULL;
  325. // Before linking record into chain, or signaling MoreData
  326. // line info is processed
  327. ReadBlock (pt, offset);
  328. if (GetLoffset() <= pt->offset)
  329. add_more_lines (pt, vpTail);
  330. WaitForSingleObject(vSemBrief, WAITFOREVER);
  331. ResetEvent(vSemBrief); // Link in new
  332. vpTail->next = pt; // block, then
  333. pt->prev = vpTail; // signal
  334. vpTail = pt;
  335. SetEvent (vSemBrief);
  336. SetEvent (vSemMoreData); // Signal another BLK read
  337. }
  338. void
  339. add_more_lines (
  340. struct Block *cur,
  341. struct Block *prev
  342. )
  343. {
  344. char *pData;
  345. long *pLine;
  346. Uchar LineLen;
  347. Uchar c;
  348. unsigned LineIndex;
  349. unsigned DataIndex;
  350. enum{ CT_ANK, CT_LEAD, CT_TRAIL } charType = CT_ANK;
  351. BOOL fLastBlock;
  352. static UINT cp = 0;
  353. long xNLine;
  354. // doesn't work w/ tabs... it should count the line len
  355. // with a different param, and figure in the TABs
  356. if (vLastLine != NOLASTLINE)
  357. return;
  358. if (vNLine/PLINES >= MAXTPAGE) {
  359. puts("Sorry, This file is too big for LIST to handle - MAXTPAGE limit exceeded\n");
  360. CleanUp();
  361. ExitProcess(0);
  362. }
  363. // Find starting data position
  364. if (GetLoffset() < cur->offset) {
  365. DataIndex = (unsigned)(BLOCKSIZE - (GetLoffset() - prev->offset));
  366. pData = prev->Data + BLOCKSIZE - DataIndex;
  367. fLastBlock = FALSE;
  368. } else {
  369. DataIndex = cur->size; // Use cur->size, in case EOF
  370. pData = cur->Data;
  371. fLastBlock = TRUE;
  372. }
  373. // Get starting line length table position
  374. LineIndex = (unsigned)(vNLine % PLINES);
  375. pLine = vprgLineTable [vNLine / PLINES] + LineIndex;
  376. LineLen = 0;
  377. if (cp==0) {
  378. cp = GetConsoleCP();
  379. }
  380. // Look for lines in the file
  381. for (; ;) {
  382. c = *(pData++);
  383. switch (cp) {
  384. case 932:
  385. if( charType != CT_LEAD )
  386. charType = IsDBCSLeadByte(c) ? CT_LEAD : CT_ANK;
  387. else
  388. charType = CT_TRAIL;
  389. break;
  390. default:
  391. break;
  392. }
  393. if (--DataIndex == 0) {
  394. if (fLastBlock)
  395. break; // Last block to scan?
  396. DataIndex = cur->size; // No, move onto next
  397. pData = cur->Data; // Block of data
  398. fLastBlock = TRUE;
  399. }
  400. LineLen++;
  401. if ((c == '\n') ||
  402. (c == '\r') ||
  403. (LineLen == vWrap) ||
  404. ((LineLen == vWrap-1) && (charType != CT_LEAD) && IsDBCSLeadByte(*pData))
  405. )
  406. {
  407. // Got a line. Check for CR/LF sequence, then record
  408. // it's length.
  409. if ( (c == '\n' && *pData == '\r') ||
  410. (c == '\r' && *pData == '\n'))
  411. {
  412. LineLen++;
  413. pData++;
  414. if (--DataIndex == 0) {
  415. if (fLastBlock)
  416. break;
  417. DataIndex = cur->size;
  418. pData = cur->Data;
  419. fLastBlock = TRUE;
  420. }
  421. }
  422. SetLoffset(GetLoffset() + LineLen);
  423. *(pLine++) = GetLoffset();
  424. LineLen = 0;
  425. vNLine++;
  426. if (++LineIndex >= PLINES) { // Overflowed table
  427. LineIndex = 0;
  428. vprgLineTable[vNLine / PLINES] = pLine = (LFP) alloc_page();
  429. }
  430. }
  431. }
  432. // Was last line just processed?
  433. // ... 0 len lines past EOF
  434. if (cur->flag & F_EOF) {
  435. if (LineLen) {
  436. SetLoffset(GetLoffset() + LineLen);
  437. *(pLine++) = GetLoffset();
  438. vNLine++;
  439. LineIndex++;
  440. }
  441. vLastLine = vNLine-1;
  442. xNLine = vNLine;
  443. for (c=0; c<MAXLINES; c++) {
  444. xNLine++;
  445. if (++LineIndex >= PLINES) {
  446. LineIndex = 0;
  447. vprgLineTable[xNLine / PLINES] = pLine = (LFP) alloc_page();
  448. }
  449. *(pLine++) = GetLoffset();
  450. }
  451. // Free the memory we don't need
  452. }
  453. }
  454. // ReadPrev - To read backwards into file
  455. void
  456. ReadPrev ()
  457. {
  458. struct Block *pt;
  459. long offset;
  460. if (vpHead->offset == 0L) { // No next to get, Trip
  461. SetEvent (vSemMoreData); // moredata just in case
  462. return; // t1 has blocked on it
  463. }
  464. if (vpHead->offset == 0L) { // No next to get, Trip
  465. return; // t1 has blocked on it
  466. }
  467. offset = vpHead->offset-BLOCKSIZE;
  468. // Get a block
  469. if (vCntBlks == vMaxBlks) {
  470. WaitForSingleObject(vSemBrief, WAITFOREVER);
  471. ResetEvent(vSemBrief);
  472. if (vpHead == vpCur) {
  473. SetEvent (vSemBrief);
  474. ReadDirect (offset);
  475. return;
  476. }
  477. pt = vpTail;
  478. vpTail = vpTail->prev;
  479. vpTail->next = NULL;
  480. SetEvent (vSemBrief);
  481. } else
  482. pt = alloc_block (offset);
  483. pt->prev = NULL;
  484. ReadBlock (pt, offset);
  485. WaitForSingleObject(vSemBrief, WAITFOREVER);
  486. ResetEvent(vSemBrief); // Link in new
  487. vpHead->prev = pt; // block, then
  488. pt->next = vpHead; // signal
  489. vpHead = pt;
  490. SetEvent (vSemBrief);
  491. SetEvent (vSemMoreData); // Signal another BLK read
  492. }
  493. // ReadBlock - Read in one block
  494. void
  495. ReadBlock (
  496. struct Block *pt,
  497. long offset
  498. )
  499. {
  500. long l;
  501. DWORD dwSize;
  502. if (pt->offset == offset)
  503. return;
  504. pt->offset = offset;
  505. if (vFhandle == 0) { // No file?
  506. pt->size = 1;
  507. pt->flag = F_EOF;
  508. pt->Data[0] = '\n';
  509. return;
  510. }
  511. if (offset != vCurOffset) {
  512. l = SetFilePointer( vFhandle, offset, NULL, FILE_BEGIN );
  513. if (l == -1) {
  514. ckerr (GetLastError(), "SetFilePointer");
  515. }
  516. }
  517. if( !ReadFile (vFhandle, pt->Data, BLOCKSIZE, &dwSize, NULL) ) {
  518. ckerr ( GetLastError(), "ReadFile" );
  519. }
  520. pt->size = (USHORT) dwSize;
  521. if (pt->size != BLOCKSIZE) {
  522. pt->Data[pt->size++] = '\n';
  523. memset (pt->Data + pt->size, 0, BLOCKSIZE-pt->size);
  524. pt->flag = F_EOF;
  525. vCurOffset += pt->size;
  526. } else {
  527. pt->flag = 0;
  528. vCurOffset += BLOCKSIZE;
  529. }
  530. }
  531. void
  532. SyncReader ()
  533. {
  534. vReaderFlag = F_SYNC;
  535. SetEvent (vSemReader);
  536. WaitForSingleObject(vSemSync, WAITFOREVER);
  537. ResetEvent(vSemSync);
  538. }
  539. // These functions are used for the call to HexEdit()
  540. NTSTATUS
  541. fncRead (
  542. HANDLE h,
  543. ULONGLONG loc,
  544. PUCHAR data,
  545. DWORD len
  546. )
  547. {
  548. DWORD l, br;
  549. DWORD High = (DWORD)(loc >> 32);
  550. l = SetFilePointer (h, (DWORD)loc, &High, FILE_BEGIN);
  551. if (l == -1)
  552. return GetLastError();
  553. if (!ReadFile (h, data, len, &br, NULL))
  554. return GetLastError();
  555. return (br != len ? ERROR_READ_FAULT : 0);
  556. }
  557. NTSTATUS
  558. fncWrite (
  559. HANDLE h,
  560. ULONGLONG loc,
  561. PUCHAR data,
  562. DWORD len
  563. )
  564. {
  565. DWORD l, bw;
  566. DWORD High = (DWORD)(loc >> 32);
  567. l = SetFilePointer (h, (DWORD)loc, &High, FILE_BEGIN);
  568. if (l == -1)
  569. return GetLastError();
  570. if (!WriteFile (h, data, len, &bw, NULL))
  571. return GetLastError();
  572. return (bw != len ? ERROR_WRITE_FAULT : 0);
  573. }
  574. long CurrentLineOffset;
  575. long GetLoffset() {
  576. return(CurrentLineOffset);
  577. }
  578. void SetLoffset(long l) {
  579. CurrentLineOffset = l;
  580. return;
  581. }