/*++ Copyright (c) 1996 Microsoft Corporation Module Name: t30util.c Abstract: Utilities for t30 Author: Rafael Lisitsa (RafaelL) 2-Feb-1996 Revision History: --*/ #include "prep.h" #include "glbproto.h" #include "t30gl.h" #define IDVARSTRINGSIZE (sizeof(VARSTRING)+128) #define BAD_HANDLE(h) (!(h) || (h)==INVALID_HANDLE_VALUE) /////////////////////////////////////////////////////////////////////////////////// PVOID T30AllocThreadGlobalData( VOID ) { PVOID pTG; pTG = MemAlloc (sizeof(ThrdGlbl) ); FillMemory (pTG, sizeof(ThrdGlbl), 0); return (pTG); } ///////////////////////////////////////////////////////////// BOOL itapi_async_setup(PThrdGlbl pTG) { EnterCriticalSection(&T30CritSection); if (pTG->fWaitingForEvent) { MyDebugPrint(pTG, LOG_ERR, "ERROR:Already waiting for event!\n"); } if (pTG->dwSignalledRID) { MyDebugPrint(pTG, LOG_ERR, "ERROR:Nonzero old NONZERO ID 0x%lx\n",(unsigned long) pTG->dwSignalledRID); } pTG->fWaitingForEvent=TRUE; ResetEvent(pTG->hevAsync); LeaveCriticalSection(&T30CritSection); return TRUE; } BOOL itapi_async_wait(PThrdGlbl pTG, DWORD dwRequestID, PDWORD lpdwParam2, PDWORD_PTR lpdwParam3, DWORD dwTimeout) { DWORD NumHandles=2; HANDLE HandlesArray[2]; DWORD WaitResult; if (!pTG->fWaitingForEvent) { MyDebugPrint(pTG, LOG_ERR, "ERROR:Not waiting for event!\n"); // ASSERT(FALSE); } HandlesArray[1] = pTG->AbortReqEvent; // // We want to be able to un-block ONCE only from waiting on I/O when the AbortReqEvent is signaled. // if (pTG->fAbortRequested) { if (pTG->fOkToResetAbortReqEvent && (!pTG->fAbortReqEventWasReset)) { MyDebugPrint(pTG, LOG_ALL, "itapi_async_wait RESETTING AbortReqEvent at %lx\n",GetTickCount() ); pTG->fAbortReqEventWasReset = 1; ResetEvent(pTG->AbortReqEvent); } pTG->fUnblockIO = 1; } HandlesArray[0] = pTG->hevAsync; if (pTG->fUnblockIO) { NumHandles = 1; } else { NumHandles = 2; } WaitResult = WaitForMultipleObjects(NumHandles, HandlesArray, FALSE, dwTimeout); if (WaitResult == WAIT_FAILED) { MyDebugPrint(pTG, LOG_ERR, "itapi_async_wait: WaitForMultipleObjects FAILED le=%lx at %ld \n", GetLastError(), GetTickCount() ); } if ( (NumHandles == 2) && (WaitResult == WAIT_OBJECT_0 + 1) ) { pTG->fUnblockIO = 1; MyDebugPrint(pTG, LOG_ALL, "itapi_async_wait ABORTED at %ld\n", GetTickCount() ); return FALSE; } switch( WaitResult ) { case (WAIT_OBJECT_0): { BOOL fRet=TRUE; EnterCriticalSection(&T30CritSection); if(pTG->dwSignalledRID == dwRequestID) { pTG->dwSignalledRID = 0; pTG->fWaitingForEvent = FALSE; } else { MyDebugPrint(pTG, LOG_ERR, "ERROR:Request ID mismatch. Input:0x%p; Curent:0x%p\n", dwRequestID, pTG->dwSignalledRID); fRet=FALSE; } LeaveCriticalSection(&T30CritSection); if (!fRet) goto failure; } break; case WAIT_TIMEOUT: MyDebugPrint(pTG, LOG_ERR, "ERROR:Wait timed out. RequestID=0x%p\n", dwRequestID); goto failure; default: MyDebugPrint(pTG, LOG_ERR, "ERROR:Wait returns error. GetLastError=%ld\n", (long) GetLastError()); goto failure; } if (lpdwParam2) *lpdwParam2 = pTG->dwSignalledParam2; if (lpdwParam3) *lpdwParam3 = pTG->dwSignalledParam3; return TRUE; failure: EnterCriticalSection(&T30CritSection); if(pTG->dwSignalledRID==dwRequestID) { pTG->dwSignalledRID=0; pTG->fWaitingForEvent=FALSE; } LeaveCriticalSection(&T30CritSection); return FALSE; } BOOL itapi_async_signal(PThrdGlbl pTG, DWORD dwRequestID, DWORD dwParam2, DWORD_PTR dwParam3) { BOOL fRet=FALSE; EnterCriticalSection(&T30CritSection); if (!pTG->fWaitingForEvent) { MyDebugPrint(pTG, LOG_ERR, "ERROR:Not waiting for event, ignoring ID=0x%lx \n", (unsigned long) dwRequestID); goto end; } if (pTG->dwSignalledRID) { MyDebugPrint(pTG, LOG_ERR, "ERROR:Nonzero old NONZERO ID 0x%lx. New ID=0x%lx \n", (unsigned long) pTG->dwSignalledRID, (unsigned long) dwRequestID); } pTG->dwSignalledRID=dwRequestID; pTG->dwSignalledParam2= 0; pTG->dwSignalledParam3= 0; if (!SetEvent(pTG->hevAsync)) { MyDebugPrint(pTG, LOG_ERR, "ERROR:SetEvent(0x%lx) returns failure code: %ld \n", (ULONG_PTR) pTG->hevAsync, (long) GetLastError()); fRet=FALSE; goto end; } pTG->dwSignalledParam2= dwParam2; pTG->dwSignalledParam3= dwParam3; fRet=TRUE; end: LeaveCriticalSection(&T30CritSection); return fRet; } VOID MyDebugPrint( PThrdGlbl pTG, int DbgLevel, LPSTR Format, ... ) { char buf[1024]; char c; va_list arg_ptr; int u; int i; DWORD dwWritten; if ( (DbgLevel > gT30.DbgLevel) || (! gfFilePrint) ) { return; } va_start(arg_ptr, Format); if (pTG == NULL) { wsprintf(buf, "----"); } else { wsprintf(buf, "-%02d-", pTG->DeviceId); } u = wvsprintf(&buf[4], Format, arg_ptr) + 4; // _vsnprintf(buf, sizeof(buf), Format, arg_ptr); va_end(arg_ptr); // // scramble buf // for (i=0; i> 4) & 0x0f ); } WriteFile(ghLogFile, buf, u, &dwWritten, NULL); } #define CALLPARAMS_SIZE (sizeof(LINECALLPARAMS)+512) LPLINECALLPARAMS itapi_create_linecallparams(void) { UINT cb = CALLPARAMS_SIZE; LPLINECALLPARAMS lpParams = MemAlloc(cb); if (!lpParams) goto end; _fmemset(lpParams,0, cb); lpParams->dwTotalSize= cb; lpParams->dwBearerMode = LINEBEARERMODE_PASSTHROUGH; lpParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM; // Unimodem only accepts lpParams->dwCallParamFlags = 0; lpParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID; lpParams->dwAddressID = 0; // +++ assumes addreddid 0. lpParams->dwCalledPartySize = 0; // +++ lpParams->dwCalledPartyOffset = 0; // +++ end: return lpParams; } BOOL SignalStatusChange( PThrdGlbl pTG, DWORD StatusId ) { FAX_DEV_STATUS *pFaxStatus; LPWSTR lpwCSI; // inside the FaxStatus struct. LPBYTE lpTemp; // // If Aborting OR completed then do NOT override the statusId // if ( (pTG->StatusId == FS_USER_ABORT) || (pTG->StatusId == FS_COMPLETED) ) { return (TRUE); } pTG->StatusId = StatusId; // should use HeapAlloc because FaxSvc frees it. pFaxStatus = HeapAlloc(gT30.HeapHandle , HEAP_ZERO_MEMORY, sizeof(FAX_DEV_STATUS) + 4096 ); if (!pFaxStatus) { MyDebugPrint(pTG, LOG_ERR, "ERROR: SignalStatusChange HeapAlloc failed\n"); goto failure; } pFaxStatus->SizeOfStruct = sizeof (FAX_DEV_STATUS) + 4096; pFaxStatus->StatusId = pTG->StatusId; pFaxStatus->StringId = pTG->StringId; if (pTG->StatusId == FS_RECEIVING) { pFaxStatus->PageCount = pTG->PageCount + 1; } else { pFaxStatus->PageCount = pTG->PageCount; } if (pTG->fRemoteIdAvail) { lpTemp = (LPBYTE) pFaxStatus; lpTemp += sizeof(FAX_DEV_STATUS); lpwCSI = (LPWSTR) lpTemp; wcscpy(lpwCSI, pTG->RemoteID); pFaxStatus->CSI = (LPWSTR) lpwCSI; } else { pFaxStatus->CSI = NULL; } // RSL BUGBUG pFaxStatus->CallerId = NULL; pFaxStatus->RoutingInfo = NULL; if (! PostQueuedCompletionStatus(pTG->CompletionPortHandle, sizeof (FAX_DEV_STATUS), pTG->CompletionKey, (LPOVERLAPPED) pFaxStatus) ) { MyDebugPrint(pTG, LOG_ERR, "ERROR: PostQueuedCompletionStatus failed LE=%x\n", GetLastError() ); goto failure; } MyDebugPrint(pTG, LOG_ALL, "SignalStatusChange ID=%x Page=%d \n", pTG->StatusId, pTG->PageCount); return (TRUE); failure: return (FALSE); } BOOL SignalRecoveryStatusChange( T30_RECOVERY_GLOB *Recovery ) { FAX_DEV_STATUS *pFaxStatus; // should use HeapAlloc because FaxSvc frees it. pFaxStatus = HeapAlloc(gT30.HeapHandle , HEAP_ZERO_MEMORY, sizeof(FAX_DEV_STATUS) + 4096 ); if (!pFaxStatus) { goto failure; } pFaxStatus->SizeOfStruct = sizeof (FAX_DEV_STATUS) + 4096; pFaxStatus->StatusId = FS_FATAL_ERROR; // RSL better: FS_FSP_EXCEPTION_HANDLED; pFaxStatus->StringId = 0; pFaxStatus->PageCount = 0; pFaxStatus->CSI = NULL; pFaxStatus->CallerId = NULL; pFaxStatus->RoutingInfo = NULL; if (! PostQueuedCompletionStatus(Recovery->CompletionPortHandle, sizeof (FAX_DEV_STATUS), Recovery->CompletionKey, (LPOVERLAPPED) pFaxStatus) ) { goto failure; } return (TRUE); failure: return (FALSE); } DWORD ComputeCheckSum( LPDWORD BaseAddr, DWORD NumDwords ) { DWORD RetValue = 0; DWORD i; for (i=0; i