/*++ Copyright (c) 1996 Microsoft Corporation Module Name: tx_thrd.c Abstract: This module implements MMR->MR and MMR->MH conversion in a separate thread. Author: Rafael Lisitsa (RafaelL) 14-Aug-1996 Revision History: --*/ #define USE_DEBUG_CONTEXT DEBUG_CONTEXT_T30_MAIN #include "prep.h" #include "efaxcb.h" #include "t30.h" #include "hdlc.h" #include "debug.h" #include "tiff.h" #include "glbproto.h" #include "t30gl.h" // Don't want to limit time to transmit page #define WAIT_FOR_NEXT_STRIP_TX_TIMEOUT INFINITE // Max size for converted page #define MAX_CONVERTED_SIZE 3000000 DWORD TiffConvertThread ( PThrdGlbl pTG ) { DWORD tiffCompression = pTG->TiffConvertThreadParams.tiffCompression; BOOL NegotHiRes = pTG->TiffConvertThreadParams.HiRes; BOOL SrcHiRes = pTG->SrcHiRes; char OutFileName[_MAX_FNAME]; HANDLE OutFileHandle; DWORD *lpdwOutputBuffer = NULL; DWORD dwBytesWritten; DWORD dwSizeOutputBuffer = 500000; DWORD dwUsedSizeOutputBuffer; DWORD StripDataSize; DWORD NumHandles=2; HANDLE HandlesArray[2]; DWORD WaitResult; DWORD RetCode = FALSE; BOOL fOutFileNeedsBeClosed = 0; BOOL fResScan = 0; DEBUG_FUNCTION_NAME(_T("TiffConvertThread")); HandlesArray[0] = pTG->AbortReqEvent; HandlesArray[1] = pTG->ThrdSignal; lpdwOutputBuffer = (DWORD *) VirtualAlloc( NULL, dwSizeOutputBuffer, MEM_COMMIT, PAGE_READWRITE ); if (! lpdwOutputBuffer) { DebugPrintEx(DEBUG_ERR, "lpdwOutputBuffer can't VirtualAlloc"); goto l_exit; } // // Set the appropriate PRTY for this thread // I/O threads run at 15. TIFF - at 9...11 // DebugPrintEx( DEBUG_MSG, "NegotHiRes=%d SrcHiRes=%d Started", NegotHiRes, SrcHiRes); if (! SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST) ) { DebugPrintEx( DEBUG_ERR, "SetThreadPriority HIGHEST failed le=%x", GetLastError() ); goto l_exit; } // need test below to make sure that pTG is still valid if (pTG->ReqTerminate) { goto l_exit; } // // TIFF file was already opened in FaxDevSendA // in order to get the YResolution tag to negotiate resolution. // pTG->CurrentOut = 1; // // loop thru all pages // do { pTG->fTiffPageDone = 0; _fmemcpy (OutFileName, gT30.TmpDirectory, gT30.dwLengthTmpDirectory); _fmemcpy (&OutFileName[gT30.dwLengthTmpDirectory], pTG->TiffConvertThreadParams.lpszLineID, 8); sprintf( &OutFileName[gT30.dwLengthTmpDirectory+8], ".%03d", pTG->CurrentOut); if ( ( OutFileHandle = CreateFileA( OutFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL) ) == INVALID_HANDLE_VALUE ) { DebugPrintEx( DEBUG_ERR, "ec: %lx CREATING file %s", GetLastError(), OutFileName); goto l_exit; } fOutFileNeedsBeClosed = 1; DebugPrintEx( DEBUG_MSG, "Page %d started", pTG->CurrentOut); if (! TiffSeekToPage( pTG->Inst.hfile, pTG->CurrentOut, FILLORDER_LSB2MSB ) ) { DebugPrintEx(DEBUG_ERR, "seeking to page"); goto l_exit; } else { DebugPrintEx(DEBUG_MSG, "TIFF_TX: Tiff seeking to page -OK"); } // // check the current page dimensions. Add memory if needed. // TiffGetCurrentPageData( pTG->Inst.hfile, NULL, &StripDataSize, NULL, NULL ); if (StripDataSize > 1500000) { DebugPrintEx( DEBUG_ERR, "Tiff CONVERTING %d page StripSize = %d", pTG->CurrentOut, StripDataSize); goto l_exit; } // convert-reallocate loop do { dwUsedSizeOutputBuffer = dwSizeOutputBuffer; if (tiffCompression == TIFF_COMPRESSION_MR) { if (NegotHiRes == SrcHiRes) { fResScan = ConvMmrPageToMrSameRes ( pTG->Inst.hfile, lpdwOutputBuffer, &dwUsedSizeOutputBuffer, NegotHiRes); } else { fResScan = ConvMmrPageHiResToMrLoRes ( pTG->Inst.hfile, lpdwOutputBuffer, &dwUsedSizeOutputBuffer); } } else { fResScan = ConvMmrPageToMh ( pTG->Inst.hfile, lpdwOutputBuffer, &dwUsedSizeOutputBuffer, NegotHiRes, SrcHiRes); } if (!fResScan) { DWORD dwLastError = GetLastError(); if ((dwLastError==ERROR_INSUFFICIENT_BUFFER) && (dwSizeOutputBuffer < MAX_CONVERTED_SIZE)) { // Buffer was too small, reallocate bigger buffer if (!VirtualFree(lpdwOutputBuffer, 0 , MEM_RELEASE)) { DebugPrintEx(DEBUG_ERR, "VirtualFree failed, LE=%d", GetLastError()); goto l_exit; } lpdwOutputBuffer = NULL; dwSizeOutputBuffer += 500000; DebugPrintEx(DEBUG_MSG, "CONVERTING %d page, LE=%d, reallocating %d bytes", pTG->CurrentOut, dwLastError, dwSizeOutputBuffer); lpdwOutputBuffer = (DWORD *) VirtualAlloc( NULL, dwSizeOutputBuffer, MEM_COMMIT, PAGE_READWRITE ); if (! lpdwOutputBuffer) { DebugPrintEx( DEBUG_ERR, "lpdwOutputBuffer can't VirtualAlloc %d", dwSizeOutputBuffer); goto l_exit; } } else { DebugPrintEx(DEBUG_ERR, "CONVERTING %d page, LE=%d", pTG->CurrentOut, dwLastError); goto l_exit; } } } while (!fResScan); if ( ( ! WriteFile(OutFileHandle, (BYTE *) lpdwOutputBuffer, dwUsedSizeOutputBuffer, &dwBytesWritten, NULL) ) || (dwUsedSizeOutputBuffer != dwBytesWritten ) ) { DebugPrintEx(DEBUG_ERR, "Tiff writing file %s", OutFileName); goto l_exit; } if ( ! CloseHandle(OutFileHandle) ) { fOutFileNeedsBeClosed = 0; DebugPrintEx(DEBUG_ERR, "Tiff closing file %s", OutFileName); goto l_exit; } fOutFileNeedsBeClosed = 0; pTG->fTiffPageDone = 1; if (!SetEvent(pTG->FirstPageReadyTxSignal)) { DebugPrintEx( DEBUG_ERR, "SetEvent(0x%lx) returns failure code: %ld", (ULONG_PTR)pTG->FirstPageReadyTxSignal, (long) GetLastError()); RetCode = FALSE; goto l_exit; } DebugPrintEx( DEBUG_MSG, "Done page %d size=%d", pTG->CurrentOut, dwUsedSizeOutputBuffer); if (!pTG->FirstOut) { pTG->FirstOut = 1; } pTG->LastOut++; // // check to see if we are done // if (pTG->LastOut >= pTG->TiffInfo.PageCount) { DebugPrintEx( DEBUG_MSG, "Done whole document Last page %d size=%d", pTG->CurrentOut, dwUsedSizeOutputBuffer); pTG->fTiffDocumentDone = 1; goto good_exit; } // // we want to maintain 2 pages ahead // if (pTG->LastOut - pTG->CurrentIn >= 2) { WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, WAIT_FOR_NEXT_STRIP_TX_TIMEOUT); if (WaitResult == WAIT_TIMEOUT) { DebugPrintEx(DEBUG_ERR, "WaitForMultipleObjects TIMEOUT"); goto l_exit; } if (WaitResult == WAIT_FAILED) { DebugPrintEx( DEBUG_ERR, "WaitForMultipleObjects FAILED le=%lx", GetLastError()); } if (pTG->ReqTerminate) { DebugPrintEx(DEBUG_MSG,"Received TERMINATE request"); goto good_exit; } else if (pTG->ReqStartNewPage) { DebugPrintEx(DEBUG_MSG,"Received START NEW PAGE request"); pTG->AckStartNewPage = 1; pTG->ReqStartNewPage = 0; } else { DebugPrintEx(DEBUG_ERR,"Received WRONG request"); WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, WAIT_FOR_NEXT_STRIP_TX_TIMEOUT); if (WaitResult == WAIT_TIMEOUT) { DebugPrintEx(DEBUG_ERR,"WaitForMultipleObjects TIMEOUT"); goto l_exit; } if (WaitResult == WAIT_FAILED) { DebugPrintEx( DEBUG_ERR, "WaitForMultipleObjects FAILED le=%lx", GetLastError()); } } } pTG->CurrentOut++; DebugPrintEx(DEBUG_MSG,"Start page %d", pTG->CurrentOut); } while (1); good_exit: if (pTG->fTiffOpenOrCreated) { TiffClose( pTG->Inst.hfile); pTG->fTiffOpenOrCreated = 0; } RetCode = TRUE; l_exit: if (fOutFileNeedsBeClosed) { CloseHandle(OutFileHandle); } if (lpdwOutputBuffer) { VirtualFree(lpdwOutputBuffer, 0 , MEM_RELEASE); // Nothing to do if it fails... lpdwOutputBuffer = NULL; } pTG->AckTerminate = 1; pTG->fOkToResetAbortReqEvent = 1; if (!SetEvent(pTG->ThrdAckTerminateSignal)) { DebugPrintEx( DEBUG_ERR, "SetEvent(0x%lx) returns failure code: %ld", (ULONG_PTR)pTG->ThrdAckTerminateSignal, (long) GetLastError()); RetCode = FALSE; } if (!SetEvent(pTG->FirstPageReadyTxSignal)) { DebugPrintEx( DEBUG_ERR, "SetEvent(0x%lx) returns failure code: %ld", (ULONG_PTR)pTG->FirstPageReadyTxSignal, (long) GetLastError()); RetCode = FALSE; } DebugPrintEx(DEBUG_MSG,"EXITs"); return (RetCode); }