Files
WindowsXP/printscan/fax/provider/t30/main/tx_thrd.c
2025-04-27 07:49:33 -04:00

441 lines
13 KiB
C

/*++
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:
--*/
#include "prep.h"
#include "efaxcb.h"
#include "t30.h"
#include "hdlc.h"
#include "debug.h"
#include "tiff.h"
#include "glbproto.h"
#include "t30gl.h"
// 10 min.
#define WAIT_FOR_NEXT_STRIP_TX_TIMEOUT 600000
DWORD
TiffConvertThreadSafe(
PThrdGlbl pTG
)
{
DWORD RetCode;
if (glT30Safe) {
__try {
RetCode = TiffConvertThread(pTG);
} __except (EXCEPTION_EXECUTE_HANDLER) {
//
// Signal to the Main T.30 Thread that we crashed
//
return (FALSE);
}
}
else {
RetCode = TiffConvertThread(pTG);
}
return (RetCode);
}
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;
DWORD dwBytesWritten;
DWORD dwSizeOutputBuffer = 500000;
DWORD dwUsedSizeOutputBuffer;
DWORD MaxNeedOutSize;
DWORD StripDataSize;
DWORD NumHandles=2;
HANDLE HandlesArray[2];
DWORD WaitResult;
DWORD RetCode = FALSE;
BOOL fOutFileNeedsBeClosed = 0;
BOOL fOutBufferNeedsBeFreed = 0;
HandlesArray[0] = pTG->AbortReqEvent;
HandlesArray[1] = pTG->ThrdSignal;
lpdwOutputBuffer = (DWORD *) VirtualAlloc(
NULL,
dwSizeOutputBuffer,
MEM_COMMIT,
PAGE_READWRITE
);
if (! lpdwOutputBuffer) {
MyDebugPrint(pTG, LOG_ERR, "ERROR TIFF_TX: lpdwOutputBuffer can'r VirtualAlloc \n");
SignalHelperError(pTG);
goto l_exit;
}
fOutBufferNeedsBeFreed = 1;
//
// Set the appropriate PRTY for this thread
// I/O threads run at 15. TIFF - at 9...11
//
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: NegotHiRes=%d SrcHiRes=%d Started at %ld \n",
NegotHiRes, SrcHiRes, GetTickCount() );
if (! SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST) ) {
MyDebugPrint(pTG, LOG_ERR, "ERROR TIFF_TX: SetThreadPriority HIGHEST failed le=%x \n", GetLastError() );
SignalHelperError(pTG);
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, OPEN_ALWAYS, 0, NULL) ) == INVALID_HANDLE_VALUE ) {
MyDebugPrint(pTG, LOG_ERR, "TIFF_TX: ERROR: %lx CREATING file %s \n", GetLastError(), OutFileName);
SignalHelperError(pTG);
goto l_exit;
}
fOutFileNeedsBeClosed = 1;
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: Page %d started at %ld\n", pTG->CurrentOut, GetTickCount() );
if (! TiffSeekToPage( (HANDLE) pTG->Inst.hfile, pTG->CurrentOut, FILLORDER_LSB2MSB ) ) {
MyDebugPrint(pTG, LOG_ERR, "ERROR: seeking to page \n");
SignalHelperError(pTG);
goto l_exit;
}
else {
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: Tiff seeking to page -OK time=%ld\n", GetTickCount() );
}
__try {
#if 0
if (glSimulateError && (glSimulateErrorType == SIMULATE_ERROR_TX_TIFF) ) {
SimulateError( EXCEPTION_ACCESS_VIOLATION);
}
#endif
//
// check the current page dimensions. Add memory if needed.
//
TiffGetCurrentPageData( (HANDLE) pTG->Inst.hfile,
NULL,
&StripDataSize,
NULL,
NULL
);
if ( (StripDataSize < 0) || (StripDataSize > 1500000) ) {
MyDebugPrint(pTG, LOG_ERR, "ERROR: Tiff CONVERTING %d page StripSize = %d \n", pTG->CurrentOut, StripDataSize);
SignalHelperError(pTG);
goto l_exit;
}
if (tiffCompression == TIFF_COMPRESSION_MR) {
MaxNeedOutSize = StripDataSize * 3 / 2;
}
else {
MaxNeedOutSize = StripDataSize * 2;
}
if (MaxNeedOutSize > dwSizeOutputBuffer) {
if (MaxNeedOutSize > 1000000) {
dwSizeOutputBuffer = 1500000;
}
else {
dwSizeOutputBuffer = 1000000;
}
VirtualFree(lpdwOutputBuffer, 0 , MEM_RELEASE);
lpdwOutputBuffer = (DWORD *) VirtualAlloc(
NULL,
dwSizeOutputBuffer,
MEM_COMMIT,
PAGE_READWRITE
);
if (! lpdwOutputBuffer) {
MyDebugPrint(pTG, LOG_ERR, "ERROR TIFF_TX: lpdwOutputBuffer can't VirtualAlloc %d \n", dwSizeOutputBuffer);
SignalHelperError(pTG);
goto l_exit;
}
fOutBufferNeedsBeFreed = 1;
}
dwUsedSizeOutputBuffer = dwSizeOutputBuffer;
if (tiffCompression == TIFF_COMPRESSION_MR) {
if (NegotHiRes == SrcHiRes) {
if (! ConvMmrPageToMrSameRes ( (HANDLE) pTG->Inst.hfile,
lpdwOutputBuffer,
&dwUsedSizeOutputBuffer,
NegotHiRes) ) {
MyDebugPrint(pTG, LOG_ERR, "ERROR: Tiff CONVERTING %d page \n", pTG->CurrentOut);
SignalHelperError(pTG);
goto l_exit;
}
}
else {
if (! ConvMmrPageHiResToMrLoRes ( (HANDLE) pTG->Inst.hfile,
lpdwOutputBuffer,
&dwUsedSizeOutputBuffer) ) {
MyDebugPrint(pTG, LOG_ERR, "ERROR: Tiff CONVERTING %d page \n", pTG->CurrentOut);
SignalHelperError(pTG);
goto l_exit;
}
}
}
else {
if (! ConvMmrPageToMh ( (HANDLE) pTG->Inst.hfile,
lpdwOutputBuffer,
&dwUsedSizeOutputBuffer,
NegotHiRes,
SrcHiRes) ) {
MyDebugPrint(pTG, LOG_ERR, "ERROR: Tiff CONVERTING %d page \n", pTG->CurrentOut);
SignalHelperError(pTG);
goto l_exit;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
//
// Signal to the Main T.30 Thread that we crashed
//
if (fOutBufferNeedsBeFreed) {
VirtualFree(lpdwOutputBuffer, 0 , MEM_RELEASE);
}
CloseHandle(OutFileHandle);
return (FALSE);
}
if ( ( ! WriteFile(OutFileHandle, (BYTE *) lpdwOutputBuffer, dwUsedSizeOutputBuffer, &dwBytesWritten, NULL) ) ||
(dwUsedSizeOutputBuffer != dwBytesWritten ) ) {
MyDebugPrint(pTG, LOG_ERR, "ERROR: Tiff writing file %s \n", OutFileName);
SignalHelperError(pTG);
goto l_exit;
}
if ( ! CloseHandle(OutFileHandle) ) {
fOutFileNeedsBeClosed = 0;
MyDebugPrint(pTG, LOG_ERR, "ERROR: Tiff writing file %s \n", OutFileName);
SignalHelperError(pTG);
goto l_exit;
}
fOutFileNeedsBeClosed = 0;
pTG->fTiffPageDone = 1;
SetEvent(pTG->FirstPageReadyTxSignal);
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: Done page %d size=%d at %ld \n", pTG->CurrentOut, dwUsedSizeOutputBuffer, GetTickCount() );
if (!pTG->FirstOut) {
pTG->FirstOut = 1;
}
pTG->LastOut++;
//
// check to see if we are done
//
if (pTG->LastOut >= pTG->TiffInfo.PageCount) {
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: Done whole document Last page %d size=%d at %ld \n", pTG->CurrentOut, dwUsedSizeOutputBuffer, GetTickCount() );
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) {
MyDebugPrint(pTG, LOG_ERR, "TIFF_TX: WaitForMultipleObjects TIMEOUT at %ld \n", GetTickCount() );
goto l_exit;
}
if (WaitResult == WAIT_FAILED) {
MyDebugPrint(pTG, LOG_ERR, "TIFF_TX: WaitForMultipleObjects FAILED le=%lx at %ld \n",
GetLastError(), GetTickCount() );
}
if (pTG->ReqTerminate) {
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: Received TERMINATE request at %ld \n", GetTickCount() );
goto good_exit;
}
else if (pTG->ReqStartNewPage) {
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: Received START NEW PAGE request at %ld \n", GetTickCount() );
pTG->AckStartNewPage = 1;
pTG->ReqStartNewPage = 0;
}
else {
MyDebugPrint(pTG, LOG_ALL, "ERROR: TIFF_TX: Received WRONG request at %ld \n", GetTickCount() );
WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, WAIT_FOR_NEXT_STRIP_TX_TIMEOUT);
if (WaitResult == WAIT_TIMEOUT) {
MyDebugPrint(pTG, LOG_ERR, "TIFF_TX: WaitForMultipleObjects TIMEOUT at %ld \n", GetTickCount() );
goto l_exit;
}
if (WaitResult == WAIT_FAILED) {
MyDebugPrint(pTG, LOG_ERR, "TIFF_TX: WaitForMultipleObjects FAILED le=%lx at %ld \n",
GetLastError(), GetTickCount() );
}
}
}
pTG->CurrentOut++;
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: Start page %d at %ld \n", pTG->CurrentOut, GetTickCount() );
} while (1);
good_exit:
if (pTG->fTiffOpenOrCreated) {
TiffClose( (HANDLE) pTG->Inst.hfile);
pTG->fTiffOpenOrCreated = 0;
}
RetCode = TRUE;
l_exit:
if (fOutFileNeedsBeClosed) {
CloseHandle(OutFileHandle);
}
if (fOutBufferNeedsBeFreed) {
VirtualFree(lpdwOutputBuffer, 0 , MEM_RELEASE);
}
pTG->AckTerminate = 1;
pTG->fOkToResetAbortReqEvent = 1;
SetEvent(pTG->ThrdAckTerminateSignal);
SetEvent(pTG->FirstPageReadyTxSignal);
MyDebugPrint(pTG, LOG_ALL, "TIFF_TX: TiffConvertThread EXITs at %ld \n", GetTickCount() );
return (RetCode);
}
VOID
SignalHelperError(
PThrdGlbl pTG
)
{
pTG->ThreadFatalError = 1;
return;
}