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.

672 lines
23 KiB

  1. /***************************************************************************
  2. Name : RECV.C
  3. Comment : Receiver functions
  4. Revision Log
  5. Date Name Description
  6. -------- ----- ---------------------------------------------------------
  7. ***************************************************************************/
  8. #define USE_DEBUG_CONTEXT DEBUG_CONTEXT_T30_MAIN
  9. #include "prep.h"
  10. #include <comdevi.h>
  11. #include "efaxcb.h"
  12. #include "glbproto.h"
  13. #include "t30gl.h"
  14. // for TIFF_SCAN_SEG_END
  15. #include "..\..\..\tiff\src\fasttiff.h"
  16. #include "psslog.h"
  17. #define FILE_ID FILE_ID_RECV
  18. BOOL ICommRecvParams(PThrdGlbl pTG, LPBC lpBC)
  19. {
  20. BOOL fRet = FALSE;
  21. DEBUG_FUNCTION_NAME(_T("ICommRecvParams"));
  22. if (pTG->fAbortRequested)
  23. {
  24. DebugPrintEx(DEBUG_MSG, "got ABORT");
  25. fRet = FALSE;
  26. goto mutexit;
  27. }
  28. if(pTG->Inst.state != BEFORE_RECVPARAMS)
  29. {
  30. // this will break if we send EOM...
  31. // then we should go back into RECV_CAPS state
  32. fRet = TRUE;
  33. goto mutexit;
  34. }
  35. _fmemset(&pTG->Inst.RecvParams, 0, sizeof(pTG->Inst.RecvParams));
  36. _fmemcpy(&pTG->Inst.RecvParams, lpBC, min(sizeof(pTG->Inst.RecvParams), lpBC->wTotalSize));
  37. pTG->Inst.state = RECVDATA_BETWEENPAGES;
  38. fRet = TRUE;
  39. // fall through
  40. mutexit:
  41. return fRet;
  42. }
  43. BOOL ICommInitTiffThread(PThrdGlbl pTG)
  44. {
  45. USHORT uEnc;
  46. DWORD TiffConvertThreadId;
  47. DEBUG_FUNCTION_NAME(_T("ICommInitTiffThread"));
  48. if (pTG->ModemClass != MODEM_CLASS1)
  49. {
  50. if (pTG->Encoding & MR_DATA)
  51. {
  52. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MR;
  53. }
  54. else
  55. {
  56. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MH;
  57. }
  58. if (pTG->Resolution & (AWRES_mm080_077 | AWRES_200_200) )
  59. {
  60. pTG->TiffConvertThreadParams.HiRes = 1;
  61. }
  62. else
  63. {
  64. pTG->TiffConvertThreadParams.HiRes = 0;
  65. }
  66. }
  67. else
  68. {
  69. uEnc = pTG->ProtInst.RecvParams.Fax.Encoding;
  70. if (uEnc == MR_DATA)
  71. {
  72. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MR;
  73. }
  74. else
  75. {
  76. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MH;
  77. }
  78. if (pTG->ProtInst.RecvParams.Fax.AwRes & (AWRES_mm080_077 | AWRES_200_200) )
  79. {
  80. pTG->TiffConvertThreadParams.HiRes = 1;
  81. }
  82. else
  83. {
  84. pTG->TiffConvertThreadParams.HiRes = 0;
  85. }
  86. }
  87. if (!pTG->fTiffThreadCreated)
  88. {
  89. _fmemcpy (pTG->TiffConvertThreadParams.lpszLineID, pTG->lpszPermanentLineID, 8);
  90. pTG->TiffConvertThreadParams.lpszLineID[8] = 0;
  91. DebugPrintEx( DEBUG_MSG,
  92. "Creating TIFF helper thread comp=%d res=%d",
  93. pTG->TiffConvertThreadParams.tiffCompression,
  94. pTG->TiffConvertThreadParams.HiRes);
  95. pTG->hThread = CreateThread(
  96. NULL,
  97. 0,
  98. (LPTHREAD_START_ROUTINE) PageAckThread,
  99. (LPVOID) pTG,
  100. 0,
  101. &TiffConvertThreadId
  102. );
  103. if (!pTG->hThread)
  104. {
  105. DebugPrintEx(DEBUG_ERR,"TiffConvertThread create FAILED");
  106. return FALSE;
  107. }
  108. pTG->fTiffThreadCreated = 1;
  109. pTG->AckTerminate = 0;
  110. pTG->fOkToResetAbortReqEvent = 0;
  111. if ( (pTG->RecoveryIndex >=0 ) && (pTG->RecoveryIndex < MAX_T30_CONNECT) )
  112. {
  113. T30Recovery[pTG->RecoveryIndex].TiffThreadId = TiffConvertThreadId;
  114. T30Recovery[pTG->RecoveryIndex].CkSum = ComputeCheckSum(
  115. (LPDWORD) &T30Recovery[pTG->RecoveryIndex].fAvail,
  116. sizeof ( T30_RECOVERY_GLOB ) / sizeof (DWORD) - 1 );
  117. }
  118. }
  119. return TRUE;
  120. }
  121. #define CLOSE_IN_FILE_HANDLE \
  122. if (pTG->InFileHandleNeedsBeClosed) \
  123. { \
  124. CloseHandle(pTG->InFileHandle); \
  125. pTG->InFileHandleNeedsBeClosed = 0; \
  126. }
  127. BOOL ICommPutRecvBuf(PThrdGlbl pTG, LPBUFFER lpbf, SLONG slOffset)
  128. {
  129. /**
  130. slOffset == RECV_STARTPAGE marks beginning of new block *and* page
  131. slOffset == RECV_ENDPAGE marks end of page
  132. slOffset == RECV_ENDDOC marks end of document (close file etc.)
  133. slOffset == RECV_ENDDOC_FORCESAVE marks end of document (close file etc.), but
  134. current RX file will be written to TIF file,
  135. whether it's bad or not. PhaseNodeF uses this
  136. option before returning actionHANGUP, because
  137. there will be no chance to send RTN, so it's
  138. better to keep part of the last page than to lose it.
  139. (for all above no data supplied -- i.e lpbf == 0)
  140. slOffset == RECV_SEQ means put buffer at current file position
  141. slOffset == RECV_FLUSH means flush RX file buffers
  142. slOffset >= 0 gives the offset in bytes from the last marked
  143. position (beginning of block) to put buffer
  144. **/
  145. BOOL fRet = TRUE;
  146. DWORD BytesWritten;
  147. DWORD NumHandles=2;
  148. HANDLE HandlesArray[2];
  149. DWORD WaitResult = WAIT_TIMEOUT;
  150. DEBUG_FUNCTION_NAME(_T("ICommPutRecvBuf"));
  151. HandlesArray[0] = pTG->AbortReqEvent;
  152. switch (slOffset)
  153. {
  154. case RECV_STARTPAGE:
  155. DebugPrintEx(DEBUG_MSG,"called. Reason: RECV_STARTPAGE");
  156. break;
  157. case RECV_ENDPAGE:
  158. DebugPrintEx(DEBUG_MSG,"called. Reason: RECV_ENDPAGE");
  159. break;
  160. case RECV_ENDDOC:
  161. DebugPrintEx(DEBUG_MSG,"called. Reason: RECV_ENDDOC");
  162. break;
  163. case RECV_ENDDOC_FORCESAVE:
  164. DebugPrintEx(DEBUG_MSG,"called. Reason: RECV_ENDDOC_FORCESAVE");
  165. break;
  166. default:
  167. break;
  168. }
  169. if(slOffset==RECV_ENDPAGE || slOffset==RECV_ENDDOC || slOffset==RECV_ENDDOC_FORCESAVE)
  170. {
  171. BOOL fPageIsBadOrig;
  172. //here we need to wait until helper thread finishes with the page
  173. if (! pTG->fPageIsBad)
  174. {
  175. DebugPrintEx( DEBUG_MSG,
  176. "EOP. Not bad yet. Start waiting for Rx_thrd to finish");
  177. HandlesArray[1] = pTG->ThrdDoneSignal;
  178. WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, RX_ACK_THRD_TIMEOUT);
  179. if ( WAIT_FAILED == WaitResult)
  180. {
  181. pTG->fPageIsBad = 1;
  182. DebugPrintEx( DEBUG_ERR,
  183. "EOP. While trying to wait for RX thrd, Wait failed "
  184. "Last error was %d ABORTING!" ,
  185. GetLastError());
  186. CLOSE_IN_FILE_HANDLE;
  187. return FALSE; // There is no reason to continue trying to receive this fax
  188. }
  189. else if (WAIT_TIMEOUT == WaitResult)
  190. {
  191. pTG->fPageIsBad = 1;
  192. DebugPrintEx(DEBUG_ERR,"EOP. TimeOut, never waked up by Rx_thrd");
  193. }
  194. else if (WAIT_OBJECT_0 == WaitResult)
  195. {
  196. DebugPrintEx(DEBUG_MSG,"wait for next page ABORTED");
  197. CLOSE_IN_FILE_HANDLE;
  198. return FALSE;
  199. }
  200. else
  201. {
  202. DebugPrintEx(DEBUG_MSG,"EOP. Waked up by Rx_thrd");
  203. }
  204. }
  205. //
  206. // In some cases, we want to save bad pages too
  207. //
  208. fPageIsBadOrig = pTG->fPageIsBad;
  209. pTG->fPageIsBadOverride = FALSE;
  210. if (slOffset==RECV_ENDDOC_FORCESAVE)
  211. {
  212. if (pTG->fPageIsBad)
  213. {
  214. pTG->fPageIsBadOverride = TRUE;
  215. DebugPrintEx(DEBUG_MSG, "Overriding fPageIsBad (1->0) because of RECV_ENDDOC_FORCESAVE");
  216. }
  217. pTG->fPageIsBad = 0;
  218. }
  219. else if (pTG->ModemClass==MODEM_CLASS2_0)
  220. {
  221. pTG->fPageIsBad = (pTG->FPTSreport != 1);
  222. if (fPageIsBadOrig != pTG->fPageIsBad)
  223. {
  224. pTG->fPageIsBadOverride = TRUE;
  225. DebugPrintEx(DEBUG_MSG, "Overriding fPageIsBad (%d->%d) because of class 2.0",
  226. fPageIsBadOrig, pTG->fPageIsBad);
  227. }
  228. }
  229. // PSSlog page quality
  230. if (fPageIsBadOrig) // Log according to our actual quality assessment
  231. {
  232. PSSLogEntry(PSS_WRN, 1, "Page %2d was bad (%4d good lines,%4d bad lines%s%s)",
  233. pTG->PageCount+1, pTG->Lines, pTG->BadFaxLines,
  234. (pTG->iResScan==TIFF_SCAN_SEG_END) ? ", didn't find RTC" : "",
  235. (pTG->fPageIsBadOverride) ? ", saved for potential recovery" : "");
  236. }
  237. else
  238. {
  239. PSSLogEntry(PSS_MSG, 1, "Page %2d was good (%4d good lines,%4d bad lines)",
  240. pTG->PageCount+1, pTG->Lines, pTG->BadFaxLines);
  241. }
  242. //
  243. // If page is good then write it to a TIFF file.
  244. //
  245. if (! pTG->fPageIsBad)
  246. {
  247. LPCHAR lpBuffer=NULL;
  248. BOOL fEof=FALSE;
  249. DWORD dwBytesToRead;
  250. DWORD dwBytesHaveRead;
  251. DWORD dwBytesLeft;
  252. if ( ! TiffStartPage( pTG->Inst.hfile ) )
  253. {
  254. DebugPrintEx(DEBUG_ERR,"TiffStartPage failed");
  255. CLOSE_IN_FILE_HANDLE;
  256. return FALSE;
  257. }
  258. // Go to the begining of the RX file
  259. if ( SetFilePointer(pTG->InFileHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER )
  260. {
  261. DebugPrintEx( DEBUG_ERR,
  262. "SetFilePointer failed le=%ld",
  263. GetLastError() );
  264. CLOSE_IN_FILE_HANDLE;
  265. return FALSE;
  266. }
  267. lpBuffer = MemAlloc(DECODE_BUFFER_SIZE);
  268. if (!lpBuffer)
  269. {
  270. DebugPrintEx(DEBUG_ERR, "MemAlloc failed");
  271. CLOSE_IN_FILE_HANDLE;
  272. return FALSE;
  273. }
  274. fEof = 0;
  275. dwBytesLeft = pTG->BytesIn;
  276. while (! fEof)
  277. {
  278. if (dwBytesLeft <= DECODE_BUFFER_SIZE)
  279. {
  280. dwBytesToRead = dwBytesLeft;
  281. fEof = 1;
  282. }
  283. else
  284. {
  285. dwBytesToRead = DECODE_BUFFER_SIZE;
  286. dwBytesLeft -= DECODE_BUFFER_SIZE;
  287. }
  288. if (! ReadFile(pTG->InFileHandle, lpBuffer, dwBytesToRead, &dwBytesHaveRead, NULL ) )
  289. {
  290. DebugPrintEx( DEBUG_ERR,
  291. "ReadFile failed le=%ld",
  292. GetLastError() );
  293. fRet=FALSE;
  294. break;
  295. }
  296. if (dwBytesToRead != dwBytesHaveRead)
  297. {
  298. DebugPrintEx( DEBUG_ERR,
  299. "ReadFile have read=%d wanted=%d",
  300. dwBytesHaveRead,
  301. dwBytesToRead);
  302. fRet=FALSE;
  303. break;
  304. }
  305. if (! TiffWriteRaw( pTG->Inst.hfile, lpBuffer, dwBytesToRead ) )
  306. {
  307. DebugPrintEx(DEBUG_ERR,"TiffWriteRaw failed");
  308. fRet=FALSE;
  309. break;
  310. }
  311. DebugPrintEx(DEBUG_MSG,"TiffWriteRaw done");
  312. }
  313. MemFree(lpBuffer);
  314. if (!fRet)
  315. {
  316. CLOSE_IN_FILE_HANDLE;
  317. return FALSE;
  318. }
  319. pTG->PageCount++;
  320. DebugPrintEx( DEBUG_MSG,
  321. "Calling TiffEndPage page=%d bytes=%d",
  322. pTG->PageCount,
  323. pTG->BytesIn);
  324. if (!TiffSetCurrentPageParams(pTG->Inst.hfile,
  325. pTG->TiffInfo.CompressionType,
  326. pTG->TiffInfo.ImageWidth,
  327. FILLORDER_LSB2MSB,
  328. pTG->TiffInfo.YResolution) )
  329. {
  330. DebugPrintEx(DEBUG_ERR,"TiffSetCurrentPageParams failed");
  331. }
  332. if (! TiffEndPage( pTG->Inst.hfile ) )
  333. {
  334. DebugPrintEx(DEBUG_ERR,"TiffEndPage failed");
  335. CLOSE_IN_FILE_HANDLE;
  336. return FALSE;
  337. }
  338. }
  339. CLOSE_IN_FILE_HANDLE;
  340. // This change solve bug #4925:
  341. // "FAX: T30: If Fax server receives bad page as last page, then fax information (all pages) is lost"
  342. // t-jonb: If we're at the last page (=received EOP), but page was found to be bad,
  343. // NonECMRecvPhaseD will call here with RECV_ENDDOC, send RTN, and proceed to receive
  344. // the page again. Therefore, we don't want to close the TIF or terminate rx_thrd.
  345. // OTOH, if we're called with RECV_ENDDOC_FORCESAVE, it means we're about to hangup,
  346. // and should therefore close the TIF and terminate rx_thrd.
  347. if ((slOffset==RECV_ENDDOC && !pTG->fPageIsBad) || (slOffset == RECV_ENDDOC_FORCESAVE))
  348. {
  349. if ( pTG->fTiffOpenOrCreated )
  350. {
  351. DebugPrintEx(DEBUG_MSG,"Actually calling TiffClose");
  352. TiffClose( pTG->Inst.hfile );
  353. pTG->fTiffOpenOrCreated = 0;
  354. }
  355. // request Rx_thrd to terminate itself.
  356. pTG->ReqTerminate = 1;
  357. if (!SetEvent(pTG->ThrdSignal))
  358. {
  359. DebugPrintEx( DEBUG_ERR,
  360. "SetEvent(0x%lx) returns failure code: %ld",
  361. (ULONG_PTR)pTG->ThrdSignal,
  362. (long) GetLastError());
  363. return FALSE;
  364. }
  365. pTG->Inst.state = BEFORE_RECVPARAMS;
  366. }
  367. else
  368. {
  369. pTG->Inst.state = RECVDATA_BETWEENPAGES;
  370. }
  371. }
  372. else if(slOffset == RECV_STARTPAGE)
  373. {
  374. // Fax Server wants to know when we start RX new page
  375. SignalStatusChange(pTG, FS_RECEIVING);
  376. pTG->Inst.state = RECVDATA_PHASE;
  377. // start Helper thread once per session
  378. // re-set the resolution and encoding params
  379. if (!ICommInitTiffThread(pTG))
  380. return FALSE;
  381. _fmemcpy (pTG->InFileName, gT30.TmpDirectory, gT30.dwLengthTmpDirectory);
  382. _fmemcpy (&pTG->InFileName[gT30.dwLengthTmpDirectory], pTG->TiffConvertThreadParams.lpszLineID, 8);
  383. strcpy (&pTG->InFileName[gT30.dwLengthTmpDirectory+8], ".RX");
  384. // We can't delete the file if the handle for the file is in use by the TIFF helper thread or
  385. // is open by this function.
  386. if (pTG->InFileHandleNeedsBeClosed)
  387. {
  388. DebugPrintEx( DEBUG_WRN,
  389. "RECV_STARTPAGE: The InFileHandle is still open,"
  390. " trying CloseHandle." );
  391. // We have open the file but never close it. Scenario for that: We get ready to get the page into
  392. // *.RX file. We got EOF and go to NodeF. Instead of getting after page cmd (EOP or MPS) we get TCF.
  393. // Finally, we get ready for the page, but the handle is open.
  394. // Till now the handle was closed when we call this function with RECV_ENDPAGE or RECV_ENDDOC
  395. if (!CloseHandle(pTG->InFileHandle))
  396. {
  397. DebugPrintEx( DEBUG_ERR,
  398. "CloseHandle FAILED le=%lx",
  399. GetLastError() );
  400. }
  401. }
  402. if (!DeleteFileA(pTG->InFileName))
  403. {
  404. DWORD lastError = GetLastError();
  405. DebugPrintEx( DEBUG_WRN,
  406. "DeleteFile %s FAILED le=%lx",
  407. pTG->InFileName,
  408. lastError);
  409. if (ERROR_SHARING_VIOLATION == lastError)
  410. { // If the problem is that the rx_thread have an open handle to *.RX file then:
  411. // Lets try to wait till the thread will close that handle
  412. // When the thread close the handle of the *.RX file, he will signal on ThrdDoneSignal event
  413. // usually RECV_ENDPAGE or RECV_ENDDOC wait for the rx_thread to finish.
  414. HandlesArray[1] = pTG->ThrdDoneSignal;
  415. if ( ( WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, RX_ACK_THRD_TIMEOUT) ) == WAIT_TIMEOUT)
  416. {
  417. DebugPrintEx( DEBUG_ERR,
  418. "RECV_STARTPAGE. Never waked up by Rx_thrd");
  419. }
  420. else
  421. {
  422. DebugPrintEx( DEBUG_MSG,
  423. "RECV_STARTPAGE. Waked up by Rx_thrd or by abort");
  424. }
  425. // Anyhow - try to delete again the file
  426. if (!DeleteFileA(pTG->InFileName))
  427. {
  428. DebugPrintEx( DEBUG_ERR,
  429. "DeleteFile %s FAILED le=%lx",
  430. pTG->InFileName,
  431. GetLastError() );
  432. return FALSE;
  433. }
  434. }
  435. }
  436. if ( ( pTG->InFileHandle = CreateFileA(pTG->InFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ,
  437. NULL, OPEN_ALWAYS, 0, NULL) ) == INVALID_HANDLE_VALUE )
  438. {
  439. DebugPrintEx( DEBUG_ERR,
  440. "Create file %s FAILED le=%lx",
  441. pTG->InFileName,
  442. GetLastError() );
  443. return FALSE;
  444. }
  445. pTG->InFileHandleNeedsBeClosed = 1;
  446. // Reset control data for the new page ack, interface
  447. pTG->fLastReadBlock = 0;
  448. pTG->BytesInNotFlushed = 0;
  449. pTG->BytesIn = 0;
  450. pTG->BytesOut = 0;
  451. pTG->fPageIsBad = 0;
  452. pTG->iResScan = 0;
  453. pTG->Lines = 0;
  454. pTG->BadFaxLines = 0;
  455. pTG->ConsecBadLines = 0;
  456. if (!ResetEvent(pTG->ThrdDoneSignal))
  457. {
  458. DebugPrintEx( DEBUG_ERR,
  459. "ResetEvent(0x%lx) returns failure code: %ld",
  460. (ULONG_PTR)pTG->ThrdDoneSignal,
  461. (long) GetLastError());
  462. // this is bad but not fatal yet.
  463. // try to get the page anyway...
  464. }
  465. }
  466. else if(slOffset >= 0)
  467. {
  468. MyFreeBuf(pTG, lpbf);
  469. }
  470. else if (slOffset == RECV_FLUSH)
  471. {
  472. if (! FlushFileBuffers (pTG->InFileHandle ) )
  473. {
  474. DebugPrintEx( DEBUG_ERR,
  475. "FlushFileBuffers FAILED LE=%lx",
  476. GetLastError());
  477. return FALSE;
  478. }
  479. DebugPrintEx(DEBUG_MSG,"ThrdSignal FLUSH");
  480. pTG->BytesIn = pTG->BytesInNotFlushed;
  481. if (! pTG->fPageIsBad)
  482. {
  483. if (!SetEvent(pTG->ThrdSignal))
  484. {
  485. DebugPrintEx( DEBUG_ERR,
  486. "SetEvent(0x%lx) returns failure code: %ld",
  487. (ULONG_PTR)pTG->ThrdSignal,
  488. (long) GetLastError());
  489. return FALSE;
  490. }
  491. }
  492. return TRUE;
  493. }
  494. else // if(slOffset == RECV_SEQ)
  495. {
  496. DebugPrintEx( DEBUG_MSG,
  497. "Write RAW Page ptr=%x; len=%d",
  498. lpbf->lpbBegData,
  499. lpbf->wLengthData);
  500. if ( ! WriteFile( pTG->InFileHandle, lpbf->lpbBegData, lpbf->wLengthData, &BytesWritten, NULL ) )
  501. {
  502. DebugPrintEx( DEBUG_ERR,
  503. "WriteFile FAILED %s ptr=%x; len=%d LE=%d",
  504. pTG->InFileName,
  505. lpbf->lpbBegData,
  506. lpbf->wLengthData,
  507. GetLastError());
  508. return FALSE;
  509. }
  510. if (BytesWritten != lpbf->wLengthData)
  511. {
  512. DebugPrintEx( DEBUG_ERR,
  513. "WriteFile %s written ONLY %d ptr=%x; len=%d LE=%d",
  514. pTG->InFileName,
  515. BytesWritten,
  516. lpbf->lpbBegData,
  517. lpbf->wLengthData,
  518. GetLastError());
  519. fRet = FALSE;
  520. return fRet;
  521. }
  522. pTG->BytesInNotFlushed += BytesWritten;
  523. // control helper thread
  524. if ( (!pTG->fTiffThreadRunning) || (pTG->fLastReadBlock) )
  525. {
  526. if ( (pTG->BytesInNotFlushed - pTG->BytesOut > DECODE_BUFFER_SIZE) || (pTG->fLastReadBlock) )
  527. {
  528. if (! FlushFileBuffers (pTG->InFileHandle ) )
  529. {
  530. DebugPrintEx( DEBUG_ERR,
  531. "FlushFileBuffers FAILED LE=%lx",
  532. GetLastError());
  533. fRet = FALSE;
  534. return fRet;
  535. }
  536. pTG->BytesIn = pTG->BytesInNotFlushed;
  537. if (! pTG->fPageIsBad)
  538. {
  539. DebugPrintEx(DEBUG_MSG,"ThrdSignal");
  540. if (!SetEvent(pTG->ThrdSignal))
  541. {
  542. DebugPrintEx( DEBUG_ERR,
  543. "SetEvent(0x%lx) returns failure code: %ld",
  544. (ULONG_PTR)pTG->ThrdSignal,
  545. (long) GetLastError());
  546. return FALSE;
  547. }
  548. }
  549. }
  550. }
  551. MyFreeBuf(pTG, lpbf);
  552. }
  553. fRet = TRUE;
  554. return fRet;
  555. }
  556. LPBC ICommGetBC(PThrdGlbl pTG, BCTYPE bctype)
  557. {
  558. LPBC lpbc = NULL;
  559. if(bctype == SEND_CAPS)
  560. {
  561. lpbc = (LPBC)&pTG->Inst.SendCaps;
  562. }
  563. else
  564. {
  565. lpbc = (LPBC)(&(pTG->Inst.SendParams));
  566. // in cases where DIS is received again after sending DCS-TCF,
  567. // this gets called multiple times & we need to return the same
  568. // SendParams BC each time
  569. }
  570. return lpbc;
  571. }