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.

578 lines
18 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. rx_thrd.c
  5. Abstract:
  6. This module implements async. MR/MH page decoding in a separate thread.
  7. Author:
  8. Rafael Lisitsa (RafaelL) 14-Aug-1996
  9. Revision History:
  10. --*/
  11. #define USE_DEBUG_CONTEXT DEBUG_CONTEXT_T30_MAIN
  12. #include "prep.h"
  13. #include "efaxcb.h"
  14. #include "t30.h"
  15. #include "hdlc.h"
  16. #include "debug.h"
  17. #include "tiff.h"
  18. #include "..\..\..\tiff\src\fasttiff.h"
  19. #include "glbproto.h"
  20. #include "t30gl.h"
  21. // 15 min.
  22. #define WAIT_FOR_NEXT_STRIP_RX_TIMEOUT 900000
  23. #define RET_NEXT_STRIP_RX_TIMEOUT 1
  24. BOOL DecodeFaxPageAsync
  25. (
  26. PThrdGlbl pTG,
  27. DWORD *RetFlags,
  28. char *InFileName
  29. );
  30. DWORD PageAckThread(PThrdGlbl pTG)
  31. {
  32. DWORD RetCode = FALSE;
  33. DWORD RetFlags = 0;
  34. DWORD ThrdDoneRetCode;
  35. char InFileName[_MAX_FNAME];
  36. DEBUG_FUNCTION_NAME(_T("PageAckThread"));
  37. //
  38. // Set the appropriate PRTY for this thread
  39. // I/O threads run at 15. TIFF - at 9...11
  40. //
  41. if (! SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST) )
  42. {
  43. DebugPrintEx( DEBUG_ERR,
  44. "SetThreadPriority HIGHEST failed le=%x",
  45. GetLastError());
  46. goto error_exit;
  47. }
  48. // binary file has fixed name based on lineID; it is created and updated by T.30 RX I/O thread.
  49. _fmemcpy (InFileName, gT30.TmpDirectory, gT30.dwLengthTmpDirectory);
  50. _fmemcpy (&InFileName[gT30.dwLengthTmpDirectory], pTG->TiffConvertThreadParams.lpszLineID, 8);
  51. sprintf (&InFileName[gT30.dwLengthTmpDirectory+8], ".RX");
  52. do
  53. {
  54. RetFlags = 0;
  55. ThrdDoneRetCode = DecodeFaxPageAsync ( pTG,
  56. &RetFlags,
  57. InFileName);
  58. DebugPrintEx( DEBUG_MSG,
  59. "DecodeFaxPageAsync RetFlags=%d",
  60. RetFlags);
  61. if ( RetFlags == RET_NEXT_STRIP_RX_TIMEOUT )
  62. {
  63. DebugPrintEx( DEBUG_MSG,
  64. "TimeOut. Trying to delete file%s",
  65. InFileName);
  66. if (!DeleteFile(InFileName))
  67. {
  68. DebugPrintEx( DEBUG_ERR,
  69. "Could not delete file %s, le = %x",
  70. InFileName,
  71. GetLastError());
  72. }
  73. return (FALSE);
  74. }
  75. // Signal that we finish process the page.
  76. if (!SetEvent(pTG->ThrdDoneSignal))
  77. {
  78. DebugPrintEx( DEBUG_ERR,
  79. "SetEvent(0x%lx) returns failure code: %ld",
  80. (ULONG_PTR)pTG->ThrdDoneSignal,
  81. (long) GetLastError());
  82. RetCode = FALSE;
  83. goto error_exit;
  84. }
  85. }
  86. while (! pTG->ReqTerminate); // Handle the next page
  87. if (!DeleteFile(InFileName))
  88. {
  89. DebugPrintEx( DEBUG_ERR,
  90. "Could not delete file %s, le = %x",
  91. InFileName,
  92. GetLastError());
  93. }
  94. DebugPrintEx(DEBUG_MSG,"Terminated");
  95. RetCode = TRUE;
  96. error_exit:
  97. pTG->AckTerminate = 1;
  98. pTG->fOkToResetAbortReqEvent = 1;
  99. if (!SetEvent(pTG->ThrdAckTerminateSignal))
  100. {
  101. DebugPrintEx( DEBUG_ERR,
  102. "SetEvent(0x%lx) returns failure code: %ld",
  103. (ULONG_PTR)pTG->ThrdAckTerminateSignal,
  104. (long) GetLastError());
  105. RetCode = FALSE;
  106. }
  107. DebugPrintEx(DEBUG_MSG,"PageAckThread EXITs");
  108. return (RetCode);
  109. }
  110. BOOL DecodeFaxPageAsync
  111. (
  112. PThrdGlbl pTG,
  113. DWORD *RetFlags,
  114. char *InFileName
  115. )
  116. {
  117. HANDLE InFileHandle;
  118. DWORD AllowedBadFaxLines = gT30.MaxErrorLinesPerPage;
  119. DWORD AllowedConsecBadLines = gT30.MaxConsecErrorLinesPerPage;
  120. LPDWORD EndPtr;
  121. LPDWORD EndBuffer;
  122. LPDWORD lpdwResPtr;
  123. LPDWORD lpdwRead;
  124. BYTE ResBit;
  125. BOOL fTestLength;
  126. BOOL fError;
  127. BOOL fFirstRead;
  128. LPDWORD lpBuffer=NULL;
  129. BOOL fLastReadBlockSync; // needs to be sync. fetched, updated by RX I/O thrd.
  130. DWORD BytesReuse;
  131. DWORD BytesDelta;
  132. DWORD BytesToRead;
  133. DWORD BytesHaveRead;
  134. BOOL f1D;
  135. DWORD PageCount;
  136. DWORD NumHandles=2;
  137. HANDLE HandlesArray[2];
  138. DWORD WaitResult;
  139. BOOL fRet=TRUE;
  140. //
  141. // At Start of Page
  142. //
  143. DEBUG_FUNCTION_NAME(_T("DecodeFaxPageAsync"));
  144. HandlesArray[0] = pTG->AbortReqEvent;
  145. HandlesArray[1] = pTG->ThrdSignal;
  146. pTG->fTiffThreadRunning = 0;
  147. do
  148. {
  149. WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, WAIT_FOR_NEXT_STRIP_RX_TIMEOUT);
  150. if (WaitResult == WAIT_TIMEOUT)
  151. {
  152. *RetFlags = RET_NEXT_STRIP_RX_TIMEOUT;
  153. return FALSE;
  154. }
  155. if (WaitResult == WAIT_FAILED)
  156. {
  157. DebugPrintEx( DEBUG_ERR,
  158. "WaitForMultipleObjects FAILED le=%lx",
  159. GetLastError());
  160. }
  161. if ( pTG->ReqTerminate || ( WaitResult == WAIT_OBJECT_0) )
  162. {
  163. DebugPrintEx(DEBUG_MSG, "wait for next page ABORTED") ;
  164. pTG->fOkToResetAbortReqEvent = 1;
  165. return TRUE;
  166. }
  167. }
  168. while (pTG->fPageIsBad); // pTG->fPageIsBad become FALSE when we call to RECV_STARTPAGE to get new page.
  169. // The reason we wait for fPageIsBad: If the prev page was bad, we want to wait till clean-up was done.
  170. pTG->fTiffThreadRunning = 1;
  171. pTG->Lines = 0;
  172. pTG->BadFaxLines = 0;
  173. pTG->ConsecBadLines = 0;
  174. pTG->iResScan = 0;
  175. PageCount = pTG->PageCount;
  176. fLastReadBlockSync = pTG->fLastReadBlock;
  177. DebugPrintEx( DEBUG_MSG,
  178. "waked up fLastReadBlockSync=%d",
  179. fLastReadBlockSync);
  180. if ( ( InFileHandle = CreateFileA(InFileName, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
  181. NULL, OPEN_EXISTING, 0, NULL) ) == INVALID_HANDLE_VALUE )
  182. {
  183. DebugPrintEx( DEBUG_ERR,
  184. "PAGE COULD NOT open %s",
  185. InFileName);
  186. pTG->fPageIsBad = 1;
  187. return FALSE;
  188. }
  189. fFirstRead = 1;
  190. pTG->BytesOut = 0;
  191. lpBuffer = MemAlloc(DECODE_BUFFER_SIZE);
  192. if (!lpBuffer)
  193. {
  194. DebugPrintEx(DEBUG_ERR, "MemAlloc failed");
  195. pTG->fPageIsBad = 1;
  196. goto bad_exit;
  197. }
  198. // lpBuffer is DWORD aligned
  199. lpdwResPtr = lpBuffer;
  200. ResBit = 0;
  201. EndBuffer = lpBuffer + ( DECODE_BUFFER_SIZE / sizeof(DWORD) );
  202. //
  203. // loop thru all blocks
  204. //
  205. do
  206. {
  207. //
  208. // Read the next RAW block prepared by main I/O thread
  209. //
  210. DWORD tiffCompression;
  211. BOOL HiRes;
  212. if (fFirstRead)
  213. {
  214. lpdwRead = lpBuffer;
  215. BytesReuse = 0;
  216. BytesToRead = DECODE_BUFFER_SIZE;
  217. fTestLength = DO_NOT_TEST_LENGTH;
  218. }
  219. else
  220. {
  221. BytesReuse = (DWORD)((EndBuffer - lpdwResPtr) * sizeof (DWORD));
  222. CopyMemory( (char *) lpBuffer, (char *) lpdwResPtr, BytesReuse);
  223. lpdwRead = lpBuffer + (BytesReuse / sizeof (DWORD) );
  224. BytesToRead = DECODE_BUFFER_SIZE - BytesReuse;
  225. fTestLength = DO_TEST_LENGTH;
  226. }
  227. lpdwResPtr = lpBuffer;
  228. BytesDelta = pTG->BytesIn - pTG->BytesOut;
  229. if (BytesDelta < DECODE_BUFFER_SIZE)
  230. {
  231. if (! fLastReadBlockSync)
  232. {
  233. DebugPrintEx( DEBUG_ERR,
  234. "PAGE LOGIC. SYNC. file %s Bytes: IN:%d OUT:%d",
  235. InFileName,
  236. pTG->BytesIn,
  237. pTG->BytesOut);
  238. pTG->fPageIsBad = 1;
  239. goto bad_exit;
  240. }
  241. }
  242. if (fLastReadBlockSync)
  243. {
  244. if (BytesDelta < BytesToRead)
  245. {
  246. BytesToRead = BytesDelta;
  247. }
  248. }
  249. if (! ReadFile(InFileHandle, lpdwRead, BytesToRead, &BytesHaveRead, NULL ) )
  250. {
  251. DebugPrintEx( DEBUG_ERR,
  252. "PAGE COULD NOT READ file %s Bytes: IN:%d"
  253. " OUT:%d WANTED:%d LE=%x",
  254. InFileName,
  255. pTG->BytesIn,
  256. pTG->BytesOut,
  257. BytesToRead,
  258. GetLastError());
  259. pTG->fPageIsBad = 1;
  260. goto bad_exit;
  261. }
  262. if (BytesHaveRead != BytesToRead)
  263. {
  264. DebugPrintEx( DEBUG_ERR,
  265. "PAGE ReadFile count=%d WANTED=%d file %s"
  266. " Bytes: IN:%d OUT:%d",
  267. BytesHaveRead,
  268. BytesToRead,
  269. InFileName,
  270. pTG->BytesIn,
  271. pTG->BytesOut);
  272. pTG->fPageIsBad = 1;
  273. goto bad_exit;
  274. }
  275. if ( fLastReadBlockSync && (BytesToRead == BytesDelta) )
  276. {
  277. EndPtr = lpBuffer + ( (BytesReuse + BytesToRead) / sizeof(DWORD) );
  278. }
  279. else
  280. {
  281. //
  282. // leave 1000*4 = 4000 bytes ahead if not final block to make sure
  283. // we always have one full line ahead.
  284. //
  285. EndPtr = EndBuffer - 1000;
  286. }
  287. pTG->BytesOut += BytesToRead;
  288. DebugPrintEx( DEBUG_MSG,
  289. "BytesIn=%d Out=%d Read=%d ResBit=%d StartPtr=%lx"
  290. " EndPtr=%lx Reuse=%d",
  291. pTG->BytesIn,
  292. pTG->BytesOut,
  293. BytesToRead,
  294. ResBit,
  295. lpBuffer,
  296. EndPtr,
  297. BytesReuse);
  298. //
  299. // find first EOL
  300. //
  301. f1D = 1;
  302. if (! FindNextEol (lpdwResPtr, ResBit, EndBuffer, &lpdwResPtr, &ResBit, fTestLength, &fError) )
  303. {
  304. DebugPrintEx( DEBUG_ERR,
  305. "Couldn't find EOL fTestLength=%d fError=%d",
  306. fTestLength,
  307. fError);
  308. pTG->fPageIsBad = 1;
  309. goto bad_exit;
  310. }
  311. //
  312. // Scan the next segment
  313. //
  314. // if those settings change from one page to the other
  315. // it has to be inside the loop, beause this thread
  316. // gets all the pages and then dies
  317. tiffCompression = pTG->TiffConvertThreadParams.tiffCompression;
  318. HiRes = pTG->TiffConvertThreadParams.HiRes;
  319. DebugPrintEx( DEBUG_MSG,
  320. "Calling %s with compression=%d and resolution=%d",
  321. (tiffCompression == TIFF_COMPRESSION_MR)?"ScanMrSegment":"ScanMhSegment",
  322. tiffCompression,HiRes);
  323. if (tiffCompression == TIFF_COMPRESSION_MR)
  324. {
  325. pTG->iResScan = ScanMrSegment(&lpdwResPtr,
  326. &ResBit,
  327. EndPtr,
  328. EndBuffer,
  329. &(pTG->Lines),
  330. &(pTG->BadFaxLines),
  331. &(pTG->ConsecBadLines),
  332. AllowedBadFaxLines,
  333. AllowedConsecBadLines,
  334. &f1D,
  335. pTG->TiffInfo.ImageWidth);
  336. }
  337. else
  338. {
  339. pTG->iResScan = ScanMhSegment(&lpdwResPtr,
  340. &ResBit,
  341. EndPtr,
  342. EndBuffer,
  343. &(pTG->Lines),
  344. &(pTG->BadFaxLines),
  345. &(pTG->ConsecBadLines),
  346. AllowedBadFaxLines,
  347. AllowedConsecBadLines,
  348. pTG->TiffInfo.ImageWidth);
  349. }
  350. DebugPrintEx( DEBUG_MSG,
  351. "%s returned: ResScan=%d Lines=%d "
  352. "BadFaxLines=%d tAllowedBadFaxLines=%d "
  353. "ConsecBadLines=%d AllowedConsecBadLines=%d "
  354. "tpImageWidth=%d",
  355. (tiffCompression == TIFF_COMPRESSION_MR)?"ScanMrSegment":"ScanMhSegment",
  356. pTG->iResScan,
  357. pTG->Lines,
  358. pTG->BadFaxLines,
  359. AllowedBadFaxLines,
  360. pTG->ConsecBadLines,
  361. AllowedConsecBadLines,
  362. pTG->TiffInfo.ImageWidth);
  363. if (pTG->iResScan == TIFF_SCAN_SUCCESS)
  364. {
  365. goto good_exit;
  366. }
  367. else if (pTG->iResScan == TIFF_SCAN_FAILURE)
  368. {
  369. DebugPrintEx( DEBUG_ERR,
  370. "ScanSegment returns TIFF_SCAN_FAILURE");
  371. pTG->fPageIsBad = 1;
  372. goto bad_exit;
  373. }
  374. else if (pTG->iResScan != TIFF_SCAN_SEG_END)
  375. {
  376. DebugPrintEx( DEBUG_ERR,
  377. "ScanSegment returns INVALID %d",
  378. pTG->iResScan);
  379. pTG->fPageIsBad = 1;
  380. goto bad_exit;
  381. }
  382. //lNextBlock:
  383. // here we make decision as to whether to do the next segment OR to block (not enough data avail).
  384. if (fLastReadBlockSync && (pTG->BytesOut == pTG->BytesIn) )
  385. {
  386. //
  387. // The class 2/2.0 standards say the modem is not supposed to include the RTC in the page data.
  388. // So, for 2/2.0, finishing the page without finding RTC marks the page as good.
  389. //
  390. if ((pTG->ModemClass==MODEM_CLASS2) || (pTG->ModemClass==MODEM_CLASS2_0))
  391. {
  392. DebugPrintEx(DEBUG_MSG, "Didn't find RTC, but we're on class 2/2.0, so page is good");
  393. goto good_exit;
  394. }
  395. DebugPrintEx( DEBUG_ERR,
  396. "Didn't find RTC Bad=%d ConsecBad=%d Good=%d",
  397. pTG->BadFaxLines,
  398. pTG->ConsecBadLines,
  399. pTG->Lines);
  400. pTG->fPageIsBad = 1;
  401. goto bad_exit;
  402. }
  403. DebugPrintEx( DEBUG_MSG,
  404. "Done with next strip BytesIn=%d Out=%d"
  405. " Lines=%d Bad=%d ConsecBad=%d Processed %d bytes \n",
  406. pTG->BytesIn,
  407. pTG->BytesOut,
  408. pTG->Lines,
  409. pTG->BadFaxLines,
  410. pTG->ConsecBadLines,
  411. (lpdwResPtr - lpBuffer) * sizeof(DWORD));
  412. fLastReadBlockSync = pTG->fLastReadBlock;
  413. if ( (pTG->BytesIn - pTG->BytesOut < DECODE_BUFFER_SIZE) && (! fLastReadBlockSync) )
  414. {
  415. DebugPrintEx(DEBUG_MSG,"Waiting for next strip to be avail.");
  416. pTG->fTiffThreadRunning = 0;
  417. WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, WAIT_FOR_NEXT_STRIP_RX_TIMEOUT);
  418. if (WaitResult == WAIT_TIMEOUT)
  419. {
  420. *RetFlags = RET_NEXT_STRIP_RX_TIMEOUT;
  421. goto bad_exit;
  422. }
  423. if (WaitResult == WAIT_FAILED)
  424. {
  425. DebugPrintEx( DEBUG_ERR,
  426. "WaitForMultipleObjects FAILED le=%lx",
  427. GetLastError());
  428. }
  429. if ( pTG->ReqTerminate || ( WaitResult == WAIT_OBJECT_0) )
  430. {
  431. DebugPrintEx(DEBUG_MSG,"wait for next page ABORTED") ;
  432. goto bad_exit;
  433. }
  434. pTG->fTiffThreadRunning = 1;
  435. fLastReadBlockSync = pTG->fLastReadBlock;
  436. DebugPrintEx( DEBUG_MSG,
  437. "Waked up with next strip. fLastReadBlockSync=%d"
  438. " BytesIn=%d Out=%d",
  439. fLastReadBlockSync,
  440. pTG->BytesIn,
  441. pTG->BytesOut);
  442. }
  443. fFirstRead = 0;
  444. }
  445. while ( ! pTG->ReqTerminate );
  446. DebugPrintEx(DEBUG_ERR, "Got Terminate request");
  447. pTG->fPageIsBad = 1;
  448. // fall through
  449. bad_exit:
  450. fRet=FALSE;
  451. goto exit;
  452. good_exit:
  453. fRet=TRUE;
  454. // fall through
  455. exit:
  456. CloseHandle(InFileHandle);
  457. if (lpBuffer)
  458. {
  459. MemFree(lpBuffer);
  460. lpBuffer=NULL;
  461. }
  462. return fRet;
  463. }