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.

578 lines
17 KiB

  1. /***************************************************************************
  2. Name : SEND.C
  3. Comment : Sender functions
  4. Revision Log
  5. Date Name Description
  6. -------- ----- ---------------------------------------------------------
  7. ***************************************************************************/
  8. #include "prep.h"
  9. #include <comdevi.h>
  10. #include <faxcodec.h>
  11. #include "efaxcb.h"
  12. //#include "debug.h"
  13. #include "cas.h"
  14. #include "bgt30.h"
  15. //#include "dynload.h"
  16. #include "tiff.h"
  17. #include "glbproto.h"
  18. #include "t30gl.h"
  19. SWORD ICommGetSendBuf(PThrdGlbl pTG, LPBUFFER far* lplpbf, SLONG slOffset)
  20. {
  21. /**
  22. slOffset == SEND_STARTBLOCK marks beginning of new block
  23. slOffset == SEND_STARTPAGE marks beginning of new block *and* page
  24. (returns with data from the "appropriate" file offset).
  25. slOffset == SEND_QUERYENDPAGE cbecks if end of page
  26. slOffset == SEND_SEQ means get buffer from current file position
  27. slOffset >= 0 gives the offset in bytes from the last marked position
  28. (beginning of block) to start reading from
  29. Inst.cbBlockStart is always file offset of start of current block
  30. Inst.cbBlockSize is bytes sent of current block in first transmission
  31. Inst.cbPage is bytes left to transmit in current page
  32. returns: SEND_ERROR on error, SEND_EOF on eof, SEND_OK otherwise.
  33. Does not return data on EOF or ERROR, i.e. *lplpbf==0
  34. **/
  35. SWORD sRet = SEND_ERROR;
  36. LPBUFFER lpbf;
  37. BOOL HiRes=0;
  38. DWORD dwBytesRead;
  39. if (pTG->fAbortRequested) {
  40. MyDebugPrint(pTG, LOG_ALL, "ICommGetSendBuf. got ABORT at %ld\n", GetTickCount() );
  41. sRet = SEND_ERROR;
  42. goto mutexit;
  43. }
  44. if(pTG->Inst.fAbort) // GetSendBuf
  45. {
  46. // SetFailureCode already called
  47. sRet = SEND_ERROR;
  48. goto mutexit;
  49. }
  50. if(slOffset == SEND_QUERYENDPAGE)
  51. {
  52. MyDebugPrint(pTG, LOG_ALL, "SendBuf--query EndPage\r\n");
  53. BG_CHK(pTG->Inst.state == SENDDATA_PHASE || pTG->Inst.state == SENDDATA_BETWEENPAGES);
  54. if(pTG->Inst.cbPage == 0 || pTG->Inst.cbPage == -1) // end of page
  55. {
  56. pTG->Inst.cbPage = -1;
  57. pTG->Inst.state = SENDDATA_BETWEENPAGES;
  58. sRet = SEND_EOF;
  59. goto mutexit;
  60. }
  61. else
  62. {
  63. sRet = SEND_OK; // no data returned
  64. goto mutexit;
  65. }
  66. }
  67. if(slOffset == SEND_STARTPAGE)
  68. {
  69. pTG->fTxPageDone=0;
  70. // Delete last successfully transmitted Tiff Page file.
  71. _fmemcpy (pTG->InFileName, gT30.TmpDirectory, gT30.dwLengthTmpDirectory);
  72. _fmemcpy (&pTG->InFileName[gT30.dwLengthTmpDirectory], pTG->lpszPermanentLineID, 8);
  73. if (pTG->PageCount != 0) {
  74. sprintf( &pTG->InFileName[gT30.dwLengthTmpDirectory+8], ".%03d", pTG->PageCount);
  75. if (! DeleteFileA (pTG->InFileName) ) {
  76. MyDebugPrint(pTG, LOG_ERR, "ERROR: file %s can't be deleted; le=%lx at %ld \n",
  77. pTG->InFileName, GetLastError(), GetTickCount() );
  78. }
  79. }
  80. pTG->PageCount++ ;
  81. pTG->CurrentIn++ ;
  82. MyDebugPrint(pTG, LOG_ALL, "SendBuf: Starting New PAGE %d cbBlockSize=%ld First=%d Last=%d time=%ld\n",
  83. pTG->PageCount, pTG->Inst.cbBlockSize, pTG->FirstOut, pTG->LastOut, GetTickCount() );
  84. // Server wants to know when we start TX new page.
  85. SignalStatusChange(pTG, FS_TRANSMITTING);
  86. BG_CHK(pTG->Inst.state == SENDDATA_BETWEENPAGES);
  87. BG_CHK(pTG->Inst.cbPage == -1);
  88. if (pTG->CurrentOut < pTG->CurrentIn ) {
  89. MyDebugPrint(pTG, LOG_ERR, "ERROR: TIFF PAGE hadn't been started CurrentOut=%d; CurrentIn=%d at %ld \n",
  90. pTG->CurrentOut, pTG->CurrentIn, GetTickCount() );
  91. sRet = SEND_ERROR;
  92. goto mutexit;
  93. }
  94. // some slack for 1st page
  95. if ( (pTG->CurrentOut == pTG->CurrentIn) && (pTG->CurrentIn == 1 ) ) {
  96. MyDebugPrint(pTG, LOG_ALL, "SEND: Wait for 1st page: CurrentOut=%d; In=%d at %ld \n",
  97. pTG->CurrentOut, pTG->CurrentIn, GetTickCount() );
  98. if ( WaitForSingleObject(pTG->FirstPageReadyTxSignal, 5000) == WAIT_TIMEOUT ) {
  99. MyDebugPrint(pTG, LOG_ERR, "SEND: TIMEOUT ERROR Wait for 1st page: CurrentOut=%d; In=%d at %ld \n",
  100. pTG->CurrentOut, pTG->CurrentIn, GetTickCount() );
  101. }
  102. MyDebugPrint(pTG, LOG_ALL, "SEND: Wakeup for 1st page: CurrentOut=%d; In=%d at %ld \n",
  103. pTG->CurrentOut, pTG->CurrentIn, GetTickCount() );
  104. }
  105. // open the file created by tiff thread
  106. sprintf( &pTG->InFileName[gT30.dwLengthTmpDirectory+8], ".%03d", pTG->PageCount);
  107. if ( ( pTG->InFileHandle = CreateFileA(pTG->InFileName, GENERIC_READ, FILE_SHARE_READ,
  108. NULL, OPEN_EXISTING, 0, NULL) ) == INVALID_HANDLE_VALUE ) {
  109. MyDebugPrint(pTG, LOG_ERR, "ERROR: OpenFile %s fails; CurrentOut=%d; CurrentIn=%d at %ld \n",
  110. pTG->InFileName, pTG->CurrentOut, pTG->CurrentIn, GetTickCount() );
  111. sRet = SEND_ERROR;
  112. goto mutexit;
  113. }
  114. pTG->InFileHandleNeedsBeClosed = 1;
  115. if ( pTG->CurrentOut == pTG->CurrentIn ) {
  116. MyDebugPrint(pTG, LOG_ALL, "WARNING: CurrentOut=%d; CurrentIn=%d at %ld \n",
  117. pTG->CurrentOut, pTG->CurrentIn, GetTickCount() );
  118. }
  119. //
  120. // Signal TIFF thread to start preparing new page if needed.
  121. //
  122. if ( (! pTG->fTiffDocumentDone) && (pTG->LastOut - pTG->CurrentIn < 2) ) {
  123. ResetEvent(pTG->ThrdSignal);
  124. pTG->ReqStartNewPage = 1;
  125. pTG->AckStartNewPage = 0;
  126. MyDebugPrint(pTG, LOG_ALL, "SIGNAL NEW PAGE CurrentOut=%d; CurrentIn=%d at %ld \n",
  127. pTG->CurrentOut, pTG->CurrentIn, GetTickCount() );
  128. SetEvent(pTG->ThrdSignal);
  129. }
  130. // uOldPermilleDone = 0;
  131. // SetStatus(T30STATS_SEND, pTG->Inst.awfi.uNumPages, 0, 0);
  132. pTG->Inst.cbPage = pTG->Inst.awfi.lDataSize; // size of page
  133. pTG->Inst.cbBlockStart = pTG->Inst.awfi.lDataOffset; // start of 1st block
  134. pTG->Inst.cbBlockSize = 0; // current size of block
  135. pTG->Inst.state = SENDDATA_PHASE;
  136. slOffset = SEND_SEQ;
  137. sRet = SEND_OK;
  138. goto mutexit;
  139. }
  140. else if(slOffset == SEND_STARTBLOCK)
  141. {
  142. // called in ECM mode at start of each block. Not called
  143. // in the first block of each page (STARTPAGE) is called
  144. // instead. Therefore BlockStart and BlockSize can never
  145. // be 0
  146. MyDebugPrint(pTG, LOG_ERR, "ERROR: ECM SendBuf: Starting New BLOCK. cbBlockSize=%ld\r\n", pTG->Inst.cbBlockSize);
  147. sRet = SEND_ERROR;
  148. goto mutexit;
  149. }
  150. BG_CHK(lplpbf);
  151. *lplpbf=0;
  152. if(slOffset == SEND_SEQ) {
  153. if (pTG->fTxPageDone) {
  154. #if 0
  155. if (glSimulateError && (glSimulateErrorType == SIMULATE_ERROR_TX_IO) ) {
  156. SimulateError( EXCEPTION_ACCESS_VIOLATION);
  157. }
  158. #endif
  159. sRet = SEND_EOF;
  160. //BUGBUG RSL delete this file after page is acknowleged
  161. if (pTG->InFileHandleNeedsBeClosed) {
  162. CloseHandle(pTG->InFileHandle);
  163. pTG->InFileHandleNeedsBeClosed = 0;
  164. }
  165. goto mutexit;
  166. }
  167. lpbf = MyAllocBuf(pTG, pTG->Inst.sSendBufSize);
  168. BG_CHK(lpbf);
  169. BG_CHK(pTG->Inst.uSendDataSize <= lpbf->wLengthBuf-4);
  170. lpbf->lpbBegData = lpbf->lpbBegBuf+4;
  171. lpbf->dwMetaData = pTG->Inst.awfi.Encoding;
  172. lpbf->wLengthData = (unsigned) pTG->Inst.sSendBufSize;
  173. if ( ! ReadFile(pTG->InFileHandle, lpbf->lpbBegData, lpbf->wLengthData, &dwBytesRead, 0) ) {
  174. MyDebugPrint(pTG, LOG_ERR, "ERROR:Can't read %d bytes from %s \n", lpbf->wLengthData, pTG->InFileName);
  175. MyFreeBuf (pTG, lpbf);
  176. sRet = SEND_ERROR;
  177. goto mutexit;
  178. }
  179. if ( lpbf->wLengthData != (unsigned) dwBytesRead ) {
  180. if (pTG->fTiffPageDone || (pTG->CurrentIn != pTG->CurrentOut) ) {
  181. // actually reached EndOfPage
  182. lpbf->wLengthData = (unsigned) dwBytesRead;
  183. pTG->fTxPageDone = 1;
  184. }
  185. else {
  186. MyDebugPrint(pTG, LOG_ERR, "ERROR:Wanted %d bytes but ONLY %d ready from %s at %ld\n",
  187. lpbf->wLengthData, dwBytesRead, pTG->InFileName, GetTickCount() );
  188. MyFreeBuf (pTG, lpbf);
  189. sRet = SEND_ERROR;
  190. goto mutexit;
  191. }
  192. }
  193. *lplpbf = lpbf;
  194. MyDebugPrint(pTG, LOG_ALL, "SEND_SEQ: length=%d \n", lpbf->wLengthData);
  195. }
  196. sRet = SEND_OK;
  197. mutexit:
  198. return sRet;
  199. }
  200. void ICommRawCaps(PThrdGlbl pTG, LPBYTE lpbCSI, LPBYTE lpbDIS, USHORT cbDIS,
  201. LPFR FAR * rglpfrNSF, USHORT wNumFrames)
  202. {
  203. }
  204. void ICommSetSendMode(PThrdGlbl pTG, BOOL fECM, LONG sBufSize, USHORT uDataSize, BOOL fPad)
  205. {
  206. BG_CHK(sBufSize && uDataSize && uDataSize <= sBufSize-4);
  207. pTG->Inst.sSendBufSize = sBufSize;
  208. pTG->Inst.uSendDataSize = uDataSize;
  209. pTG->Inst.fSendPad = fPad;
  210. }
  211. USHORT ICommNextSend(PThrdGlbl pTG)
  212. {
  213. USHORT uRet = NEXTSEND_ERROR;
  214. if (pTG->PageCount >= pTG->TiffInfo.PageCount) {
  215. pTG->Inst.awfi.fLastPage = 1;
  216. }
  217. if(pTG->Inst.awfi.fLastPage)
  218. uRet = NEXTSEND_EOP;
  219. else
  220. uRet = NEXTSEND_MPS;
  221. MyDebugPrint(pTG, LOG_ALL, "ICommNextSend uRet=%d, fLastPage=%d \n", uRet, pTG->Inst.awfi.fLastPage);
  222. return uRet;
  223. }
  224. BOOL ICommSendPageAck(PThrdGlbl pTG, BOOL fAck)
  225. {
  226. BOOL fRet = FALSE;
  227. BG_CHK(pTG->Inst.state == SENDDATA_BETWEENPAGES);
  228. if(fAck)
  229. {
  230. SetStatus(pTG, T30STATS_CONFIRM, pTG->Inst.awfi.uNumPages, 0, 0);
  231. pTG->Inst.uPageAcks++;
  232. fRet = FALSE;
  233. }
  234. else
  235. {
  236. SetStatus(pTG, T30STATS_REJECT, pTG->Inst.awfi.uNumPages, 0, 0);
  237. # ifdef RETRANS
  238. // RewindSendPage();
  239. fRet = TRUE;
  240. # else // RETRANS
  241. fRet = FALSE;
  242. # endif // RETRANS
  243. }
  244. //mutexit:
  245. return fRet;
  246. }
  247. void
  248. ICommGotAnswer(
  249. PThrdGlbl pTG
  250. )
  251. {
  252. BG_CHK(pTG->Inst.state == BEFORE_ANSWER);
  253. pTG->Inst.state = BEFORE_RECVCAPS;
  254. }
  255. BOOL ICommRecvCaps(PThrdGlbl pTG, LPBC lpBC)
  256. {
  257. USHORT uType;
  258. BOOL fRet = FALSE;
  259. #if 0
  260. BG_CHK(lpBC);
  261. BG_CHK(lpBC->bctype == RECV_CAPS);
  262. BG_CHK(lpBC->wTotalSize>=sizeof(BC));
  263. BG_CHK(lpBC->wTotalSize<=sizeof(pTG->Inst.RemoteRecvCaps));
  264. BG_CHK(pTG->Inst.fSending || pTG->Inst.fInPollReq);
  265. #endif
  266. if (pTG->fAbortRequested) {
  267. MyDebugPrint(pTG, LOG_ALL, "ICommRecvCaps. got ABORT at %ld", GetTickCount() );
  268. fRet = FALSE;
  269. goto mutexit;
  270. }
  271. if(pTG->Inst.fAbort) // recv caps
  272. {
  273. fRet = FALSE;
  274. goto mutexit;
  275. }
  276. if(pTG->Inst.state != BEFORE_RECVCAPS)
  277. {
  278. (MyDebugPrint(pTG, LOG_ALL, "<<WARNING>> Got caps unexpectedly--ignoring\r\n"));
  279. // this will break if we send EOM...
  280. // then we should go back into RECV_CAPS state
  281. fRet = TRUE;
  282. //RSL goto mutexit;
  283. }
  284. _fmemset(&pTG->Inst.RemoteRecvCaps, 0, sizeof(pTG->Inst.RemoteRecvCaps));
  285. _fmemcpy(&pTG->Inst.RemoteRecvCaps, lpBC, min(sizeof(pTG->Inst.RemoteRecvCaps), lpBC->wTotalSize));
  286. if(lpBC->Std.vMsgProtocol == 0) // not Msg Protocol must be G3
  287. uType = DEST_G3;
  288. else if(!lpBC->Std.fBinaryData) // vMsgProtocol != 0 && !Binary
  289. uType = DEST_IFAX;
  290. else
  291. uType = DEST_EFAX;
  292. #if 0 // RSL
  293. #ifdef USECAPI
  294. // update capabilities database.
  295. // Note: +++ assumes UpdateCapabilitiesEntry overhead is small...
  296. // If not, we'll have to do this after the call is over...
  297. {
  298. char szPhone[PHONENUMSIZE];
  299. BG_CHK(pTG->Inst.aCapsPhone);
  300. if (!GlobalGetAtomName(pTG->Inst.aCapsPhone, szPhone, sizeof(szPhone)))
  301. {BG_CHK(FALSE);}
  302. // +++ NYI First call normalizing function for phone...
  303. if (UpdateCapabilitiesEntry(szPhone,
  304. lpBC->wTotalSize,
  305. (LPBYTE) lpBC) != ERROR_SUCCESS)
  306. {
  307. (MyDebugPrint(pTG, LOG_ERR, SZMOD "<<ERROR>> Couldn't update remote caps\r\n"));
  308. }
  309. }
  310. #else // !USECAPI
  311. PostMessage(pTG->Inst.hwndSend, IF_FILET30_DESTTYPERES, pTG->Inst.aPhone,
  312. (LPARAM)MAKELONG(MAKEWORD(uType, lpBC->Fax.AwRes),
  313. MAKEWORD(lpBC->Fax.Encoding, lpBC->Std.vSecurity)));
  314. #endif // !USECAPI
  315. #ifdef POLLREQ
  316. if(pTG->Inst.fInPollReq)
  317. {
  318. BG_CHK(!pTG->Inst.fSending);
  319. fRet = DoPollReq(lpBC);
  320. goto mutexit;
  321. }
  322. #endif
  323. #ifdef TSK
  324. // must be before Negotiate caps
  325. if(!OpenSendFiles(pTG->Inst.aFileMG3, pTG->Inst.aFileIFX, pTG->Inst.aFileEFX))
  326. {
  327. faxTlog((SZMOD "Can't open Send Files\r\n"));
  328. SetFailureCode(T30FAILS_FILEOPEN);
  329. fRet = FALSE;
  330. goto mutexit;
  331. }
  332. #endif //TSK
  333. #endif // 0 RSL
  334. if(!NegotiateCaps(pTG))
  335. {
  336. _fmemset(&pTG->Inst.SendParams, 0, sizeof(pTG->Inst.SendParams));
  337. // SetFailureCode already called
  338. fRet = FALSE;
  339. goto mutexit;
  340. }
  341. ////////// Now done in the ICommGetBC callback ////////
  342. // if(pTG->Inst.uModemClass==FAXCLASS1 || pTG->Inst.uModemClass == FAXCLASS0)
  343. // {
  344. // LPFNCHK(lpfniET30ProtSetBC);
  345. // // Set Send Params
  346. // if(!lpfniET30ProtSetBC((LPBC)&pTG->Inst.SendParams, SEND_PARAMS))
  347. // {
  348. // // SetFailureCode already called
  349. // fRet = FALSE;
  350. // goto mutexit;
  351. // }
  352. // }
  353. // else
  354. ////////// Now done in the ICommGetBC callback ////////
  355. #if defined(CL2) || defined(CL2_0)
  356. ////////// Now done in the ICommGetBC callback ////////
  357. // if(pTG->Inst.uModemClass==FAXCLASS2 || pTG->Inst.uModemClass==FAXCLASS2_0)
  358. // {
  359. // LPFNCHK(lpfnClass2SetBC);
  360. // // Set CLASS2 Send Params
  361. // if(!lpfnClass2SetBC((LPBC)&pTG->Inst.SendParams, SEND_PARAMS))
  362. // {
  363. // // SetFailureCode already called
  364. // fRet = FALSE;
  365. // goto mutexit;
  366. // }
  367. // }
  368. ////////// Now done in the ICommGetBC callback ////////
  369. #endif //CL2
  370. pTG->Inst.state = SENDDATA_BETWEENPAGES;
  371. pTG->Inst.uPageAcks = 0;
  372. pTG->Inst.cbPage = -1;
  373. # ifdef CHK
  374. pTG->Inst.fRecvChecking = FALSE;
  375. # endif // CHK
  376. fRet = TRUE;
  377. mutexit:
  378. return fRet;
  379. return (fRet);
  380. }